figrecipe 0.9.0__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.

Potentially problematic release.


This version of figrecipe might be problematic. Click here for more details.

Files changed (394) hide show
  1. figrecipe-0.9.0/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
  2. figrecipe-0.9.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. figrecipe-0.9.0/.github/ISSUE_TEMPLATE/feature_request.md +33 -0
  4. figrecipe-0.9.0/.github/PULL_REQUEST_TEMPLATE.md +34 -0
  5. figrecipe-0.9.0/.github/workflows/test.yml +60 -0
  6. figrecipe-0.9.0/.gitignore +121 -0
  7. figrecipe-0.9.0/.old/README_v02.md +288 -0
  8. figrecipe-0.9.0/.pre-commit-config.yaml +25 -0
  9. figrecipe-0.9.0/CHANGELOG.md +294 -0
  10. figrecipe-0.9.0/CONTRIBUTING.md +190 -0
  11. figrecipe-0.9.0/KNOWN_ISSUES.md +15 -0
  12. figrecipe-0.9.0/LICENSE +661 -0
  13. figrecipe-0.9.0/Makefile +86 -0
  14. figrecipe-0.9.0/PKG-INFO +427 -0
  15. figrecipe-0.9.0/README.md +364 -0
  16. figrecipe-0.9.0/docs/bgm/README.md +13 -0
  17. figrecipe-0.9.0/docs/bgm/smile.mp3 +0 -0
  18. figrecipe-0.9.0/docs/figrecipe_logo.png +0 -0
  19. figrecipe-0.9.0/docs/images/editor_axis_panel.png +0 -0
  20. figrecipe-0.9.0/docs/images/editor_dark_mode.png +0 -0
  21. figrecipe-0.9.0/docs/images/editor_demo.png +0 -0
  22. figrecipe-0.9.0/docs/images/editor_download_options.png +0 -0
  23. figrecipe-0.9.0/docs/images/editor_overview.png +0 -0
  24. figrecipe-0.9.0/docs/images/gui_editor_demo.png +0 -0
  25. figrecipe-0.9.0/docs/images/plot_types/all_plot_types.png +0 -0
  26. figrecipe-0.9.0/docs/images/plot_types/category_2d_image_matrix.png +0 -0
  27. figrecipe-0.9.0/docs/images/plot_types/category_bar_categorical.png +0 -0
  28. figrecipe-0.9.0/docs/images/plot_types/category_contour_surface.png +0 -0
  29. figrecipe-0.9.0/docs/images/plot_types/category_distribution.png +0 -0
  30. figrecipe-0.9.0/docs/images/plot_types/category_line_curve.png +0 -0
  31. figrecipe-0.9.0/docs/images/plot_types/category_scatter_points.png +0 -0
  32. figrecipe-0.9.0/docs/images/plot_types/category_special.png +0 -0
  33. figrecipe-0.9.0/docs/images/plot_types/category_spectral_signal.png +0 -0
  34. figrecipe-0.9.0/docs/images/plot_types/category_vector_flow.png +0 -0
  35. figrecipe-0.9.0/docs/layout_and_cropping.md +277 -0
  36. figrecipe-0.9.0/docs/to_claude/examples/pip-project-template/.pre-commit-config.yaml +65 -0
  37. figrecipe-0.9.0/docs/to_claude/examples/pip-project-template/pyproject.toml +160 -0
  38. figrecipe-0.9.0/examples/demo_editor.py +142 -0
  39. figrecipe-0.9.0/examples/demo_editor_brackets.py +119 -0
  40. figrecipe-0.9.0/examples/demo_editor_full.py +89 -0
  41. figrecipe-0.9.0/examples/demo_editor_smart_alignment.py +113 -0
  42. figrecipe-0.9.0/examples/demo_get_signature.py +99 -0
  43. figrecipe-0.9.0/examples/demo_movie/01_enable_dark_mode.py +84 -0
  44. figrecipe-0.9.0/examples/demo_movie/02_change_color.py +119 -0
  45. figrecipe-0.9.0/examples/demo_movie/03_datatable_import.py +83 -0
  46. figrecipe-0.9.0/examples/demo_movie/04_image_drop.py +68 -0
  47. figrecipe-0.9.0/examples/demo_movie/05_panel_drag.py +96 -0
  48. figrecipe-0.9.0/examples/demo_movie/06_file_browser.py +68 -0
  49. figrecipe-0.9.0/examples/demo_movie/__init__.py +9 -0
  50. figrecipe-0.9.0/examples/demo_movie/add_narration.py +119 -0
  51. figrecipe-0.9.0/examples/demo_movie/process_all_demos.py +270 -0
  52. figrecipe-0.9.0/examples/demo_movie/run_all.py +194 -0
  53. figrecipe-0.9.0/examples/demo_plot_all.py +146 -0
  54. figrecipe-0.9.0/examples/figrecipe_demo.ipynb +849 -0
  55. figrecipe-0.9.0/examples/figrecipe_demo.pdf +0 -0
  56. figrecipe-0.9.0/outputs/notebook/before_crop.jpg +0 -0
  57. figrecipe-0.9.0/outputs/notebook/before_crop.yaml +51 -0
  58. figrecipe-0.9.0/outputs/notebook/before_crop_cropped.jpg +0 -0
  59. figrecipe-0.9.0/outputs/notebook/dark.png +0 -0
  60. figrecipe-0.9.0/outputs/notebook/dark.yaml +537 -0
  61. figrecipe-0.9.0/outputs/notebook/mm_layout.png +0 -0
  62. figrecipe-0.9.0/outputs/notebook/mm_layout.yaml +489 -0
  63. figrecipe-0.9.0/outputs/notebook/multi_panel.png +0 -0
  64. figrecipe-0.9.0/outputs/notebook/multi_panel.yaml +479 -0
  65. figrecipe-0.9.0/outputs/notebook/multi_plot.png +0 -0
  66. figrecipe-0.9.0/outputs/notebook/multi_plot.yaml +786 -0
  67. figrecipe-0.9.0/outputs/notebook/seaborn.png +0 -0
  68. figrecipe-0.9.0/outputs/notebook/seaborn.yaml +425 -0
  69. figrecipe-0.9.0/outputs/notebook/styled.png +0 -0
  70. figrecipe-0.9.0/outputs/notebook/styled.yaml +1185 -0
  71. figrecipe-0.9.0/pyproject.toml +111 -0
  72. figrecipe-0.9.0/scripts/gui_periodic.sh +42 -0
  73. figrecipe-0.9.0/scripts/restart_gui.sh +13 -0
  74. figrecipe-0.9.0/src/figrecipe/__init__.py +489 -0
  75. figrecipe-0.9.0/src/figrecipe/__main__.py +12 -0
  76. figrecipe-0.9.0/src/figrecipe/_api/__init__.py +48 -0
  77. figrecipe-0.9.0/src/figrecipe/_api/_extract.py +108 -0
  78. figrecipe-0.9.0/src/figrecipe/_api/_notebook.py +61 -0
  79. figrecipe-0.9.0/src/figrecipe/_api/_panel.py +113 -0
  80. figrecipe-0.9.0/src/figrecipe/_api/_save.py +287 -0
  81. figrecipe-0.9.0/src/figrecipe/_api/_seaborn_proxy.py +34 -0
  82. figrecipe-0.9.0/src/figrecipe/_api/_style_manager.py +153 -0
  83. figrecipe-0.9.0/src/figrecipe/_api/_subplots.py +333 -0
  84. figrecipe-0.9.0/src/figrecipe/_api/_validate.py +82 -0
  85. figrecipe-0.9.0/src/figrecipe/_cli/__init__.py +7 -0
  86. figrecipe-0.9.0/src/figrecipe/_cli/_compose.py +87 -0
  87. figrecipe-0.9.0/src/figrecipe/_cli/_convert.py +117 -0
  88. figrecipe-0.9.0/src/figrecipe/_cli/_crop.py +82 -0
  89. figrecipe-0.9.0/src/figrecipe/_cli/_edit.py +70 -0
  90. figrecipe-0.9.0/src/figrecipe/_cli/_extract.py +128 -0
  91. figrecipe-0.9.0/src/figrecipe/_cli/_fonts.py +47 -0
  92. figrecipe-0.9.0/src/figrecipe/_cli/_info.py +67 -0
  93. figrecipe-0.9.0/src/figrecipe/_cli/_main.py +58 -0
  94. figrecipe-0.9.0/src/figrecipe/_cli/_reproduce.py +79 -0
  95. figrecipe-0.9.0/src/figrecipe/_cli/_style.py +77 -0
  96. figrecipe-0.9.0/src/figrecipe/_cli/_validate.py +66 -0
  97. figrecipe-0.9.0/src/figrecipe/_cli/_version.py +50 -0
  98. figrecipe-0.9.0/src/figrecipe/_composition/__init__.py +32 -0
  99. figrecipe-0.9.0/src/figrecipe/_composition/_alignment.py +452 -0
  100. figrecipe-0.9.0/src/figrecipe/_composition/_compose.py +179 -0
  101. figrecipe-0.9.0/src/figrecipe/_composition/_import_axes.py +127 -0
  102. figrecipe-0.9.0/src/figrecipe/_composition/_visibility.py +125 -0
  103. figrecipe-0.9.0/src/figrecipe/_dev/__init__.py +31 -0
  104. figrecipe-0.9.0/src/figrecipe/_dev/_plotters.py +76 -0
  105. figrecipe-0.9.0/src/figrecipe/_dev/_run_demos.py +56 -0
  106. figrecipe-0.9.0/src/figrecipe/_dev/browser/__init__.py +69 -0
  107. figrecipe-0.9.0/src/figrecipe/_dev/browser/_audio.py +240 -0
  108. figrecipe-0.9.0/src/figrecipe/_dev/browser/_caption.py +356 -0
  109. figrecipe-0.9.0/src/figrecipe/_dev/browser/_click_effect.py +146 -0
  110. figrecipe-0.9.0/src/figrecipe/_dev/browser/_cursor.py +196 -0
  111. figrecipe-0.9.0/src/figrecipe/_dev/browser/_highlight.py +105 -0
  112. figrecipe-0.9.0/src/figrecipe/_dev/browser/_narration.py +237 -0
  113. figrecipe-0.9.0/src/figrecipe/_dev/browser/_recorder.py +446 -0
  114. figrecipe-0.9.0/src/figrecipe/_dev/browser/_utils.py +178 -0
  115. figrecipe-0.9.0/src/figrecipe/_dev/browser/_video_trim/__init__.py +152 -0
  116. figrecipe-0.9.0/src/figrecipe/_dev/browser/_video_trim/_detection.py +223 -0
  117. figrecipe-0.9.0/src/figrecipe/_dev/browser/_video_trim/_markers.py +140 -0
  118. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/__init__.py +64 -0
  119. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/_categories.py +81 -0
  120. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/_figure_creators.py +119 -0
  121. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/_helpers.py +31 -0
  122. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/_registry.py +50 -0
  123. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/bar_categorical/__init__.py +4 -0
  124. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/bar_categorical/plot_bar.py +25 -0
  125. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/bar_categorical/plot_barh.py +25 -0
  126. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/__init__.py +4 -0
  127. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_contour.py +30 -0
  128. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_contourf.py +29 -0
  129. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_tricontour.py +28 -0
  130. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_tricontourf.py +28 -0
  131. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_tripcolor.py +29 -0
  132. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/contour_surface/plot_triplot.py +25 -0
  133. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/__init__.py +4 -0
  134. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/plot_boxplot.py +24 -0
  135. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/plot_ecdf.py +24 -0
  136. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/plot_hist.py +24 -0
  137. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/plot_hist2d.py +25 -0
  138. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/distribution/plot_violinplot.py +25 -0
  139. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/__init__.py +4 -0
  140. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_hexbin.py +25 -0
  141. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_imshow.py +23 -0
  142. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_matshow.py +23 -0
  143. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_pcolor.py +29 -0
  144. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_pcolormesh.py +29 -0
  145. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/image_matrix/plot_spy.py +29 -0
  146. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/__init__.py +4 -0
  147. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_errorbar.py +28 -0
  148. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_fill.py +29 -0
  149. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_fill_between.py +30 -0
  150. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_fill_betweenx.py +28 -0
  151. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_plot.py +28 -0
  152. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_stackplot.py +29 -0
  153. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_stairs.py +27 -0
  154. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/line_curve/plot_step.py +27 -0
  155. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/scatter_points/__init__.py +4 -0
  156. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/scatter_points/plot_scatter.py +24 -0
  157. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/__init__.py +4 -0
  158. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_eventplot.py +25 -0
  159. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_loglog.py +27 -0
  160. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_pie.py +27 -0
  161. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_semilogx.py +27 -0
  162. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_semilogy.py +27 -0
  163. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/special/plot_stem.py +27 -0
  164. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/__init__.py +4 -0
  165. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_acorr.py +24 -0
  166. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_angle_spectrum.py +28 -0
  167. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_cohere.py +29 -0
  168. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_csd.py +29 -0
  169. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_magnitude_spectrum.py +28 -0
  170. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_phase_spectrum.py +28 -0
  171. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_psd.py +29 -0
  172. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_specgram.py +30 -0
  173. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/spectral_signal/plot_xcorr.py +25 -0
  174. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/vector_flow/__init__.py +4 -0
  175. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/vector_flow/plot_barbs.py +30 -0
  176. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/vector_flow/plot_quiver.py +30 -0
  177. figrecipe-0.9.0/src/figrecipe/_dev/demo_plotters/vector_flow/plot_streamplot.py +30 -0
  178. figrecipe-0.9.0/src/figrecipe/_editor/__init__.py +278 -0
  179. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/__init__.py +43 -0
  180. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_collections.py +177 -0
  181. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_elements.py +159 -0
  182. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_extract.py +402 -0
  183. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_extract_axes.py +370 -0
  184. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_extract_text.py +466 -0
  185. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_lines.py +173 -0
  186. figrecipe-0.9.0/src/figrecipe/_editor/_bbox/_transforms.py +146 -0
  187. figrecipe-0.9.0/src/figrecipe/_editor/_call_overrides.py +183 -0
  188. figrecipe-0.9.0/src/figrecipe/_editor/_datatable_plot_handlers.py +249 -0
  189. figrecipe-0.9.0/src/figrecipe/_editor/_figure_layout.py +211 -0
  190. figrecipe-0.9.0/src/figrecipe/_editor/_flask_app.py +399 -0
  191. figrecipe-0.9.0/src/figrecipe/_editor/_helpers.py +251 -0
  192. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/__init__.py +76 -0
  193. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/__init__.py +21 -0
  194. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/_collections.py +345 -0
  195. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/_images.py +68 -0
  196. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/_lines.py +107 -0
  197. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/_patches.py +163 -0
  198. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_artists/_text.py +190 -0
  199. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_colors.py +181 -0
  200. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_detect.py +194 -0
  201. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap/_restore.py +154 -0
  202. figrecipe-0.9.0/src/figrecipe/_editor/_hitmap_main.py +182 -0
  203. figrecipe-0.9.0/src/figrecipe/_editor/_overrides.py +321 -0
  204. figrecipe-0.9.0/src/figrecipe/_editor/_plot_types_registry.py +190 -0
  205. figrecipe-0.9.0/src/figrecipe/_editor/_preferences.py +135 -0
  206. figrecipe-0.9.0/src/figrecipe/_editor/_render_overrides.py +507 -0
  207. figrecipe-0.9.0/src/figrecipe/_editor/_renderer.py +244 -0
  208. figrecipe-0.9.0/src/figrecipe/_editor/_routes_annotation.py +114 -0
  209. figrecipe-0.9.0/src/figrecipe/_editor/_routes_axis.py +482 -0
  210. figrecipe-0.9.0/src/figrecipe/_editor/_routes_captions.py +130 -0
  211. figrecipe-0.9.0/src/figrecipe/_editor/_routes_composition.py +270 -0
  212. figrecipe-0.9.0/src/figrecipe/_editor/_routes_core.py +126 -0
  213. figrecipe-0.9.0/src/figrecipe/_editor/_routes_datatable.py +364 -0
  214. figrecipe-0.9.0/src/figrecipe/_editor/_routes_element.py +335 -0
  215. figrecipe-0.9.0/src/figrecipe/_editor/_routes_files.py +443 -0
  216. figrecipe-0.9.0/src/figrecipe/_editor/_routes_image.py +200 -0
  217. figrecipe-0.9.0/src/figrecipe/_editor/_routes_snapshot.py +94 -0
  218. figrecipe-0.9.0/src/figrecipe/_editor/_routes_style.py +243 -0
  219. figrecipe-0.9.0/src/figrecipe/_editor/_templates/__init__.py +190 -0
  220. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_html.py +496 -0
  221. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_html_components/__init__.py +13 -0
  222. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_html_components/_composition_toolbar.py +79 -0
  223. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_html_components/_file_browser.py +41 -0
  224. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_html_datatable.py +92 -0
  225. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/__init__.py +178 -0
  226. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_accordion.py +328 -0
  227. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_annotation_drag.py +504 -0
  228. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_api.py +228 -0
  229. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_canvas_context_menu.py +182 -0
  230. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_captions.py +231 -0
  231. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_colors.py +485 -0
  232. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_composition.py +283 -0
  233. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_core.py +493 -0
  234. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/__init__.py +59 -0
  235. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_cell_edit.py +97 -0
  236. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_clipboard.py +164 -0
  237. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_context_menu.py +221 -0
  238. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_core.py +150 -0
  239. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_editable.py +511 -0
  240. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_import.py +161 -0
  241. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_plot.py +261 -0
  242. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_selection.py +438 -0
  243. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_table.py +256 -0
  244. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_datatable/_tabs.py +354 -0
  245. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_debug_snapshot.py +186 -0
  246. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_element_editor.py +325 -0
  247. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_files.py +429 -0
  248. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_files_context_menu.py +240 -0
  249. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_hitmap.py +512 -0
  250. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_image_drop.py +428 -0
  251. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_inspector.py +315 -0
  252. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_labels.py +464 -0
  253. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_legend_drag.py +270 -0
  254. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_modals.py +226 -0
  255. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_multi_select.py +198 -0
  256. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_overlays.py +292 -0
  257. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_panel_drag.py +505 -0
  258. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_panel_drag_snapshot.py +33 -0
  259. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_panel_position.py +463 -0
  260. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_panel_resize.py +230 -0
  261. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_panel_snap.py +307 -0
  262. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_region_select.py +255 -0
  263. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_selection.py +244 -0
  264. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_sync.py +242 -0
  265. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_tabs.py +89 -0
  266. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_undo_redo.py +348 -0
  267. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_view_mode.py +107 -0
  268. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_scripts/_zoom.py +212 -0
  269. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/__init__.py +78 -0
  270. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_base.py +111 -0
  271. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_buttons.py +327 -0
  272. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_color_input.py +123 -0
  273. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_composition.py +87 -0
  274. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_controls.py +430 -0
  275. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/__init__.py +40 -0
  276. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/_editable.py +203 -0
  277. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/_panel.py +268 -0
  278. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/_table.py +479 -0
  279. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/_toolbar.py +384 -0
  280. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_datatable/_vars.py +123 -0
  281. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_dynamic_props.py +144 -0
  282. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_file_browser.py +466 -0
  283. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_forms.py +224 -0
  284. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_hitmap.py +191 -0
  285. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_inspector.py +90 -0
  286. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_labels.py +118 -0
  287. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_modals.py +127 -0
  288. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_overlays.py +130 -0
  289. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_preview.py +430 -0
  290. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_selection.py +73 -0
  291. figrecipe-0.9.0/src/figrecipe/_editor/_templates/_styles/_spinner.py +117 -0
  292. figrecipe-0.9.0/src/figrecipe/_editor/static/audio/click.mp3 +0 -0
  293. figrecipe-0.9.0/src/figrecipe/_editor/static/click.mp3 +0 -0
  294. figrecipe-0.9.0/src/figrecipe/_editor/static/icons/favicon.ico +0 -0
  295. figrecipe-0.9.0/src/figrecipe/_integrations/__init__.py +17 -0
  296. figrecipe-0.9.0/src/figrecipe/_integrations/_scitex_stats.py +298 -0
  297. figrecipe-0.9.0/src/figrecipe/_params/_DECORATION_METHODS.py +35 -0
  298. figrecipe-0.9.0/src/figrecipe/_params/_PLOTTING_METHODS.py +58 -0
  299. figrecipe-0.9.0/src/figrecipe/_params/__init__.py +9 -0
  300. figrecipe-0.9.0/src/figrecipe/_recorder.py +442 -0
  301. figrecipe-0.9.0/src/figrecipe/_recorder_utils.py +124 -0
  302. figrecipe-0.9.0/src/figrecipe/_reproducer/__init__.py +18 -0
  303. figrecipe-0.9.0/src/figrecipe/_reproducer/_core.py +509 -0
  304. figrecipe-0.9.0/src/figrecipe/_reproducer/_custom_plots.py +279 -0
  305. figrecipe-0.9.0/src/figrecipe/_reproducer/_seaborn.py +100 -0
  306. figrecipe-0.9.0/src/figrecipe/_reproducer/_violin.py +186 -0
  307. figrecipe-0.9.0/src/figrecipe/_seaborn.py +310 -0
  308. figrecipe-0.9.0/src/figrecipe/_serializer.py +227 -0
  309. figrecipe-0.9.0/src/figrecipe/_signatures/README.md +68 -0
  310. figrecipe-0.9.0/src/figrecipe/_signatures/__init__.py +17 -0
  311. figrecipe-0.9.0/src/figrecipe/_signatures/_kwargs.py +273 -0
  312. figrecipe-0.9.0/src/figrecipe/_signatures/_loader.py +243 -0
  313. figrecipe-0.9.0/src/figrecipe/_signatures/_parsing.py +147 -0
  314. figrecipe-0.9.0/src/figrecipe/_utils/__init__.py +37 -0
  315. figrecipe-0.9.0/src/figrecipe/_utils/_bundle.py +205 -0
  316. figrecipe-0.9.0/src/figrecipe/_utils/_crop.py +267 -0
  317. figrecipe-0.9.0/src/figrecipe/_utils/_diff.py +98 -0
  318. figrecipe-0.9.0/src/figrecipe/_utils/_image_diff.py +208 -0
  319. figrecipe-0.9.0/src/figrecipe/_utils/_numpy_io.py +203 -0
  320. figrecipe-0.9.0/src/figrecipe/_utils/_units.py +208 -0
  321. figrecipe-0.9.0/src/figrecipe/_validator.py +195 -0
  322. figrecipe-0.9.0/src/figrecipe/_wrappers/__init__.py +8 -0
  323. figrecipe-0.9.0/src/figrecipe/_wrappers/_axes.py +498 -0
  324. figrecipe-0.9.0/src/figrecipe/_wrappers/_axes_helpers.py +136 -0
  325. figrecipe-0.9.0/src/figrecipe/_wrappers/_axes_plots.py +418 -0
  326. figrecipe-0.9.0/src/figrecipe/_wrappers/_axes_seaborn.py +157 -0
  327. figrecipe-0.9.0/src/figrecipe/_wrappers/_caption_generator.py +218 -0
  328. figrecipe-0.9.0/src/figrecipe/_wrappers/_figure.py +511 -0
  329. figrecipe-0.9.0/src/figrecipe/_wrappers/_panel_labels.py +127 -0
  330. figrecipe-0.9.0/src/figrecipe/_wrappers/_plot_helpers.py +143 -0
  331. figrecipe-0.9.0/src/figrecipe/_wrappers/_stat_annotation.py +274 -0
  332. figrecipe-0.9.0/src/figrecipe/_wrappers/_violin_helpers.py +180 -0
  333. figrecipe-0.9.0/src/figrecipe/plt.py +11 -0
  334. figrecipe-0.9.0/src/figrecipe/pyplot.py +265 -0
  335. figrecipe-0.9.0/src/figrecipe/styles/__init__.py +51 -0
  336. figrecipe-0.9.0/src/figrecipe/styles/_dotdict.py +72 -0
  337. figrecipe-0.9.0/src/figrecipe/styles/_finalize.py +134 -0
  338. figrecipe-0.9.0/src/figrecipe/styles/_fonts.py +77 -0
  339. figrecipe-0.9.0/src/figrecipe/styles/_kwargs_converter.py +178 -0
  340. figrecipe-0.9.0/src/figrecipe/styles/_plot_styles.py +209 -0
  341. figrecipe-0.9.0/src/figrecipe/styles/_style_applier.py +278 -0
  342. figrecipe-0.9.0/src/figrecipe/styles/_style_loader.py +402 -0
  343. figrecipe-0.9.0/src/figrecipe/styles/_themes.py +151 -0
  344. figrecipe-0.9.0/src/figrecipe/styles/presets/MATPLOTLIB.yaml +95 -0
  345. figrecipe-0.9.0/src/figrecipe/styles/presets/SCITEX.yaml +188 -0
  346. figrecipe-0.9.0/tests/__init__.py +3 -0
  347. figrecipe-0.9.0/tests/editor/__init__.py +3 -0
  348. figrecipe-0.9.0/tests/editor/conftest.py +122 -0
  349. figrecipe-0.9.0/tests/editor/test_datatable_theme_aware.py +119 -0
  350. figrecipe-0.9.0/tests/editor/test_hit_detection.py +103 -0
  351. figrecipe-0.9.0/tests/editor/test_js_errors.py +106 -0
  352. figrecipe-0.9.0/tests/editor/test_overrides.py +107 -0
  353. figrecipe-0.9.0/tests/editor/test_panel_position.py +191 -0
  354. figrecipe-0.9.0/tests/editor/test_plot_types_registry.py +127 -0
  355. figrecipe-0.9.0/tests/editor/test_properties.py +101 -0
  356. figrecipe-0.9.0/tests/editor/test_restore_endpoint.py +90 -0
  357. figrecipe-0.9.0/tests/editor/test_theme.py +95 -0
  358. figrecipe-0.9.0/tests/editor/test_toolbar.py +107 -0
  359. figrecipe-0.9.0/tests/test_alignment.py +280 -0
  360. figrecipe-0.9.0/tests/test_bundle.py +237 -0
  361. figrecipe-0.9.0/tests/test_caption_generation.py +198 -0
  362. figrecipe-0.9.0/tests/test_cli.py +299 -0
  363. figrecipe-0.9.0/tests/test_composition.py +436 -0
  364. figrecipe-0.9.0/tests/test_editor_browser.py +75 -0
  365. figrecipe-0.9.0/tests/test_editor_contourf.py +252 -0
  366. figrecipe-0.9.0/tests/test_editor_dark_mode.py +251 -0
  367. figrecipe-0.9.0/tests/test_editor_datatable.py +377 -0
  368. figrecipe-0.9.0/tests/test_editor_edit_variants.py +284 -0
  369. figrecipe-0.9.0/tests/test_editor_file_browser.py +339 -0
  370. figrecipe-0.9.0/tests/test_editor_hitmap.py +300 -0
  371. figrecipe-0.9.0/tests/test_editor_image_drop.py +284 -0
  372. figrecipe-0.9.0/tests/test_editor_image_drop_formats.py +201 -0
  373. figrecipe-0.9.0/tests/test_editor_image_drop_recording.py +162 -0
  374. figrecipe-0.9.0/tests/test_editor_image_drop_url.py +162 -0
  375. figrecipe-0.9.0/tests/test_editor_layout_stability.py +312 -0
  376. figrecipe-0.9.0/tests/test_editor_new_figure.py +241 -0
  377. figrecipe-0.9.0/tests/test_editor_panel_drag.py +79 -0
  378. figrecipe-0.9.0/tests/test_editor_panel_drag_snapshot.py +79 -0
  379. figrecipe-0.9.0/tests/test_editor_panel_snap.py +174 -0
  380. figrecipe-0.9.0/tests/test_editor_pie_colors.py +226 -0
  381. figrecipe-0.9.0/tests/test_editor_preferences.py +283 -0
  382. figrecipe-0.9.0/tests/test_editor_selection_features.py +311 -0
  383. figrecipe-0.9.0/tests/test_editor_undo_redo.py +251 -0
  384. figrecipe-0.9.0/tests/test_hit_areas.py +668 -0
  385. figrecipe-0.9.0/tests/test_integration.py +438 -0
  386. figrecipe-0.9.0/tests/test_metadata_caption.py +291 -0
  387. figrecipe-0.9.0/tests/test_recorder.py +163 -0
  388. figrecipe-0.9.0/tests/test_reproducer_pie_colors.py +85 -0
  389. figrecipe-0.9.0/tests/test_roundtrip.py +271 -0
  390. figrecipe-0.9.0/tests/test_roundtrip_all_types.py +257 -0
  391. figrecipe-0.9.0/tests/test_scitex_stats_integration.py +227 -0
  392. figrecipe-0.9.0/tests/test_seaborn.py +194 -0
  393. figrecipe-0.9.0/tests/test_stat_annotation.py +192 -0
  394. figrecipe-0.9.0/tests/test_stats.py +255 -0
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug to help us improve FigRecipe
4
+ title: "[BUG] "
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear and concise description of the bug.
12
+
13
+ ## To Reproduce
14
+
15
+ Steps to reproduce the behavior:
16
+
17
+ 1. ...
18
+ 2. ...
19
+ 3. ...
20
+
21
+ ## Minimal Code Example
22
+
23
+ ```python
24
+ import figrecipe as fr
25
+
26
+ # Minimal code that reproduces the issue
27
+ ```
28
+
29
+ ## Expected Behavior
30
+
31
+ What you expected to happen.
32
+
33
+ ## Actual Behavior
34
+
35
+ What actually happened.
36
+
37
+ ## Error Traceback
38
+
39
+ ```
40
+ Paste full error traceback here (if applicable)
41
+ ```
42
+
43
+ ## Environment
44
+
45
+ - OS: [e.g., Ubuntu 22.04, Windows 11, macOS 14]
46
+ - Python version: [e.g., 3.11.5]
47
+ - FigRecipe version: [run `pip show figrecipe`]
48
+ - Matplotlib version: [run `pip show matplotlib`]
49
+
50
+ ## Additional Context
51
+
52
+ Add any other context, screenshots, or generated files here.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Documentation
4
+ url: https://github.com/ywatanabe1989/figrecipe#readme
5
+ about: Check the README for usage examples and API reference
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature for FigRecipe
4
+ title: "[FEATURE] "
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ A clear description of the problem you're trying to solve.
12
+
13
+ Example: "I'm frustrated when trying to..."
14
+
15
+ ## Proposed Solution
16
+
17
+ A clear description of what you'd like to happen.
18
+
19
+ ## Example Usage
20
+
21
+ ```python
22
+ import figrecipe as fr
23
+
24
+ # How you envision using this feature
25
+ ```
26
+
27
+ ## Alternatives Considered
28
+
29
+ Any alternative solutions or features you've considered.
30
+
31
+ ## Additional Context
32
+
33
+ Add any other context, mockups, or references here.
@@ -0,0 +1,34 @@
1
+ ## Summary
2
+
3
+ Brief description of the changes.
4
+
5
+ ## Type of Change
6
+
7
+ - [ ] Bug fix (non-breaking change that fixes an issue)
8
+ - [ ] New feature (non-breaking change that adds functionality)
9
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
10
+ - [ ] Documentation update
11
+ - [ ] Refactoring (no functional changes)
12
+
13
+ ## Related Issues
14
+
15
+ Fixes #(issue number)
16
+
17
+ ## Changes Made
18
+
19
+ -
20
+ -
21
+ -
22
+
23
+ ## Testing
24
+
25
+ - [ ] Tests pass locally (`make test`)
26
+ - [ ] Linter passes (`make lint`)
27
+ - [ ] New tests added (if applicable)
28
+
29
+ ## Checklist
30
+
31
+ - [ ] My code follows the project's code style
32
+ - [ ] I have updated the documentation (if needed)
33
+ - [ ] I have added tests that prove my fix/feature works
34
+ - [ ] All new and existing tests pass
@@ -0,0 +1,60 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install system fonts (Arial, etc.)
25
+ run: |
26
+ echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
27
+ sudo apt-get update
28
+ sudo apt-get install -y ttf-mscorefonts-installer fontconfig
29
+ sudo fc-cache -f -v
30
+ # Clear matplotlib font cache
31
+ rm -rf ~/.cache/matplotlib
32
+
33
+ - name: Install dependencies
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ pip install -e ".[all]"
37
+
38
+ - name: Install Playwright browsers
39
+ run: |
40
+ playwright install chromium
41
+
42
+ - name: Run tests
43
+ run: |
44
+ pytest tests/ -v --tb=short --ignore=tests/editor
45
+
46
+ lint:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+
51
+ - name: Set up Python
52
+ uses: actions/setup-python@v5
53
+ with:
54
+ python-version: "3.11"
55
+
56
+ - name: Install ruff
57
+ run: pip install ruff
58
+
59
+ - name: Run ruff
60
+ run: ruff check src/
@@ -0,0 +1,121 @@
1
+ # Claude Code
2
+ CLAUDE.md
3
+ .claude
4
+ docs/to_claude
5
+ REFACTORING.md
6
+ project_management/
7
+
8
+ # Byte-compiled / optimized / DLL files
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+
13
+ # C extensions
14
+ *.so
15
+
16
+ # Distribution / packaging
17
+ .Python
18
+ build/
19
+ develop-eggs/
20
+ dist/
21
+ downloads/
22
+ eggs/
23
+ .eggs/
24
+ lib/
25
+ lib64/
26
+ parts/
27
+ sdist/
28
+ var/
29
+ wheels/
30
+ *.egg-info/
31
+ .installed.cfg
32
+ *.egg
33
+
34
+ # PyInstaller
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Environments
61
+ .env
62
+ .venv
63
+ env/
64
+ venv/
65
+ ENV/
66
+ env.bak/
67
+ venv.bak/
68
+
69
+ # IDE
70
+ .idea/
71
+ .vscode/
72
+ *.swp
73
+ *.swo
74
+ *~
75
+
76
+ # OS
77
+ .DS_Store
78
+ Thumbs.db
79
+
80
+ # Project specific
81
+ outputs/
82
+ !outputs/notebook/
83
+ *.png
84
+ !docs/figrecipe_logo.png
85
+ !docs/images/*.png
86
+ !docs/images/**/*.png
87
+ !outputs/notebook/*.png
88
+ *.yaml
89
+ !.pre-commit-config.yaml
90
+ !pyproject.toml
91
+ !outputs/notebook/*.yaml
92
+ !src/figrecipe/styles/presets/*.yaml
93
+ *.npy
94
+ *.npz
95
+ *.csv
96
+ GITIGNORED/
97
+ examples/.ipynb_checkpoints/
98
+ examples/.old/
99
+ tts_cache/
100
+
101
+ # BGM files (large files excluded, except smile.mp3 for demo)
102
+ docs/bgm/*.mp3
103
+ !docs/bgm/smile.mp3
104
+
105
+ # Claude worktree symlinks
106
+ .worktree-*
107
+
108
+ # Claude worktree symlink
109
+ /feature-demo-movie
110
+ /.claude-worktree-symlinks
111
+ # Claude worktree symlink
112
+ /feature-cli
113
+ # Claude worktree symlink
114
+ /feature-datatable-direct-edit
115
+
116
+ # Example outputs (generated files)
117
+ examples/*/outputs_*/
118
+ # Claude worktree symlink
119
+ /feature-object-support
120
+ # Claude worktree symlink
121
+ /feature-editor-improvements
@@ -0,0 +1,288 @@
1
+ <!-- ---
2
+ !-- Timestamp: 2025-12-22 13:01:11
3
+ !-- Author: ywatanabe
4
+ !-- File: /home/ywatanabe/proj/figrecipe/README.md
5
+ !-- --- -->
6
+
7
+ <p align="center">
8
+ <img src="docs/figrecipe_logo.png" alt="figrecipe logo" width="200"/>
9
+ </p>
10
+
11
+ # FigRecipe
12
+
13
+ **Reproducible matplotlib figures with mm-precision layouts.**
14
+ FigRecipe is a lightweight recording & reproduction layer for matplotlib,
15
+ designed for scientific figures that must remain **editable, inspectable,
16
+ and reproducible**.
17
+
18
+ Part of **SciTeX™ – Research OS for reproducible science**
19
+ https://scitex.ai
20
+
21
+ [![PyPI version](https://badge.fury.io/py/figrecipe.svg)](https://badge.fury.io/py/figrecipe)
22
+ [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
23
+
24
+ ---
25
+
26
+ ## Why FigRecipe?
27
+
28
+ In scientific workflows, figures are often:
29
+ - hard to reproduce once scripts change,
30
+ - resized manually in pixels or inches,
31
+ - impossible to partially reuse or inspect later.
32
+
33
+ **FigRecipe solves this by recording plotting calls as a structured “recipe”**,
34
+ allowing figures to be:
35
+ - faithfully reproduced,
36
+ - partially re-rendered,
37
+ - inspected for underlying data,
38
+ - laid out in **exact millimeters** for publication.
39
+
40
+ ---
41
+
42
+ ## Key Features
43
+
44
+ - ✅ Drop-in replacement for `matplotlib.pyplot`
45
+ - ✅ Automatic recording of plotting calls
46
+ - ✅ Reproduce figures from a YAML recipe
47
+ - ✅ Extract plotted data programmatically
48
+ - ✅ Selective reproduction of specific plots
49
+ - ✅ Millimeter-based layout (journal-ready)
50
+ - ✅ Publication-quality style presets
51
+ - ✅ Dark theme support (data colors preserved)
52
+ - ✅ Seamless seaborn integration
53
+ - ✅ Crop figures to content with mm margins
54
+
55
+ ---
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install figrecipe
61
+
62
+ # Optional: for PDF export from notebooks (SVG → PDF)
63
+ sudo apt install inkscape # Linux
64
+ brew install inkscape # macOS
65
+
66
+ ```
67
+
68
+ ## Basic Usage
69
+
70
+ ### Recording & Saving
71
+
72
+ ``` python
73
+ import figrecipe as fr
74
+ import numpy as np
75
+
76
+ x = np.linspace(0, 10, 100)
77
+ y = np.sin(x)
78
+
79
+ fig, ax = fr.subplots()
80
+ ax.plot(x, y, color='red', linewidth=2, id='sine_wave')
81
+ ax.set_xlabel('Time (s)')
82
+ ax.set_ylabel('Amplitude')
83
+
84
+ # Save image + recipe
85
+ img_path, yaml_path, result = fr.save(fig, 'figure.png')
86
+ # → creates: figure.png + figure.yaml
87
+ ```
88
+
89
+ ### Reproducing a Figure
90
+
91
+ ``` python
92
+ import figrecipe as fr
93
+
94
+ fig, ax = fr.reproduce('figure.yaml')
95
+ ```
96
+
97
+ ### Extracting Plotted Data
98
+
99
+ ``` python
100
+ import figrecipe as fr
101
+
102
+ data = fr.extract_data('figure.yaml')
103
+ # {'sine_wave': {'x': array([...]), 'y': array([...])}}
104
+ ```
105
+
106
+ ### Millimeter-Based Layout (Publication-Ready)
107
+
108
+ ``` python
109
+ fig, ax = fr.subplots(
110
+ axes_width_mm=60,
111
+ axes_height_mm=40,
112
+ margin_left_mm=15,
113
+ margin_bottom_mm=12,
114
+ )
115
+ ```
116
+ This guarantees consistent sizing across editors, exports, and journals.
117
+
118
+ ### Style Presets
119
+
120
+ ``` python
121
+ fr.list_presets()
122
+ # ['MATPLOTLIB', 'SCITEX']
123
+
124
+ # Publication-quality preset (applied globally)
125
+ fr.load_style('SCITEX')
126
+ fig, ax = fr.subplots()
127
+
128
+ # Dark theme (UI-only, data colors preserved)
129
+ fr.load_style('SCITEX_DARK')
130
+ # or: fr.load_style('SCITEX', dark=True)
131
+
132
+ # Custom style
133
+ fr.load_style('/path/to/my_style.yaml')
134
+ ```
135
+
136
+ See docs/EXAMPLE_RECIPE.yaml for a full style template.
137
+
138
+ ### Recipe Format (YAML)
139
+
140
+ ``` yaml
141
+ # Timestamp: "2025-12-22 11:53:14 (ywatanabe)"
142
+ # File: ./docs/EXAMPLE_RECIPE.yaml
143
+ # MATPLOTLIB Style Preset
144
+ # =======================
145
+ # Vanilla matplotlib defaults - minimal customization.
146
+ # Use this to reset to standard matplotlib behavior.
147
+
148
+ axes:
149
+ width_mm: null # Use matplotlib default (auto)
150
+ height_mm: null # Use matplotlib default (auto)
151
+ thickness_mm: null # Use matplotlib default
152
+
153
+ margins:
154
+ left_mm: null
155
+ right_mm: null
156
+ bottom_mm: null
157
+ top_mm: null
158
+
159
+ spacing:
160
+ horizontal_mm: null
161
+ vertical_mm: null
162
+
163
+ fonts:
164
+ family: null # matplotlib default (DejaVu Sans)
165
+ axis_label_pt: null
166
+ tick_label_pt: null
167
+ title_pt: null
168
+ suptitle_pt: null
169
+ legend_pt: null
170
+ annotation_pt: null
171
+
172
+ padding:
173
+ label_pt: null
174
+ tick_pt: null
175
+ title_pt: null
176
+
177
+ lines:
178
+ trace_mm: null
179
+ errorbar_mm: null
180
+ errorbar_cap_mm: null
181
+
182
+ ticks:
183
+ length_mm: null
184
+ thickness_mm: null
185
+ direction: null
186
+ n_ticks: null
187
+
188
+ markers:
189
+ size_mm: null
190
+ scatter_mm: null
191
+ edge_width_mm: null
192
+
193
+ legend:
194
+ frameon: null # matplotlib default (True)
195
+ bg: null # matplotlib default
196
+ edgecolor: null # matplotlib default
197
+ alpha: null # matplotlib default
198
+ loc: null # matplotlib default
199
+
200
+ output:
201
+ dpi: 300
202
+ transparent: false
203
+ format: "png"
204
+
205
+ behavior:
206
+ auto_scale_axes: false
207
+ hide_top_spine: false
208
+ hide_right_spine: false
209
+ grid: false
210
+
211
+ theme:
212
+ mode: "light"
213
+ dark:
214
+ figure_bg: "#1e1e1e"
215
+ axes_bg: "#1e1e1e"
216
+ legend_bg: "#1e1e1e"
217
+ text: "#d4d4d4"
218
+ spine: "#3c3c3c"
219
+ tick: "#d4d4d4"
220
+ grid: "#3a3a3a"
221
+ light:
222
+ figure_bg: "white"
223
+ axes_bg: "white"
224
+ legend_bg: "white"
225
+ text: "black"
226
+ spine: "black"
227
+ tick: "black"
228
+ grid: "#cccccc"
229
+
230
+ # Standard matplotlib color cycle (tab10)
231
+ colors:
232
+ palette:
233
+ - [31, 119, 180] # tab:blue
234
+ - [255, 127, 14] # tab:orange
235
+ - [44, 160, 44] # tab:green
236
+ - [214, 39, 40] # tab:red
237
+ - [148, 103, 189] # tab:purple
238
+ - [140, 86, 75] # tab:brown
239
+ - [227, 119, 194] # tab:pink
240
+ - [127, 127, 127] # tab:gray
241
+ - [188, 189, 34] # tab:olive
242
+ - [23, 190, 207] # tab:cyan
243
+
244
+ # EOF
245
+ ```
246
+
247
+ The recipe is human-readable, version-controllable, and inspectable.
248
+
249
+
250
+ ### API Overview
251
+
252
+ | Function | Description |
253
+ | ----------------------------- | --------------------------------- |
254
+ | `fr.subplots()` | Create a recording-enabled figure |
255
+ | `fr.save(fig, 'fig.png')` | Save image + recipe |
256
+ | `fr.reproduce('fig.yaml')` | Reproduce figure from recipe |
257
+ | `fr.extract_data('fig.yaml')` | Extract plotted data |
258
+ | `fr.info('fig.yaml')` | Inspect recipe metadata |
259
+ | `fr.load_style()` | Load style preset (global) |
260
+ | `fr.list_presets()` | List available presets |
261
+ | `fr.crop('fig.png')` | Crop to content with mm margin |
262
+
263
+
264
+ ### Examples
265
+ - 📓 Interactive demo notebook:
266
+ examples/figrecipe_demo.ipynb
267
+
268
+ - 🌐 View on nbviewer:
269
+ https://nbviewer.org/github/ywatanabe1989/figrecipe/blob/main/examples/figrecipe_demo.ipynb
270
+
271
+ The notebook includes side-by-side comparisons of original and reproduced figures.
272
+
273
+ ## Positioning
274
+
275
+ FigRecipe is intentionally minimal.
276
+ It focuses on recording, reproduction, and layout fidelity.
277
+
278
+ Higher-level workflows (figures, tables, statistics, GUIs) are handled in:
279
+
280
+ FTS (Figure-Table-Statics Bundle) in SciTeX ecosystem (https://scitex.ai/vis/)
281
+
282
+
283
+ ## License
284
+
285
+ AGPL-3.0 See [LICENSE](LICENSE)
286
+ .
287
+
288
+ <!-- EOF -->
@@ -0,0 +1,25 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+
10
+ - repo: https://github.com/astral-sh/ruff-pre-commit
11
+ rev: v0.8.4
12
+ hooks:
13
+ - id: ruff
14
+ args: [--fix]
15
+ - id: ruff-format
16
+
17
+ - repo: local
18
+ hooks:
19
+ - id: pytest
20
+ name: pytest
21
+ entry: python -m pytest tests/ -n auto --dist loadfile -x -q --tb=short
22
+ language: system
23
+ types: [python]
24
+ pass_filenames: false
25
+ stages: [pre-commit]