scitex 2.7.0__py3-none-any.whl → 2.7.3__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.
- scitex/__init__.py +6 -2
- scitex/__version__.py +1 -1
- scitex/audio/README.md +52 -0
- scitex/audio/__init__.py +384 -0
- scitex/audio/__main__.py +129 -0
- scitex/audio/_tts.py +334 -0
- scitex/audio/engines/__init__.py +44 -0
- scitex/audio/engines/base.py +275 -0
- scitex/audio/engines/elevenlabs_engine.py +143 -0
- scitex/audio/engines/gtts_engine.py +162 -0
- scitex/audio/engines/pyttsx3_engine.py +131 -0
- scitex/audio/mcp_server.py +757 -0
- scitex/bridge/_helpers.py +1 -1
- scitex/bridge/_plt_vis.py +1 -1
- scitex/bridge/_stats_vis.py +1 -1
- scitex/dev/plt/__init__.py +272 -0
- scitex/dev/plt/plot_mpl_axhline.py +28 -0
- scitex/dev/plt/plot_mpl_axhspan.py +28 -0
- scitex/dev/plt/plot_mpl_axvline.py +28 -0
- scitex/dev/plt/plot_mpl_axvspan.py +28 -0
- scitex/dev/plt/plot_mpl_bar.py +29 -0
- scitex/dev/plt/plot_mpl_barh.py +29 -0
- scitex/dev/plt/plot_mpl_boxplot.py +28 -0
- scitex/dev/plt/plot_mpl_contour.py +31 -0
- scitex/dev/plt/plot_mpl_contourf.py +31 -0
- scitex/dev/plt/plot_mpl_errorbar.py +30 -0
- scitex/dev/plt/plot_mpl_eventplot.py +28 -0
- scitex/dev/plt/plot_mpl_fill.py +30 -0
- scitex/dev/plt/plot_mpl_fill_between.py +31 -0
- scitex/dev/plt/plot_mpl_hexbin.py +28 -0
- scitex/dev/plt/plot_mpl_hist.py +28 -0
- scitex/dev/plt/plot_mpl_hist2d.py +28 -0
- scitex/dev/plt/plot_mpl_imshow.py +29 -0
- scitex/dev/plt/plot_mpl_pcolormesh.py +31 -0
- scitex/dev/plt/plot_mpl_pie.py +29 -0
- scitex/dev/plt/plot_mpl_plot.py +29 -0
- scitex/dev/plt/plot_mpl_quiver.py +31 -0
- scitex/dev/plt/plot_mpl_scatter.py +28 -0
- scitex/dev/plt/plot_mpl_stackplot.py +31 -0
- scitex/dev/plt/plot_mpl_stem.py +29 -0
- scitex/dev/plt/plot_mpl_step.py +29 -0
- scitex/dev/plt/plot_mpl_violinplot.py +28 -0
- scitex/dev/plt/plot_sns_barplot.py +29 -0
- scitex/dev/plt/plot_sns_boxplot.py +29 -0
- scitex/dev/plt/plot_sns_heatmap.py +28 -0
- scitex/dev/plt/plot_sns_histplot.py +29 -0
- scitex/dev/plt/plot_sns_kdeplot.py +29 -0
- scitex/dev/plt/plot_sns_lineplot.py +31 -0
- scitex/dev/plt/plot_sns_scatterplot.py +29 -0
- scitex/dev/plt/plot_sns_stripplot.py +29 -0
- scitex/dev/plt/plot_sns_swarmplot.py +29 -0
- scitex/dev/plt/plot_sns_violinplot.py +29 -0
- scitex/dev/plt/plot_stx_bar.py +29 -0
- scitex/dev/plt/plot_stx_barh.py +29 -0
- scitex/dev/plt/plot_stx_box.py +28 -0
- scitex/dev/plt/plot_stx_boxplot.py +28 -0
- scitex/dev/plt/plot_stx_conf_mat.py +28 -0
- scitex/dev/plt/plot_stx_contour.py +31 -0
- scitex/dev/plt/plot_stx_ecdf.py +28 -0
- scitex/dev/plt/plot_stx_errorbar.py +30 -0
- scitex/dev/plt/plot_stx_fill_between.py +31 -0
- scitex/dev/plt/plot_stx_fillv.py +28 -0
- scitex/dev/plt/plot_stx_heatmap.py +28 -0
- scitex/dev/plt/plot_stx_image.py +28 -0
- scitex/dev/plt/plot_stx_imshow.py +28 -0
- scitex/dev/plt/plot_stx_joyplot.py +28 -0
- scitex/dev/plt/plot_stx_kde.py +28 -0
- scitex/dev/plt/plot_stx_line.py +28 -0
- scitex/dev/plt/plot_stx_mean_ci.py +28 -0
- scitex/dev/plt/plot_stx_mean_std.py +28 -0
- scitex/dev/plt/plot_stx_median_iqr.py +28 -0
- scitex/dev/plt/plot_stx_raster.py +28 -0
- scitex/dev/plt/plot_stx_rectangle.py +28 -0
- scitex/dev/plt/plot_stx_scatter.py +29 -0
- scitex/dev/plt/plot_stx_shaded_line.py +29 -0
- scitex/dev/plt/plot_stx_violin.py +28 -0
- scitex/dev/plt/plot_stx_violinplot.py +28 -0
- scitex/fig/__init__.py +352 -0
- scitex/{vis → fig}/backend/_parser.py +1 -1
- scitex/{vis → fig}/canvas.py +1 -1
- scitex/{vis → fig}/editor/_defaults.py +70 -5
- scitex/fig/editor/_edit.py +751 -0
- scitex/{vis → fig}/editor/_qt_editor.py +181 -1
- scitex/fig/editor/flask_editor/_bbox.py +1276 -0
- scitex/fig/editor/flask_editor/_core.py +624 -0
- scitex/{vis → fig}/editor/flask_editor/_plotter.py +38 -4
- scitex/fig/editor/flask_editor/_renderer.py +739 -0
- scitex/{vis → fig}/editor/flask_editor/templates/__init__.py +1 -1
- scitex/fig/editor/flask_editor/templates/_html.py +834 -0
- scitex/fig/editor/flask_editor/templates/_scripts.py +3136 -0
- scitex/{vis → fig}/editor/flask_editor/templates/_styles.py +625 -18
- scitex/{vis → fig}/io/__init__.py +13 -1
- scitex/fig/io/_bundle.py +973 -0
- scitex/{vis → fig}/io/_canvas.py +1 -1
- scitex/{vis → fig}/io/_data.py +1 -1
- scitex/{vis → fig}/io/_export.py +1 -1
- scitex/{vis → fig}/io/_load.py +1 -1
- scitex/{vis → fig}/io/_panel.py +1 -1
- scitex/{vis → fig}/io/_save.py +1 -1
- scitex/{vis → fig}/model/__init__.py +1 -1
- scitex/{vis → fig}/model/_annotations.py +1 -1
- scitex/{vis → fig}/model/_axes.py +1 -1
- scitex/{vis → fig}/model/_figure.py +1 -1
- scitex/{vis → fig}/model/_guides.py +1 -1
- scitex/{vis → fig}/model/_plot.py +1 -1
- scitex/{vis → fig}/model/_styles.py +1 -1
- scitex/{vis → fig}/utils/__init__.py +1 -1
- scitex/io/__init__.py +10 -26
- scitex/io/_bundle.py +434 -0
- scitex/io/_flush.py +5 -2
- scitex/io/_load.py +98 -0
- scitex/io/_load_modules/_H5Explorer.py +5 -2
- scitex/io/_load_modules/_canvas.py +2 -2
- scitex/io/_load_modules/_image.py +3 -4
- scitex/io/_load_modules/_txt.py +4 -2
- scitex/io/_metadata.py +34 -324
- scitex/io/_metadata_modules/__init__.py +46 -0
- scitex/io/_metadata_modules/_embed.py +70 -0
- scitex/io/_metadata_modules/_read.py +64 -0
- scitex/io/_metadata_modules/_utils.py +79 -0
- scitex/io/_metadata_modules/embed_metadata_jpeg.py +74 -0
- scitex/io/_metadata_modules/embed_metadata_pdf.py +53 -0
- scitex/io/_metadata_modules/embed_metadata_png.py +26 -0
- scitex/io/_metadata_modules/embed_metadata_svg.py +62 -0
- scitex/io/_metadata_modules/read_metadata_jpeg.py +57 -0
- scitex/io/_metadata_modules/read_metadata_pdf.py +51 -0
- scitex/io/_metadata_modules/read_metadata_png.py +39 -0
- scitex/io/_metadata_modules/read_metadata_svg.py +44 -0
- scitex/io/_qr_utils.py +5 -3
- scitex/io/_save.py +548 -30
- scitex/io/_save_modules/_canvas.py +3 -3
- scitex/io/_save_modules/_image.py +5 -9
- scitex/io/_save_modules/_tex.py +7 -4
- scitex/io/utils/h5_to_zarr.py +11 -9
- scitex/msword/__init__.py +255 -0
- scitex/msword/profiles.py +357 -0
- scitex/msword/reader.py +753 -0
- scitex/msword/utils.py +289 -0
- scitex/msword/writer.py +362 -0
- scitex/plt/__init__.py +5 -2
- scitex/plt/_subplots/_AxesWrapper.py +6 -6
- scitex/plt/_subplots/_AxisWrapper.py +15 -9
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +36 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +264 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +213 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +128 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +59 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +34 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +593 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +654 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +527 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +321 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +33 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +152 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +600 -0
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +79 -5
- scitex/plt/_subplots/_FigWrapper.py +6 -6
- scitex/plt/_subplots/_SubplotsWrapper.py +28 -18
- scitex/plt/_subplots/_export_as_csv.py +35 -5
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +8 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +10 -21
- scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +18 -7
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +28 -12
- scitex/plt/_subplots/_export_as_csv_formatters/_format_matshow.py +10 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_imshow.py +13 -1
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +12 -2
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +10 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_quiver.py +10 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +18 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +44 -36
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +14 -2
- scitex/plt/_subplots/_export_as_csv_formatters/_format_streamplot.py +11 -5
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +84 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +85 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_conf_mat.py +14 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_contour.py +54 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_ecdf.py +14 -2
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +120 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_heatmap.py +16 -6
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_image.py +29 -19
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_imshow.py +63 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_joyplot.py +22 -5
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_ci.py +18 -14
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_std.py +18 -14
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_median_iqr.py +18 -14
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_raster.py +10 -2
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +51 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter_hist.py +18 -9
- scitex/plt/ax/_plot/_stx_ecdf.py +4 -2
- scitex/plt/gallery/_generate.py +421 -14
- scitex/plt/io/__init__.py +53 -0
- scitex/plt/io/_bundle.py +490 -0
- scitex/plt/io/_layered_bundle.py +1343 -0
- scitex/plt/styles/SCITEX_STYLE.yaml +26 -0
- scitex/plt/styles/__init__.py +14 -0
- scitex/plt/styles/presets.py +78 -0
- scitex/plt/utils/__init__.py +13 -1
- scitex/plt/utils/_collect_figure_metadata.py +10 -14
- scitex/plt/utils/_configure_mpl.py +6 -18
- scitex/plt/utils/_crop.py +32 -14
- scitex/plt/utils/_csv_column_naming.py +54 -0
- scitex/plt/utils/_figure_mm.py +116 -1
- scitex/plt/utils/_hitmap.py +1643 -0
- scitex/plt/utils/metadata/__init__.py +25 -0
- scitex/plt/utils/metadata/_core.py +9 -10
- scitex/plt/utils/metadata/_dimensions.py +6 -3
- scitex/plt/utils/metadata/_editable_export.py +405 -0
- scitex/plt/utils/metadata/_geometry_extraction.py +570 -0
- scitex/schema/__init__.py +109 -16
- scitex/schema/_canvas.py +1 -1
- scitex/schema/_plot.py +1015 -0
- scitex/schema/_stats.py +2 -2
- scitex/stats/__init__.py +117 -0
- scitex/stats/io/__init__.py +29 -0
- scitex/stats/io/_bundle.py +156 -0
- scitex/tex/__init__.py +4 -0
- scitex/tex/_export.py +890 -0
- {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/METADATA +11 -1
- {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/RECORD +238 -170
- scitex/io/memo.md +0 -2827
- scitex/plt/REQUESTS.md +0 -191
- scitex/plt/_subplots/TODO.md +0 -53
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +0 -559
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +0 -1609
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +0 -447
- scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_between.json +0 -110
- scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_betweenx.json +0 -88
- scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fill_between.json +0 -103
- scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fillv.json +0 -106
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/bar.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/barh.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/boxplot.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_bar.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_barh.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_box.json +0 -83
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_boxplot.json +0 -93
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violin.json +0 -91
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violinplot.json +0 -91
- scitex/plt/templates/research-master/scitex/vis/gallery/categorical/violinplot.json +0 -91
- scitex/plt/templates/research-master/scitex/vis/gallery/contour/contour.json +0 -97
- scitex/plt/templates/research-master/scitex/vis/gallery/contour/contourf.json +0 -98
- scitex/plt/templates/research-master/scitex/vis/gallery/contour/stx_contour.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist.json +0 -101
- scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist2d.json +0 -96
- scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_ecdf.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_joyplot.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_kde.json +0 -93
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/imshow.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/matshow.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_conf_mat.json +0 -83
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_heatmap.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_image.json +0 -121
- scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_imshow.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/line/plot.json +0 -110
- scitex/plt/templates/research-master/scitex/vis/gallery/line/step.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_line.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_shaded_line.json +0 -96
- scitex/plt/templates/research-master/scitex/vis/gallery/scatter/hexbin.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/scatter/scatter.json +0 -95
- scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stem.json +0 -92
- scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stx_scatter.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/special/pie.json +0 -94
- scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_raster.json +0 -109
- scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_rectangle.json +0 -108
- scitex/plt/templates/research-master/scitex/vis/gallery/statistical/errorbar.json +0 -93
- scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_errorbar.json +0 -84
- scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_ci.json +0 -96
- scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_std.json +0 -96
- scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_median_iqr.json +0 -96
- scitex/plt/templates/research-master/scitex/vis/gallery/vector/quiver.json +0 -99
- scitex/plt/templates/research-master/scitex/vis/gallery/vector/streamplot.json +0 -100
- scitex/vis/__init__.py +0 -177
- scitex/vis/editor/_edit.py +0 -390
- scitex/vis/editor/flask_editor/_bbox.py +0 -529
- scitex/vis/editor/flask_editor/_core.py +0 -168
- scitex/vis/editor/flask_editor/_renderer.py +0 -393
- scitex/vis/editor/flask_editor/templates/_html.py +0 -513
- scitex/vis/editor/flask_editor/templates/_scripts.py +0 -1261
- /scitex/{vis → fig}/README.md +0 -0
- /scitex/{vis → fig}/backend/__init__.py +0 -0
- /scitex/{vis → fig}/backend/_export.py +0 -0
- /scitex/{vis → fig}/backend/_render.py +0 -0
- /scitex/{vis → fig}/docs/CANVAS_ARCHITECTURE.md +0 -0
- /scitex/{vis → fig}/editor/__init__.py +0 -0
- /scitex/{vis → fig}/editor/_dearpygui_editor.py +0 -0
- /scitex/{vis → fig}/editor/_flask_editor.py +0 -0
- /scitex/{vis → fig}/editor/_mpl_editor.py +0 -0
- /scitex/{vis → fig}/editor/_tkinter_editor.py +0 -0
- /scitex/{vis → fig}/editor/flask_editor/__init__.py +0 -0
- /scitex/{vis → fig}/editor/flask_editor/_utils.py +0 -0
- /scitex/{vis → fig}/io/_directory.py +0 -0
- /scitex/{vis → fig}/model/_plot_types.py +0 -0
- /scitex/{vis → fig}/utils/_defaults.py +0 -0
- /scitex/{vis → fig}/utils/_validate.py +0 -0
- {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/WHEEL +0 -0
- {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/entry_points.txt +0 -0
- {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/licenses/LICENSE +0 -0
scitex/{vis → fig}/io/_canvas.py
RENAMED
scitex/{vis → fig}/io/_data.py
RENAMED
scitex/{vis → fig}/io/_export.py
RENAMED
scitex/{vis → fig}/io/_load.py
RENAMED
scitex/{vis → fig}/io/_panel.py
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Timestamp: 2025-12-08
|
|
4
4
|
# File: ./src/scitex/vis/io/panel.py
|
|
5
5
|
"""
|
|
6
|
-
Panel operations for scitex.
|
|
6
|
+
Panel operations for scitex.fig.
|
|
7
7
|
|
|
8
8
|
Handles adding, removing, updating, and listing panels within a canvas.
|
|
9
9
|
Panels can be either 'scitex' type (full stx.plt output) or 'image' type (static image).
|
scitex/{vis → fig}/io/_save.py
RENAMED
|
@@ -119,7 +119,7 @@ def save_figure_model(
|
|
|
119
119
|
|
|
120
120
|
Examples
|
|
121
121
|
--------
|
|
122
|
-
>>> from scitex.
|
|
122
|
+
>>> from scitex.fig.model import FigureModel
|
|
123
123
|
>>> fig_model = FigureModel(width_mm=180, height_mm=120)
|
|
124
124
|
>>> save_figure_model(fig_model, "figure.json")
|
|
125
125
|
PosixPath('figure.json')
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/__init__.py
|
|
4
4
|
"""
|
|
5
|
-
JSON models for scitex.
|
|
5
|
+
JSON models for scitex.fig figure specifications.
|
|
6
6
|
|
|
7
7
|
This module provides dataclass-based models for representing
|
|
8
8
|
publication-quality figures as JSON structures.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/annotations.py
|
|
4
|
-
"""Annotation JSON model for scitex.
|
|
4
|
+
"""Annotation JSON model for scitex.fig."""
|
|
5
5
|
|
|
6
6
|
from typing import Optional, Dict, Any, Tuple
|
|
7
7
|
from dataclasses import dataclass, field, asdict
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/axes.py
|
|
4
|
-
"""Axes JSON model for scitex.
|
|
4
|
+
"""Axes JSON model for scitex.fig."""
|
|
5
5
|
|
|
6
6
|
from typing import Optional, List, Dict, Any
|
|
7
7
|
from dataclasses import dataclass, field, asdict
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/figure.py
|
|
4
|
-
"""Figure JSON model for scitex.
|
|
4
|
+
"""Figure JSON model for scitex.fig."""
|
|
5
5
|
|
|
6
6
|
from typing import Optional, List, Dict, Any
|
|
7
7
|
from dataclasses import dataclass, field, asdict
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/guides.py
|
|
4
|
-
"""Guide elements (lines, spans) JSON model for scitex.
|
|
4
|
+
"""Guide elements (lines, spans) JSON model for scitex.fig."""
|
|
5
5
|
|
|
6
6
|
from typing import Optional, List, Dict, Any
|
|
7
7
|
from dataclasses import dataclass, field, asdict
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# File: ./src/scitex/vis/model/plot.py
|
|
4
|
-
"""Plot JSON model for scitex.
|
|
4
|
+
"""Plot JSON model for scitex.fig."""
|
|
5
5
|
|
|
6
6
|
from typing import Optional, List, Dict, Any
|
|
7
7
|
from dataclasses import dataclass, field, asdict
|
scitex/io/__init__.py
CHANGED
|
@@ -13,6 +13,13 @@ __DIR__ = os.path.dirname(__FILE__)
|
|
|
13
13
|
# Import commonly used functions directly
|
|
14
14
|
from ._save import save
|
|
15
15
|
from ._load import load
|
|
16
|
+
|
|
17
|
+
# Bundle I/O for .figz, .pltz, .statsz
|
|
18
|
+
# Users should use module-specific save/load functions:
|
|
19
|
+
# - scitex.plt.save_pltz() / load_pltz()
|
|
20
|
+
# - scitex.fig.save_figz() / load_figz()
|
|
21
|
+
# - scitex.stats.save_statsz() / load_statsz()
|
|
22
|
+
# Internal bundle functions available via scitex.io._bundle for module implementations
|
|
16
23
|
from ._load_configs import load_configs
|
|
17
24
|
from ._glob import glob, parse_glob
|
|
18
25
|
from ._reload import reload
|
|
@@ -79,39 +86,16 @@ except ImportError:
|
|
|
79
86
|
has_metadata = None
|
|
80
87
|
|
|
81
88
|
__all__ = [
|
|
89
|
+
# Primary I/O
|
|
82
90
|
"save",
|
|
83
91
|
"load",
|
|
92
|
+
# Config loading
|
|
84
93
|
"load_configs",
|
|
94
|
+
# File utilities
|
|
85
95
|
"glob",
|
|
86
|
-
"parse_glob",
|
|
87
96
|
"reload",
|
|
88
97
|
"flush",
|
|
89
98
|
"cache",
|
|
90
|
-
"H5Explorer",
|
|
91
|
-
"explore_h5",
|
|
92
|
-
"has_h5_key",
|
|
93
|
-
"path",
|
|
94
|
-
"mv_to_tmp",
|
|
95
|
-
"json2md",
|
|
96
|
-
"save_image",
|
|
97
|
-
"save_text",
|
|
98
|
-
"save_mp4",
|
|
99
|
-
"save_listed_dfs_as_csv",
|
|
100
|
-
"save_listed_scalars_as_csv",
|
|
101
|
-
"save_optuna_study_as_csv_and_pngs",
|
|
102
|
-
"ZarrExplorer",
|
|
103
|
-
"explore_zarr",
|
|
104
|
-
"has_zarr_key",
|
|
105
|
-
"migrate_h5_to_zarr",
|
|
106
|
-
"migrate_h5_to_zarr_batch",
|
|
107
|
-
# Load cache control functions
|
|
108
|
-
"get_cache_info",
|
|
109
|
-
"configure_cache",
|
|
110
|
-
"clear_load_cache",
|
|
111
|
-
# Metadata functions
|
|
112
|
-
"read_metadata",
|
|
113
|
-
"embed_metadata",
|
|
114
|
-
"has_metadata",
|
|
115
99
|
]
|
|
116
100
|
|
|
117
101
|
# EOF
|
scitex/io/_bundle.py
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-12-13 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/io/_bundle.py
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
SciTeX Bundle I/O - Shared utilities for .figz, .pltz, and .statsz formats.
|
|
8
|
+
|
|
9
|
+
This module provides common bundle operations. Domain-specific logic is in:
|
|
10
|
+
- scitex.plt.io._bundle (pltz: hitmap, CSV, overview)
|
|
11
|
+
- scitex.fig.io._bundle (figz: panel composition, nested pltz)
|
|
12
|
+
- scitex.stats.io._bundle (statsz: comparison metadata)
|
|
13
|
+
|
|
14
|
+
Bundle formats:
|
|
15
|
+
.figz - Publication Figure Bundle (panels + layout)
|
|
16
|
+
.pltz - Reproducible Plot Bundle (data + spec + exports)
|
|
17
|
+
.statsz - Statistical Results Bundle (stats + metadata)
|
|
18
|
+
|
|
19
|
+
Each bundle can be:
|
|
20
|
+
- Directory form: Figure1.figz.d/
|
|
21
|
+
- ZIP archive form: Figure1.figz
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import shutil
|
|
26
|
+
import zipfile
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any, Dict, List, Optional, Union
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"is_bundle",
|
|
32
|
+
"load_bundle",
|
|
33
|
+
"save_bundle",
|
|
34
|
+
"pack_bundle",
|
|
35
|
+
"unpack_bundle",
|
|
36
|
+
"validate_bundle",
|
|
37
|
+
"validate_spec",
|
|
38
|
+
"BundleType",
|
|
39
|
+
"BundleValidationError",
|
|
40
|
+
"BUNDLE_EXTENSIONS",
|
|
41
|
+
"get_bundle_type",
|
|
42
|
+
"dir_to_zip_path",
|
|
43
|
+
"zip_to_dir_path",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
# Bundle extensions
|
|
47
|
+
BUNDLE_EXTENSIONS = (".figz", ".pltz", ".statsz")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class BundleValidationError(ValueError):
|
|
51
|
+
"""Error raised when bundle validation fails."""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class BundleType:
|
|
56
|
+
"""Bundle type constants."""
|
|
57
|
+
FIGZ = "figz"
|
|
58
|
+
PLTZ = "pltz"
|
|
59
|
+
STATSZ = "statsz"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_bundle_type(path: Union[str, Path]) -> Optional[str]:
|
|
63
|
+
"""Get bundle type from path.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
path: Path to bundle (directory or ZIP).
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Bundle type string or None if not a bundle.
|
|
70
|
+
"""
|
|
71
|
+
p = Path(path)
|
|
72
|
+
|
|
73
|
+
# Directory bundle: ends with .figz.d, .pltz.d, .statsz.d
|
|
74
|
+
if p.is_dir() and p.suffix == ".d":
|
|
75
|
+
stem = p.stem # e.g., "Figure1.figz"
|
|
76
|
+
for ext in BUNDLE_EXTENSIONS:
|
|
77
|
+
if stem.endswith(ext):
|
|
78
|
+
return ext[1:] # Remove leading dot
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
# ZIP bundle: ends with .figz, .pltz, .statsz
|
|
82
|
+
if p.suffix in BUNDLE_EXTENSIONS:
|
|
83
|
+
return p.suffix[1:] # Remove leading dot
|
|
84
|
+
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def is_bundle(path: Union[str, Path]) -> bool:
|
|
89
|
+
"""Check if path is a SciTeX bundle (directory or ZIP).
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
path: Path to check.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
True if path is a bundle.
|
|
96
|
+
"""
|
|
97
|
+
return get_bundle_type(path) is not None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def dir_to_zip_path(dir_path: Path) -> Path:
|
|
101
|
+
"""Convert directory path to ZIP path.
|
|
102
|
+
|
|
103
|
+
Example: Figure1.figz.d/ -> Figure1.figz
|
|
104
|
+
"""
|
|
105
|
+
if dir_path.suffix == ".d":
|
|
106
|
+
return dir_path.with_suffix("")
|
|
107
|
+
return dir_path
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def zip_to_dir_path(zip_path: Path) -> Path:
|
|
111
|
+
"""Convert ZIP path to directory path.
|
|
112
|
+
|
|
113
|
+
Example: Figure1.figz -> Figure1.figz.d/
|
|
114
|
+
"""
|
|
115
|
+
return Path(str(zip_path) + ".d")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def pack_bundle(
|
|
119
|
+
dir_path: Union[str, Path], output_path: Optional[Union[str, Path]] = None
|
|
120
|
+
) -> Path:
|
|
121
|
+
"""Pack a bundle directory into a ZIP archive.
|
|
122
|
+
|
|
123
|
+
The ZIP archive includes the .d directory as a top-level folder so that
|
|
124
|
+
standard unzip extracts to: fname.pltz.d/fname.csv, fname.pltz.d/fname.json, etc.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
dir_path: Path to bundle directory (e.g., Figure1.figz.d/).
|
|
128
|
+
output_path: Output ZIP path. Auto-generated if None.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Path to created ZIP archive.
|
|
132
|
+
"""
|
|
133
|
+
dir_path = Path(dir_path)
|
|
134
|
+
|
|
135
|
+
if not dir_path.is_dir():
|
|
136
|
+
raise ValueError(f"Not a directory: {dir_path}")
|
|
137
|
+
|
|
138
|
+
if output_path is None:
|
|
139
|
+
output_path = dir_to_zip_path(dir_path)
|
|
140
|
+
else:
|
|
141
|
+
output_path = Path(output_path)
|
|
142
|
+
|
|
143
|
+
# Get the directory name to use as top-level folder in ZIP
|
|
144
|
+
# e.g., "stx_line.pltz.d" for path "/path/to/stx_line.pltz.d"
|
|
145
|
+
dir_name = dir_path.name
|
|
146
|
+
|
|
147
|
+
# Create ZIP archive with directory structure preserved
|
|
148
|
+
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
149
|
+
for file_path in dir_path.rglob("*"):
|
|
150
|
+
if file_path.is_file():
|
|
151
|
+
# Include directory name in archive path
|
|
152
|
+
# e.g., "stx_line.pltz.d/stx_line.csv"
|
|
153
|
+
rel_path = file_path.relative_to(dir_path)
|
|
154
|
+
arcname = Path(dir_name) / rel_path
|
|
155
|
+
zf.write(file_path, arcname)
|
|
156
|
+
|
|
157
|
+
return output_path
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def unpack_bundle(
|
|
161
|
+
zip_path: Union[str, Path], output_path: Optional[Union[str, Path]] = None
|
|
162
|
+
) -> Path:
|
|
163
|
+
"""Unpack a bundle ZIP archive into a directory.
|
|
164
|
+
|
|
165
|
+
The ZIP archive contains a top-level .d directory, so extraction goes to
|
|
166
|
+
the parent directory. E.g., stx_line.pltz extracts to create stx_line.pltz.d/
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
zip_path: Path to bundle ZIP (e.g., Figure1.figz).
|
|
170
|
+
output_path: Output directory path. Auto-generated if None.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Path to created directory.
|
|
174
|
+
"""
|
|
175
|
+
zip_path = Path(zip_path)
|
|
176
|
+
|
|
177
|
+
if not zip_path.is_file():
|
|
178
|
+
raise ValueError(f"Not a file: {zip_path}")
|
|
179
|
+
|
|
180
|
+
# Determine extraction target
|
|
181
|
+
if output_path is None:
|
|
182
|
+
# Extract to same directory as ZIP file (ZIP contains .d folder structure)
|
|
183
|
+
extract_to = zip_path.parent
|
|
184
|
+
expected_dir = zip_to_dir_path(zip_path)
|
|
185
|
+
else:
|
|
186
|
+
output_path = Path(output_path)
|
|
187
|
+
extract_to = output_path.parent
|
|
188
|
+
expected_dir = output_path
|
|
189
|
+
|
|
190
|
+
# Extract ZIP archive (contains .d directory structure)
|
|
191
|
+
with zipfile.ZipFile(zip_path, "r") as zf:
|
|
192
|
+
zf.extractall(extract_to)
|
|
193
|
+
|
|
194
|
+
return expected_dir
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def validate_spec(
|
|
198
|
+
spec: Dict[str, Any], bundle_type: str, strict: bool = False
|
|
199
|
+
) -> List[str]:
|
|
200
|
+
"""Validate a bundle specification against its schema.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
spec: The specification dictionary to validate.
|
|
204
|
+
bundle_type: Bundle type ('figz', 'pltz', 'statsz').
|
|
205
|
+
strict: If True, raise BundleValidationError on failure.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
List of validation warning/error messages (empty if valid).
|
|
209
|
+
|
|
210
|
+
Raises:
|
|
211
|
+
BundleValidationError: If strict=True and validation fails.
|
|
212
|
+
"""
|
|
213
|
+
errors = []
|
|
214
|
+
|
|
215
|
+
# Basic schema validation
|
|
216
|
+
if "schema" not in spec:
|
|
217
|
+
errors.append("Missing required field: schema")
|
|
218
|
+
elif not isinstance(spec["schema"], dict):
|
|
219
|
+
errors.append("'schema' field must be a dictionary")
|
|
220
|
+
else:
|
|
221
|
+
schema = spec["schema"]
|
|
222
|
+
if "name" not in schema:
|
|
223
|
+
errors.append("schema.name is required")
|
|
224
|
+
if "version" not in schema:
|
|
225
|
+
errors.append("schema.version is required")
|
|
226
|
+
|
|
227
|
+
# Delegate to domain-specific validators
|
|
228
|
+
if bundle_type == BundleType.FIGZ:
|
|
229
|
+
from scitex.fig.io._bundle import validate_figz_spec
|
|
230
|
+
errors.extend(validate_figz_spec(spec))
|
|
231
|
+
elif bundle_type == BundleType.PLTZ:
|
|
232
|
+
from scitex.plt.io._bundle import validate_pltz_spec
|
|
233
|
+
errors.extend(validate_pltz_spec(spec))
|
|
234
|
+
elif bundle_type == BundleType.STATSZ:
|
|
235
|
+
from scitex.stats.io._bundle import validate_statsz_spec
|
|
236
|
+
errors.extend(validate_statsz_spec(spec))
|
|
237
|
+
else:
|
|
238
|
+
errors.append(f"Unknown bundle type: {bundle_type}")
|
|
239
|
+
|
|
240
|
+
if strict and errors:
|
|
241
|
+
raise BundleValidationError("; ".join(errors))
|
|
242
|
+
|
|
243
|
+
return errors
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def validate_bundle(
|
|
247
|
+
path: Union[str, Path], strict: bool = False
|
|
248
|
+
) -> Dict[str, Any]:
|
|
249
|
+
"""Validate a bundle and return validation results.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
path: Path to bundle (directory or ZIP).
|
|
253
|
+
strict: If True, raise BundleValidationError on failure.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
Dictionary with:
|
|
257
|
+
- 'valid': bool
|
|
258
|
+
- 'errors': list of error messages
|
|
259
|
+
- 'bundle_type': detected bundle type
|
|
260
|
+
- 'spec': parsed spec (if available)
|
|
261
|
+
|
|
262
|
+
Raises:
|
|
263
|
+
BundleValidationError: If strict=True and validation fails.
|
|
264
|
+
"""
|
|
265
|
+
result = {
|
|
266
|
+
"valid": True,
|
|
267
|
+
"errors": [],
|
|
268
|
+
"bundle_type": None,
|
|
269
|
+
"spec": None,
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
p = Path(path)
|
|
273
|
+
|
|
274
|
+
# Check bundle type
|
|
275
|
+
bundle_type = get_bundle_type(p)
|
|
276
|
+
if bundle_type is None:
|
|
277
|
+
result["valid"] = False
|
|
278
|
+
result["errors"].append(f"Not a valid bundle path: {path}")
|
|
279
|
+
if strict:
|
|
280
|
+
raise BundleValidationError(result["errors"][0])
|
|
281
|
+
return result
|
|
282
|
+
|
|
283
|
+
result["bundle_type"] = bundle_type
|
|
284
|
+
|
|
285
|
+
# Try to load and validate
|
|
286
|
+
try:
|
|
287
|
+
bundle = load_bundle(path)
|
|
288
|
+
spec = bundle.get("spec")
|
|
289
|
+
result["spec"] = spec
|
|
290
|
+
|
|
291
|
+
if spec is not None:
|
|
292
|
+
errors = validate_spec(spec, bundle_type, strict=False)
|
|
293
|
+
if errors:
|
|
294
|
+
result["valid"] = False
|
|
295
|
+
result["errors"].extend(errors)
|
|
296
|
+
else:
|
|
297
|
+
result["valid"] = False
|
|
298
|
+
result["errors"].append("Bundle has no spec")
|
|
299
|
+
|
|
300
|
+
except Exception as e:
|
|
301
|
+
result["valid"] = False
|
|
302
|
+
result["errors"].append(f"Failed to load bundle: {e}")
|
|
303
|
+
|
|
304
|
+
if strict and not result["valid"]:
|
|
305
|
+
raise BundleValidationError("; ".join(result["errors"]))
|
|
306
|
+
|
|
307
|
+
return result
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def load_bundle(path: Union[str, Path]) -> Dict[str, Any]:
|
|
311
|
+
"""Load bundle from directory or ZIP transparently.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
path: Path to bundle (directory or ZIP).
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
Bundle data as dictionary with:
|
|
318
|
+
- 'type': Bundle type ('figz', 'pltz', 'statsz')
|
|
319
|
+
- 'spec': Parsed JSON specification
|
|
320
|
+
- 'path': Original path
|
|
321
|
+
- 'is_zip': Whether loaded from ZIP
|
|
322
|
+
- Additional fields based on bundle type
|
|
323
|
+
"""
|
|
324
|
+
p = Path(path)
|
|
325
|
+
bundle_type = get_bundle_type(p)
|
|
326
|
+
|
|
327
|
+
if bundle_type is None:
|
|
328
|
+
raise ValueError(f"Not a valid bundle: {path}")
|
|
329
|
+
|
|
330
|
+
result = {
|
|
331
|
+
"type": bundle_type,
|
|
332
|
+
"path": p,
|
|
333
|
+
"is_zip": False,
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
# Handle ZIP vs directory
|
|
337
|
+
if p.is_file() and p.suffix in BUNDLE_EXTENSIONS:
|
|
338
|
+
# ZIP archive - extract to temp and load
|
|
339
|
+
result["is_zip"] = True
|
|
340
|
+
import tempfile
|
|
341
|
+
temp_dir = Path(tempfile.mkdtemp())
|
|
342
|
+
with zipfile.ZipFile(p, "r") as zf:
|
|
343
|
+
zf.extractall(temp_dir)
|
|
344
|
+
bundle_dir = temp_dir
|
|
345
|
+
else:
|
|
346
|
+
bundle_dir = p
|
|
347
|
+
|
|
348
|
+
# Delegate to domain-specific loaders
|
|
349
|
+
if bundle_type == BundleType.FIGZ:
|
|
350
|
+
from scitex.fig.io._bundle import load_figz_bundle
|
|
351
|
+
result.update(load_figz_bundle(bundle_dir))
|
|
352
|
+
elif bundle_type == BundleType.PLTZ:
|
|
353
|
+
from scitex.plt.io import load_layered_pltz_bundle
|
|
354
|
+
result.update(load_layered_pltz_bundle(bundle_dir))
|
|
355
|
+
elif bundle_type == BundleType.STATSZ:
|
|
356
|
+
from scitex.stats.io._bundle import load_statsz_bundle
|
|
357
|
+
result.update(load_statsz_bundle(bundle_dir))
|
|
358
|
+
|
|
359
|
+
return result
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def save_bundle(
|
|
363
|
+
data: Dict[str, Any],
|
|
364
|
+
path: Union[str, Path],
|
|
365
|
+
bundle_type: Optional[str] = None,
|
|
366
|
+
as_zip: bool = False,
|
|
367
|
+
) -> Path:
|
|
368
|
+
"""Save data as a bundle.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
data: Bundle data dictionary.
|
|
372
|
+
path: Output path (with or without .d suffix).
|
|
373
|
+
bundle_type: Bundle type ('figz', 'pltz', 'statsz'). Auto-detected if None.
|
|
374
|
+
as_zip: If True, save as ZIP archive.
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
Path to saved bundle.
|
|
378
|
+
"""
|
|
379
|
+
p = Path(path)
|
|
380
|
+
|
|
381
|
+
# Determine bundle type
|
|
382
|
+
if bundle_type is None:
|
|
383
|
+
bundle_type = get_bundle_type(p)
|
|
384
|
+
if bundle_type is None:
|
|
385
|
+
raise ValueError(f"Cannot determine bundle type from path: {path}")
|
|
386
|
+
|
|
387
|
+
# Determine if saving as directory or ZIP
|
|
388
|
+
if as_zip or (p.suffix in BUNDLE_EXTENSIONS and not str(p).endswith(".d")):
|
|
389
|
+
save_as_zip = True
|
|
390
|
+
if p.suffix == ".d":
|
|
391
|
+
zip_path = dir_to_zip_path(p)
|
|
392
|
+
else:
|
|
393
|
+
zip_path = p
|
|
394
|
+
dir_path = zip_to_dir_path(zip_path)
|
|
395
|
+
else:
|
|
396
|
+
save_as_zip = False
|
|
397
|
+
if not str(p).endswith(".d"):
|
|
398
|
+
dir_path = Path(str(p) + ".d")
|
|
399
|
+
else:
|
|
400
|
+
dir_path = p
|
|
401
|
+
|
|
402
|
+
# Create directory
|
|
403
|
+
dir_path.mkdir(parents=True, exist_ok=True)
|
|
404
|
+
|
|
405
|
+
# Delegate to domain-specific savers
|
|
406
|
+
if bundle_type == BundleType.FIGZ:
|
|
407
|
+
from scitex.fig.io._bundle import save_figz_bundle
|
|
408
|
+
save_figz_bundle(data, dir_path)
|
|
409
|
+
elif bundle_type == BundleType.PLTZ:
|
|
410
|
+
# Note: This path is only reached when calling save_bundle() directly
|
|
411
|
+
# The main stx.io.save() flow uses _save_pltz_bundle() which handles layered format
|
|
412
|
+
from scitex.plt.io._bundle import save_pltz_bundle
|
|
413
|
+
save_pltz_bundle(data, dir_path)
|
|
414
|
+
elif bundle_type == BundleType.STATSZ:
|
|
415
|
+
from scitex.stats.io._bundle import save_statsz_bundle
|
|
416
|
+
save_statsz_bundle(data, dir_path)
|
|
417
|
+
else:
|
|
418
|
+
raise ValueError(f"Unknown bundle type: {bundle_type}")
|
|
419
|
+
|
|
420
|
+
# Pack to ZIP if requested
|
|
421
|
+
if save_as_zip:
|
|
422
|
+
pack_bundle(dir_path, zip_path)
|
|
423
|
+
shutil.rmtree(dir_path) # Remove temp directory
|
|
424
|
+
return zip_path
|
|
425
|
+
|
|
426
|
+
return dir_path
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
# Backward compatibility aliases
|
|
430
|
+
_get_bundle_type = get_bundle_type
|
|
431
|
+
_dir_to_zip_path = dir_to_zip_path
|
|
432
|
+
_zip_to_dir_path = zip_to_dir_path
|
|
433
|
+
|
|
434
|
+
# EOF
|
scitex/io/_flush.py
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
from scitex import logging
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
def flush(sys=sys):
|
|
@@ -14,7 +17,7 @@ def flush(sys=sys):
|
|
|
14
17
|
This ensures all pending write operations are completed.
|
|
15
18
|
"""
|
|
16
19
|
if sys is None:
|
|
17
|
-
|
|
20
|
+
logger.warning("flush needs sys. Skipping.")
|
|
18
21
|
else:
|
|
19
22
|
sys.stdout.flush()
|
|
20
23
|
sys.stderr.flush()
|