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.
- figrecipe/__init__.py +161 -1030
- figrecipe/__main__.py +12 -0
- figrecipe/_api/__init__.py +48 -0
- figrecipe/_api/_extract.py +108 -0
- figrecipe/_api/_notebook.py +61 -0
- figrecipe/_api/_panel.py +113 -0
- figrecipe/_api/_save.py +287 -0
- figrecipe/_api/_seaborn_proxy.py +34 -0
- figrecipe/_api/_style_manager.py +153 -0
- figrecipe/_api/_subplots.py +333 -0
- figrecipe/_api/_validate.py +82 -0
- figrecipe/_cli/__init__.py +7 -0
- figrecipe/_cli/_compose.py +87 -0
- figrecipe/_cli/_convert.py +117 -0
- figrecipe/_cli/_crop.py +82 -0
- figrecipe/_cli/_edit.py +70 -0
- figrecipe/_cli/_extract.py +128 -0
- figrecipe/_cli/_fonts.py +47 -0
- figrecipe/_cli/_info.py +67 -0
- figrecipe/_cli/_main.py +58 -0
- figrecipe/_cli/_reproduce.py +79 -0
- figrecipe/_cli/_style.py +77 -0
- figrecipe/_cli/_validate.py +66 -0
- figrecipe/_cli/_version.py +50 -0
- figrecipe/_composition/__init__.py +32 -0
- figrecipe/_composition/_alignment.py +452 -0
- figrecipe/_composition/_compose.py +179 -0
- figrecipe/_composition/_import_axes.py +127 -0
- figrecipe/_composition/_visibility.py +125 -0
- figrecipe/_dev/__init__.py +4 -93
- figrecipe/_dev/_plotters.py +76 -0
- figrecipe/_dev/_run_demos.py +56 -0
- figrecipe/_dev/browser/__init__.py +69 -0
- figrecipe/_dev/browser/_audio.py +240 -0
- figrecipe/_dev/browser/_caption.py +356 -0
- figrecipe/_dev/browser/_click_effect.py +146 -0
- figrecipe/_dev/browser/_cursor.py +196 -0
- figrecipe/_dev/browser/_highlight.py +105 -0
- figrecipe/_dev/browser/_narration.py +237 -0
- figrecipe/_dev/browser/_recorder.py +446 -0
- figrecipe/_dev/browser/_utils.py +178 -0
- figrecipe/_dev/browser/_video_trim/__init__.py +152 -0
- figrecipe/_dev/browser/_video_trim/_detection.py +223 -0
- figrecipe/_dev/browser/_video_trim/_markers.py +140 -0
- figrecipe/_dev/demo_plotters/__init__.py +35 -166
- figrecipe/_dev/demo_plotters/_categories.py +81 -0
- figrecipe/_dev/demo_plotters/_figure_creators.py +119 -0
- figrecipe/_dev/demo_plotters/_helpers.py +31 -0
- figrecipe/_dev/demo_plotters/_registry.py +50 -0
- figrecipe/_dev/demo_plotters/bar_categorical/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/contour_surface/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/distribution/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/image_matrix/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/line_curve/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/{plot_plot.py → line_curve/plot_plot.py} +3 -2
- figrecipe/_dev/demo_plotters/scatter_points/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/special/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/{plot_pie.py → special/plot_pie.py} +5 -1
- figrecipe/_dev/demo_plotters/spectral_signal/__init__.py +4 -0
- figrecipe/_dev/demo_plotters/vector_flow/__init__.py +4 -0
- figrecipe/_editor/__init__.py +61 -13
- figrecipe/_editor/_bbox/__init__.py +43 -0
- figrecipe/_editor/_bbox/_collections.py +177 -0
- figrecipe/_editor/_bbox/_elements.py +159 -0
- figrecipe/_editor/_bbox/_extract.py +402 -0
- figrecipe/_editor/_bbox/_extract_axes.py +370 -0
- figrecipe/_editor/_bbox/_extract_text.py +466 -0
- figrecipe/_editor/_bbox/_lines.py +173 -0
- figrecipe/_editor/_bbox/_transforms.py +146 -0
- figrecipe/_editor/_call_overrides.py +183 -0
- figrecipe/_editor/_datatable_plot_handlers.py +249 -0
- figrecipe/_editor/_figure_layout.py +211 -0
- figrecipe/_editor/_flask_app.py +200 -1030
- figrecipe/_editor/_helpers.py +251 -0
- figrecipe/_editor/_hitmap/__init__.py +76 -0
- figrecipe/_editor/_hitmap/_artists/__init__.py +21 -0
- figrecipe/_editor/_hitmap/_artists/_collections.py +345 -0
- figrecipe/_editor/_hitmap/_artists/_images.py +68 -0
- figrecipe/_editor/_hitmap/_artists/_lines.py +107 -0
- figrecipe/_editor/_hitmap/_artists/_patches.py +163 -0
- figrecipe/_editor/_hitmap/_artists/_text.py +190 -0
- figrecipe/_editor/_hitmap/_colors.py +181 -0
- figrecipe/_editor/_hitmap/_detect.py +194 -0
- figrecipe/_editor/_hitmap/_restore.py +154 -0
- figrecipe/_editor/_hitmap_main.py +182 -0
- figrecipe/_editor/_overrides.py +4 -1
- figrecipe/_editor/_plot_types_registry.py +190 -0
- figrecipe/_editor/_preferences.py +135 -0
- figrecipe/_editor/_render_overrides.py +507 -0
- figrecipe/_editor/_renderer.py +81 -186
- figrecipe/_editor/_routes_annotation.py +114 -0
- figrecipe/_editor/_routes_axis.py +482 -0
- figrecipe/_editor/_routes_captions.py +130 -0
- figrecipe/_editor/_routes_composition.py +270 -0
- figrecipe/_editor/_routes_core.py +126 -0
- figrecipe/_editor/_routes_datatable.py +364 -0
- figrecipe/_editor/_routes_element.py +335 -0
- figrecipe/_editor/_routes_files.py +443 -0
- figrecipe/_editor/_routes_image.py +200 -0
- figrecipe/_editor/_routes_snapshot.py +94 -0
- figrecipe/_editor/_routes_style.py +243 -0
- figrecipe/_editor/_templates/__init__.py +116 -1
- figrecipe/_editor/_templates/_html.py +154 -64
- figrecipe/_editor/_templates/_html_components/__init__.py +13 -0
- figrecipe/_editor/_templates/_html_components/_composition_toolbar.py +79 -0
- figrecipe/_editor/_templates/_html_components/_file_browser.py +41 -0
- figrecipe/_editor/_templates/_html_datatable.py +92 -0
- figrecipe/_editor/_templates/_scripts/__init__.py +178 -0
- figrecipe/_editor/_templates/_scripts/_accordion.py +328 -0
- figrecipe/_editor/_templates/_scripts/_annotation_drag.py +504 -0
- figrecipe/_editor/_templates/_scripts/_api.py +228 -0
- figrecipe/_editor/_templates/_scripts/_canvas_context_menu.py +182 -0
- figrecipe/_editor/_templates/_scripts/_captions.py +231 -0
- figrecipe/_editor/_templates/_scripts/_colors.py +485 -0
- figrecipe/_editor/_templates/_scripts/_composition.py +283 -0
- figrecipe/_editor/_templates/_scripts/_core.py +493 -0
- figrecipe/_editor/_templates/_scripts/_datatable/__init__.py +59 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_cell_edit.py +97 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_clipboard.py +164 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_context_menu.py +221 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_core.py +150 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_editable.py +511 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_import.py +161 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_plot.py +261 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_selection.py +438 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_table.py +256 -0
- figrecipe/_editor/_templates/_scripts/_datatable/_tabs.py +354 -0
- figrecipe/_editor/_templates/_scripts/_debug_snapshot.py +186 -0
- figrecipe/_editor/_templates/_scripts/_element_editor.py +325 -0
- figrecipe/_editor/_templates/_scripts/_files.py +429 -0
- figrecipe/_editor/_templates/_scripts/_files_context_menu.py +240 -0
- figrecipe/_editor/_templates/_scripts/_hitmap.py +512 -0
- figrecipe/_editor/_templates/_scripts/_image_drop.py +428 -0
- figrecipe/_editor/_templates/_scripts/_inspector.py +315 -0
- figrecipe/_editor/_templates/_scripts/_labels.py +464 -0
- figrecipe/_editor/_templates/_scripts/_legend_drag.py +270 -0
- figrecipe/_editor/_templates/_scripts/_modals.py +226 -0
- figrecipe/_editor/_templates/_scripts/_multi_select.py +198 -0
- figrecipe/_editor/_templates/_scripts/_overlays.py +292 -0
- figrecipe/_editor/_templates/_scripts/_panel_drag.py +505 -0
- figrecipe/_editor/_templates/_scripts/_panel_drag_snapshot.py +33 -0
- figrecipe/_editor/_templates/_scripts/_panel_position.py +463 -0
- figrecipe/_editor/_templates/_scripts/_panel_resize.py +230 -0
- figrecipe/_editor/_templates/_scripts/_panel_snap.py +307 -0
- figrecipe/_editor/_templates/_scripts/_region_select.py +255 -0
- figrecipe/_editor/_templates/_scripts/_selection.py +244 -0
- figrecipe/_editor/_templates/_scripts/_sync.py +242 -0
- figrecipe/_editor/_templates/_scripts/_tabs.py +89 -0
- figrecipe/_editor/_templates/_scripts/_undo_redo.py +348 -0
- figrecipe/_editor/_templates/_scripts/_view_mode.py +107 -0
- figrecipe/_editor/_templates/_scripts/_zoom.py +212 -0
- figrecipe/_editor/_templates/_styles/__init__.py +78 -0
- figrecipe/_editor/_templates/_styles/_base.py +111 -0
- figrecipe/_editor/_templates/_styles/_buttons.py +327 -0
- figrecipe/_editor/_templates/_styles/_color_input.py +123 -0
- figrecipe/_editor/_templates/_styles/_composition.py +87 -0
- figrecipe/_editor/_templates/_styles/_controls.py +430 -0
- figrecipe/_editor/_templates/_styles/_datatable/__init__.py +40 -0
- figrecipe/_editor/_templates/_styles/_datatable/_editable.py +203 -0
- figrecipe/_editor/_templates/_styles/_datatable/_panel.py +268 -0
- figrecipe/_editor/_templates/_styles/_datatable/_table.py +479 -0
- figrecipe/_editor/_templates/_styles/_datatable/_toolbar.py +384 -0
- figrecipe/_editor/_templates/_styles/_datatable/_vars.py +123 -0
- figrecipe/_editor/_templates/_styles/_dynamic_props.py +144 -0
- figrecipe/_editor/_templates/_styles/_file_browser.py +466 -0
- figrecipe/_editor/_templates/_styles/_forms.py +224 -0
- figrecipe/_editor/_templates/_styles/_hitmap.py +191 -0
- figrecipe/_editor/_templates/_styles/_inspector.py +90 -0
- figrecipe/_editor/_templates/_styles/_labels.py +118 -0
- figrecipe/_editor/_templates/_styles/_modals.py +127 -0
- figrecipe/_editor/_templates/_styles/_overlays.py +130 -0
- figrecipe/_editor/_templates/_styles/_preview.py +430 -0
- figrecipe/_editor/_templates/_styles/_selection.py +73 -0
- figrecipe/_editor/_templates/_styles/_spinner.py +117 -0
- figrecipe/_editor/static/audio/click.mp3 +0 -0
- figrecipe/_editor/static/click.mp3 +0 -0
- figrecipe/_editor/static/icons/favicon.ico +0 -0
- figrecipe/_integrations/__init__.py +17 -0
- figrecipe/_integrations/_scitex_stats.py +298 -0
- figrecipe/_params/_DECORATION_METHODS.py +8 -0
- figrecipe/_recorder.py +63 -109
- figrecipe/_recorder_utils.py +124 -0
- figrecipe/_reproducer/__init__.py +18 -0
- figrecipe/_reproducer/_core.py +509 -0
- figrecipe/_reproducer/_custom_plots.py +279 -0
- figrecipe/_reproducer/_seaborn.py +100 -0
- figrecipe/_reproducer/_violin.py +186 -0
- figrecipe/_signatures/_kwargs.py +273 -0
- figrecipe/_signatures/_loader.py +21 -423
- figrecipe/_signatures/_parsing.py +147 -0
- figrecipe/_utils/__init__.py +3 -0
- figrecipe/_utils/_bundle.py +205 -0
- figrecipe/_wrappers/_axes.py +252 -895
- figrecipe/_wrappers/_axes_helpers.py +136 -0
- figrecipe/_wrappers/_axes_plots.py +418 -0
- figrecipe/_wrappers/_axes_seaborn.py +157 -0
- figrecipe/_wrappers/_caption_generator.py +218 -0
- figrecipe/_wrappers/_figure.py +188 -1
- figrecipe/_wrappers/_panel_labels.py +127 -0
- figrecipe/_wrappers/_plot_helpers.py +143 -0
- figrecipe/_wrappers/_stat_annotation.py +274 -0
- figrecipe/_wrappers/_violin_helpers.py +180 -0
- figrecipe/styles/__init__.py +8 -6
- figrecipe/styles/_dotdict.py +72 -0
- figrecipe/styles/_finalize.py +134 -0
- figrecipe/styles/_fonts.py +77 -0
- figrecipe/styles/_kwargs_converter.py +178 -0
- figrecipe/styles/_plot_styles.py +209 -0
- figrecipe/styles/_style_applier.py +42 -480
- figrecipe/styles/_style_loader.py +16 -192
- figrecipe/styles/_themes.py +151 -0
- figrecipe/styles/presets/MATPLOTLIB.yaml +2 -1
- figrecipe/styles/presets/SCITEX.yaml +40 -28
- figrecipe-0.9.0.dist-info/METADATA +427 -0
- figrecipe-0.9.0.dist-info/RECORD +277 -0
- figrecipe-0.9.0.dist-info/entry_points.txt +2 -0
- figrecipe/_editor/_bbox.py +0 -978
- figrecipe/_editor/_hitmap.py +0 -937
- figrecipe/_editor/_templates/_scripts.py +0 -2778
- figrecipe/_editor/_templates/_styles.py +0 -1326
- figrecipe/_reproducer.py +0 -975
- figrecipe-0.6.0.dist-info/METADATA +0 -394
- figrecipe-0.6.0.dist-info/RECORD +0 -90
- /figrecipe/_dev/demo_plotters/{plot_bar.py → bar_categorical/plot_bar.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_barh.py → bar_categorical/plot_barh.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_contour.py → contour_surface/plot_contour.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_contourf.py → contour_surface/plot_contourf.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_tricontour.py → contour_surface/plot_tricontour.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_tricontourf.py → contour_surface/plot_tricontourf.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_tripcolor.py → contour_surface/plot_tripcolor.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_triplot.py → contour_surface/plot_triplot.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_boxplot.py → distribution/plot_boxplot.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_ecdf.py → distribution/plot_ecdf.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_hist.py → distribution/plot_hist.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_hist2d.py → distribution/plot_hist2d.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_violinplot.py → distribution/plot_violinplot.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_hexbin.py → image_matrix/plot_hexbin.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_imshow.py → image_matrix/plot_imshow.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_matshow.py → image_matrix/plot_matshow.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_pcolor.py → image_matrix/plot_pcolor.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_pcolormesh.py → image_matrix/plot_pcolormesh.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_spy.py → image_matrix/plot_spy.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_errorbar.py → line_curve/plot_errorbar.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_fill.py → line_curve/plot_fill.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_fill_between.py → line_curve/plot_fill_between.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_fill_betweenx.py → line_curve/plot_fill_betweenx.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_stackplot.py → line_curve/plot_stackplot.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_stairs.py → line_curve/plot_stairs.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_step.py → line_curve/plot_step.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_scatter.py → scatter_points/plot_scatter.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_eventplot.py → special/plot_eventplot.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_loglog.py → special/plot_loglog.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_semilogx.py → special/plot_semilogx.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_semilogy.py → special/plot_semilogy.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_stem.py → special/plot_stem.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_acorr.py → spectral_signal/plot_acorr.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_angle_spectrum.py → spectral_signal/plot_angle_spectrum.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_cohere.py → spectral_signal/plot_cohere.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_csd.py → spectral_signal/plot_csd.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_magnitude_spectrum.py → spectral_signal/plot_magnitude_spectrum.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_phase_spectrum.py → spectral_signal/plot_phase_spectrum.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_psd.py → spectral_signal/plot_psd.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_specgram.py → spectral_signal/plot_specgram.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_xcorr.py → spectral_signal/plot_xcorr.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_barbs.py → vector_flow/plot_barbs.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_quiver.py → vector_flow/plot_quiver.py} +0 -0
- /figrecipe/_dev/demo_plotters/{plot_streamplot.py → vector_flow/plot_streamplot.py} +0 -0
- {figrecipe-0.6.0.dist-info → figrecipe-0.9.0.dist-info}/WHEEL +0 -0
- {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
|
+
[](https://badge.fury.io/py/figrecipe)
|
|
83
|
+
[](https://github.com/ywatanabe1989/figrecipe/actions/workflows/test.yml)
|
|
84
|
+
[](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
|
+
|  |  |  |
|
|
112
|
+
|
|
113
|
+
| Move Legend | Undo/Redo | Toggle Theme |
|
|
114
|
+
|:---:|:---:|:---:|
|
|
115
|
+
|  |  |  |
|
|
116
|
+
|
|
117
|
+
| Hover Feedback | Edit Labels | Zoom Controls |
|
|
118
|
+
|:---:|:---:|:---:|
|
|
119
|
+
|  |  |  |
|
|
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
|
+
|  |  |  |
|
|
133
|
+
|
|
134
|
+
| Bar & Categorical | Contour & Surface | 2D/Image/Matrix |
|
|
135
|
+
|:---:|:---:|:---:|
|
|
136
|
+
|  |  |  |
|
|
137
|
+
|
|
138
|
+
| Vector & Flow | Spectral & Signal | Special |
|
|
139
|
+
|:---:|:---:|:---:|
|
|
140
|
+
|  |  |  |
|
|
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
|
+
|  |  |  |
|
|
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 -->
|