scitex 2.7.3__py3-none-any.whl → 2.10.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.
- scitex/__init__.py +15 -7
- scitex/__version__.py +1 -2
- scitex/_install_guide.py +250 -0
- scitex/_optional_deps.py +206 -39
- scitex/ai/_gen_ai/_Groq.py +2 -4
- scitex/ai/_gen_ai/_OpenAI.py +5 -2
- scitex/ai/_gen_ai/_Perplexity.py +20 -6
- scitex/audio/__init__.py +24 -15
- scitex/audio/_cross_process_lock.py +139 -0
- scitex/audio/_mcp_handlers.py +256 -0
- scitex/audio/_mcp_tool_schemas.py +203 -0
- scitex/audio/engines/elevenlabs_engine.py +5 -2
- scitex/audio/mcp_server.py +98 -457
- scitex/bridge/__init__.py +30 -19
- scitex/bridge/_figrecipe.py +245 -0
- scitex/bridge/_helpers.py +2 -1
- scitex/bridge/_plt_vis.py +23 -10
- scitex/bridge/_stats_plt.py +18 -5
- scitex/bridge/_stats_vis.py +16 -2
- scitex/browser/__init__.py +84 -44
- scitex/browser/automation/__init__.py +5 -1
- scitex/browser/core/BrowserMixin.py +17 -4
- scitex/browser/core/__init__.py +11 -2
- scitex/browser/remote/CaptchaHandler.py +1 -1
- scitex/browser/remote/ZenRowsAPIClient.py +1 -1
- scitex/capture/grid.py +487 -0
- scitex/capture/mcp_handlers.py +401 -0
- scitex/capture/mcp_tool_defs.py +192 -0
- scitex/capture/mcp_tools.py +241 -0
- scitex/capture/mcp_utils.py +30 -0
- scitex/cli/convert.py +421 -0
- scitex/cli/main.py +6 -4
- scitex/datetime/__init__.py +46 -0
- scitex/datetime/_linspace.py +100 -0
- scitex/datetime/_normalize_timestamp.py +306 -0
- scitex/db/_delete_duplicates.py +4 -4
- scitex/db/_sqlite3/_delete_duplicates.py +11 -2
- scitex/dev/plt/__init__.py +61 -62
- scitex/dev/plt/demo_plotters/__init__.py +0 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axhline.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axhspan.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axvline.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axvspan.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_bar.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_barh.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_boxplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_contour.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_contourf.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_errorbar.py +30 -0
- scitex/dev/plt/demo_plotters/plot_mpl_eventplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_fill.py +30 -0
- scitex/dev/plt/demo_plotters/plot_mpl_fill_between.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hexbin.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hist.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hist2d.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_imshow.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_pcolormesh.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_pie.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_plot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_quiver.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_scatter.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_stackplot.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_stem.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_step.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_violinplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_sns_barplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_boxplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_heatmap.py +28 -0
- scitex/dev/plt/demo_plotters/plot_sns_histplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_kdeplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_lineplot.py +31 -0
- scitex/dev/plt/demo_plotters/plot_sns_scatterplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_stripplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_swarmplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_violinplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_bar.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_barh.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_box.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_boxplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_conf_mat.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_contour.py +31 -0
- scitex/dev/plt/demo_plotters/plot_stx_ecdf.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_errorbar.py +30 -0
- scitex/dev/plt/demo_plotters/plot_stx_fill_between.py +31 -0
- scitex/dev/plt/demo_plotters/plot_stx_fillv.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_heatmap.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_image.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_imshow.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_joyplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_kde.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_line.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_mean_ci.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_mean_std.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_median_iqr.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_raster.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_rectangle.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_scatter.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_shaded_line.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_violin.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_violinplot.py +28 -0
- scitex/dev/plt/mpl/get_dir_ax.py +46 -0
- scitex/dev/plt/mpl/get_signatures.py +176 -0
- scitex/dev/plt/mpl/get_signatures_details.py +522 -0
- scitex/dev/plt/plot_mpl_axhline.py +0 -0
- scitex/dev/plt/plot_mpl_axhspan.py +0 -0
- scitex/dev/plt/plot_mpl_axvline.py +0 -0
- scitex/dev/plt/plot_mpl_axvspan.py +0 -0
- scitex/dev/plt/plot_mpl_bar.py +0 -0
- scitex/dev/plt/plot_mpl_barh.py +0 -0
- scitex/dev/plt/plot_mpl_boxplot.py +0 -0
- scitex/dev/plt/plot_mpl_contour.py +0 -0
- scitex/dev/plt/plot_mpl_contourf.py +0 -0
- scitex/dev/plt/plot_mpl_errorbar.py +0 -0
- scitex/dev/plt/plot_mpl_eventplot.py +0 -0
- scitex/dev/plt/plot_mpl_fill.py +0 -0
- scitex/dev/plt/plot_mpl_fill_between.py +0 -0
- scitex/dev/plt/plot_mpl_hexbin.py +0 -0
- scitex/dev/plt/plot_mpl_hist.py +0 -0
- scitex/dev/plt/plot_mpl_hist2d.py +0 -0
- scitex/dev/plt/plot_mpl_imshow.py +0 -0
- scitex/dev/plt/plot_mpl_pcolormesh.py +0 -0
- scitex/dev/plt/plot_mpl_pie.py +0 -0
- scitex/dev/plt/plot_mpl_plot.py +0 -0
- scitex/dev/plt/plot_mpl_quiver.py +0 -0
- scitex/dev/plt/plot_mpl_scatter.py +0 -0
- scitex/dev/plt/plot_mpl_stackplot.py +0 -0
- scitex/dev/plt/plot_mpl_stem.py +0 -0
- scitex/dev/plt/plot_mpl_step.py +0 -0
- scitex/dev/plt/plot_mpl_violinplot.py +0 -0
- scitex/dev/plt/plot_sns_barplot.py +0 -0
- scitex/dev/plt/plot_sns_boxplot.py +0 -0
- scitex/dev/plt/plot_sns_heatmap.py +0 -0
- scitex/dev/plt/plot_sns_histplot.py +0 -0
- scitex/dev/plt/plot_sns_kdeplot.py +0 -0
- scitex/dev/plt/plot_sns_lineplot.py +0 -0
- scitex/dev/plt/plot_sns_scatterplot.py +0 -0
- scitex/dev/plt/plot_sns_stripplot.py +0 -0
- scitex/dev/plt/plot_sns_swarmplot.py +0 -0
- scitex/dev/plt/plot_sns_violinplot.py +0 -0
- scitex/dev/plt/plot_stx_bar.py +0 -0
- scitex/dev/plt/plot_stx_barh.py +0 -0
- scitex/dev/plt/plot_stx_box.py +0 -0
- scitex/dev/plt/plot_stx_boxplot.py +0 -0
- scitex/dev/plt/plot_stx_conf_mat.py +0 -0
- scitex/dev/plt/plot_stx_contour.py +0 -0
- scitex/dev/plt/plot_stx_ecdf.py +0 -0
- scitex/dev/plt/plot_stx_errorbar.py +0 -0
- scitex/dev/plt/plot_stx_fill_between.py +0 -0
- scitex/dev/plt/plot_stx_fillv.py +0 -0
- scitex/dev/plt/plot_stx_heatmap.py +0 -0
- scitex/dev/plt/plot_stx_image.py +0 -0
- scitex/dev/plt/plot_stx_imshow.py +0 -0
- scitex/dev/plt/plot_stx_joyplot.py +0 -0
- scitex/dev/plt/plot_stx_kde.py +0 -0
- scitex/dev/plt/plot_stx_line.py +0 -0
- scitex/dev/plt/plot_stx_mean_ci.py +0 -0
- scitex/dev/plt/plot_stx_mean_std.py +0 -0
- scitex/dev/plt/plot_stx_median_iqr.py +0 -0
- scitex/dev/plt/plot_stx_raster.py +0 -0
- scitex/dev/plt/plot_stx_rectangle.py +0 -0
- scitex/dev/plt/plot_stx_scatter.py +0 -0
- scitex/dev/plt/plot_stx_shaded_line.py +0 -0
- scitex/dev/plt/plot_stx_violin.py +0 -0
- scitex/dev/plt/plot_stx_violinplot.py +0 -0
- scitex/diagram/README.md +197 -0
- scitex/diagram/__init__.py +48 -0
- scitex/diagram/_compile.py +312 -0
- scitex/diagram/_diagram.py +355 -0
- scitex/diagram/_presets.py +173 -0
- scitex/diagram/_schema.py +182 -0
- scitex/diagram/_split.py +278 -0
- scitex/dict/_pop_keys.py +1 -7
- scitex/dsp/__init__.py +15 -10
- scitex/dsp/add_noise.py +5 -2
- scitex/dsp/example.py +35 -22
- scitex/dsp/filt.py +8 -3
- scitex/dsp/reference.py +3 -2
- scitex/dsp/utils/__init__.py +2 -1
- scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
- scitex/dt/__init__.py +39 -2
- scitex/errors.py +82 -521
- scitex/fig/__init__.py +4 -4
- scitex/fig/editor/__init__.py +5 -2
- scitex/fig/editor/_dearpygui_editor.py +1 -1
- scitex/fig/editor/_mpl_editor.py +1 -1
- scitex/fig/editor/_qt_editor.py +1 -1
- scitex/fig/editor/_tkinter_editor.py +1 -1
- scitex/fig/editor/edit/__init__.py +50 -0
- scitex/fig/editor/edit/backend_detector.py +109 -0
- scitex/fig/editor/edit/bundle_resolver.py +240 -0
- scitex/fig/editor/edit/editor_launcher.py +239 -0
- scitex/fig/editor/edit/manual_handler.py +53 -0
- scitex/fig/editor/edit/panel_loader.py +232 -0
- scitex/fig/editor/edit/path_resolver.py +67 -0
- scitex/fig/editor/flask_editor/_bbox.py +23 -0
- scitex/fig/editor/flask_editor/_core.py +908 -103
- scitex/fig/editor/flask_editor/_renderer.py +74 -0
- scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
- scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
- scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
- scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
- scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
- scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
- scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
- scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
- scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
- scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
- scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
- scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
- scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
- scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
- scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
- scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
- scitex/fig/editor/flask_editor/static/css/index.css +31 -0
- scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
- scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
- scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
- scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
- scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
- scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
- scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
- scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
- scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
- scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
- scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
- scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
- scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
- scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
- scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
- scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
- scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
- scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
- scitex/fig/editor/flask_editor/static/js/main.js +426 -0
- scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
- scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
- scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
- scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
- scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
- scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
- scitex/fig/editor/flask_editor/templates/__init__.py +95 -5
- scitex/fig/editor/flask_editor/templates/_html.py +27 -9
- scitex/fig/editor/flask_editor/templates/_scripts.py +1928 -131
- scitex/fig/editor/flask_editor/templates/_styles.py +363 -51
- scitex/fig/io/_bundle.py +104 -19
- scitex/fts/README.md +262 -0
- scitex/fts/TODO.md +66 -0
- scitex/fts/__init__.py +90 -0
- scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
- scitex/fts/_bundle/_FTS.py +657 -0
- scitex/fts/_bundle/__init__.py +38 -0
- scitex/fts/_bundle/_children.py +216 -0
- scitex/fts/_bundle/_conversion/__init__.py +15 -0
- scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
- scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
- scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
- scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
- scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
- scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
- scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
- scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
- scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
- scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
- scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
- scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
- scitex/fts/_bundle/_extractors/__init__.py +32 -0
- scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
- scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
- scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
- scitex/fts/_bundle/_loader.py +134 -0
- scitex/fts/_bundle/_mpl_helpers.py +389 -0
- scitex/fts/_bundle/_saver.py +269 -0
- scitex/fts/_bundle/_storage.py +200 -0
- scitex/fts/_bundle/_utils/__init__.py +55 -0
- scitex/fts/_bundle/_utils/_const.py +26 -0
- scitex/fts/_bundle/_utils/_errors.py +73 -0
- scitex/fts/_bundle/_utils/_generate.py +21 -0
- scitex/fts/_bundle/_utils/_types.py +76 -0
- scitex/fts/_bundle/_validation.py +434 -0
- scitex/fts/_bundle/_zipbundle.py +165 -0
- scitex/fts/_fig/__init__.py +22 -0
- scitex/fts/_fig/_backend/__init__.py +53 -0
- scitex/fts/_fig/_backend/_export.py +165 -0
- scitex/fts/_fig/_backend/_parser.py +188 -0
- scitex/fts/_fig/_backend/_render.py +538 -0
- scitex/fts/_fig/_composite.py +345 -0
- scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
- scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
- scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
- scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
- scitex/fts/_fig/_dataclasses/__init__.py +47 -0
- scitex/fts/_fig/_editor/__init__.py +14 -0
- scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
- scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
- scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
- scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
- scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
- scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
- scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
- scitex/fts/_fig/_editor/_defaults.py +300 -0
- scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
- scitex/fts/_fig/_models/_Annotations.py +115 -0
- scitex/fts/_fig/_models/_Axes.py +152 -0
- scitex/fts/_fig/_models/_Figure.py +138 -0
- scitex/fts/_fig/_models/_Guides.py +104 -0
- scitex/fts/_fig/_models/_Plot.py +123 -0
- scitex/fts/_fig/_models/_Styles.py +245 -0
- scitex/fts/_fig/_models/__init__.py +80 -0
- scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
- scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
- scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
- scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
- scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
- scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
- scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
- scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
- scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
- scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
- scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
- scitex/fts/_fig/_utils/__init__.py +129 -0
- scitex/fts/_fig/_utils/_auto_layout.py +127 -0
- scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
- scitex/fts/_fig/_utils/_const_sizes.py +48 -0
- scitex/fts/_fig/_utils/_convert_coords.py +77 -0
- scitex/fts/_fig/_utils/_get_template.py +178 -0
- scitex/fts/_fig/_utils/_normalize.py +73 -0
- scitex/fts/_fig/_utils/_plot_layout.py +397 -0
- scitex/fts/_fig/_utils/_validate.py +197 -0
- scitex/fts/_kinds/__init__.py +45 -0
- scitex/fts/_kinds/_figure/__init__.py +19 -0
- scitex/fts/_kinds/_figure/_composite.py +345 -0
- scitex/fts/_kinds/_plot/__init__.py +25 -0
- scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
- scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
- scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
- scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
- scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
- scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
- scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
- scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
- scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
- scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
- scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
- scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
- scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
- scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
- scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
- scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
- scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
- scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
- scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
- scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
- scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
- scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
- scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
- scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
- scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
- scitex/fts/_kinds/_shape/__init__.py +141 -0
- scitex/fts/_kinds/_stats/__init__.py +56 -0
- scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
- scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
- scitex/fts/_kinds/_table/__init__.py +72 -0
- scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
- scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
- scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
- scitex/fts/_kinds/_table/_latex/_export.py +279 -0
- scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
- scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
- scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
- scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
- scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
- scitex/fts/_kinds/_text/__init__.py +77 -0
- scitex/fts/_schemas/data_info.schema.json +75 -0
- scitex/fts/_schemas/encoding.schema.json +90 -0
- scitex/fts/_schemas/node.schema.json +145 -0
- scitex/fts/_schemas/render_manifest.schema.json +62 -0
- scitex/fts/_schemas/stats.schema.json +132 -0
- scitex/fts/_schemas/theme.schema.json +141 -0
- scitex/fts/_stats/__init__.py +48 -0
- scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
- scitex/fts/_stats/_dataclasses/__init__.py +48 -0
- scitex/fts/_tables/__init__.py +65 -0
- scitex/fts/_tables/_latex/__init__.py +93 -0
- scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
- scitex/fts/_tables/_latex/_editor/_app.py +725 -0
- scitex/fts/_tables/_latex/_export.py +279 -0
- scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
- scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
- scitex/fts/_tables/_latex/_table_exporter.py +362 -0
- scitex/fts/_tables/_latex/_utils.py +369 -0
- scitex/fts/_tables/_latex/_validator.py +445 -0
- scitex/gen/__init__.py +66 -25
- scitex/gen/misc.py +28 -0
- scitex/io/__init__.py +47 -20
- scitex/io/_load.py +87 -36
- scitex/io/_load_modules/__init__.py +10 -7
- scitex/io/_load_modules/_pandas.py +6 -1
- scitex/io/_save.py +299 -1556
- scitex/io/_save_modules/__init__.py +76 -19
- scitex/io/_save_modules/_figure_utils.py +90 -0
- scitex/io/_save_modules/_image_csv.py +497 -0
- scitex/io/_save_modules/_legends.py +91 -0
- scitex/io/_save_modules/_pltz_bundle.py +356 -0
- scitex/io/_save_modules/_pltz_stx.py +536 -0
- scitex/io/_save_modules/_stx_bundle.py +104 -0
- scitex/io/_save_modules/_symlink.py +96 -0
- scitex/io/_save_modules/_yaml.py +1 -1
- scitex/io/_save_modules/_zarr.py +64 -18
- scitex/io/bundle/README.md +212 -0
- scitex/io/bundle/__init__.py +110 -0
- scitex/io/{_bundle.py → bundle/_core.py} +219 -89
- scitex/io/bundle/_nested.py +713 -0
- scitex/io/bundle/_types.py +74 -0
- scitex/io/bundle/_zip.py +487 -0
- scitex/io/utils/h5_to_zarr.py +1 -1
- scitex/logging/__init__.py +108 -13
- scitex/logging/_errors.py +508 -0
- scitex/logging/_formatters.py +30 -6
- scitex/logging/_warnings.py +261 -0
- scitex/plt/__init__.py +4 -1
- scitex/plt/_figrecipe.py +236 -0
- scitex/plt/_subplots/_AxisWrapper.py +6 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
- scitex/plt/_subplots/_FigWrapper.py +15 -0
- scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
- scitex/plt/_subplots/_export_as_csv.py +11 -0
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
- scitex/plt/_subplots/_fonts.py +71 -0
- scitex/plt/_subplots/_mm_layout.py +282 -0
- scitex/plt/gallery/__init__.py +99 -2
- scitex/plt/io/_layered_bundle.py +0 -0
- scitex/plt/styles/_plot_postprocess.py +3 -1
- scitex/plt/utils/_configure_mpl.py +16 -19
- scitex/repro/_RandomStateManager.py +13 -8
- scitex/resource/__init__.py +19 -1
- scitex/resource/_utils/_get_env_info.py +13 -25
- scitex/schema/__init__.py +149 -160
- scitex/schema/_encoding.py +273 -0
- scitex/schema/_figure_elements.py +406 -0
- scitex/schema/_plot.py +0 -0
- scitex/schema/_theme.py +360 -0
- scitex/schema/_validation.py +0 -98
- scitex/scholar/__init__.py +56 -14
- scitex/scholar/auth/ScholarAuthManager.py +1 -1
- scitex/scholar/auth/__init__.py +11 -2
- scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
- scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
- scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
- scitex/scholar/config/ScholarConfig.py +1 -1
- scitex/scholar/core/Scholar.py +1 -1
- scitex/session/_decorator.py +18 -16
- scitex/session/_lifecycle.py +9 -11
- scitex/session/template.py +9 -8
- scitex/sh/test_sh.py +72 -0
- scitex/sh/test_sh_simple.py +61 -0
- scitex/stats/__init__.py +221 -97
- scitex/stats/_schema.py +21 -22
- scitex/stats/descriptive/_circular.py +212 -351
- scitex/stats/descriptive/_describe.py +81 -132
- scitex/stats/descriptive/_nan.py +205 -433
- scitex/stats/descriptive/_real.py +127 -141
- scitex/str/_format_plot_text.py +5 -5
- scitex/str/_latex.py +26 -84
- scitex/str/_latex_fallback.py +53 -47
- scitex/web/_search_pubmed.py +5 -4
- scitex/writer/tests/test_diff_between.py +451 -0
- scitex/writer/tests/test_document_section.py +311 -0
- scitex/writer/tests/test_document_workflow.py +393 -0
- scitex/writer/tests/test_writer.py +361 -0
- scitex/writer/tests/test_writer_integration.py +303 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/RECORD +479 -108
- scitex/fig/editor/_edit.py +0 -751
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
scitex/logging/_formatters.py
CHANGED
|
@@ -21,6 +21,10 @@ import sys
|
|
|
21
21
|
# SCITEX_LOG_FORMAT=debug python script.py
|
|
22
22
|
LOG_FORMAT = os.getenv("SCITEX_LOG_FORMAT", "default")
|
|
23
23
|
|
|
24
|
+
# Force color output even when stdout is not a TTY (e.g., when piping through tee)
|
|
25
|
+
# SCITEX_FORCE_COLOR=1 python script.py | tee output.log
|
|
26
|
+
FORCE_COLOR = os.getenv("SCITEX_FORCE_COLOR", "").lower() in ("1", "true", "yes")
|
|
27
|
+
|
|
24
28
|
# Available format templates
|
|
25
29
|
FORMAT_TEMPLATES = {
|
|
26
30
|
"minimal": "%(levelname)s: %(message)s",
|
|
@@ -80,6 +84,14 @@ class SciTeXConsoleFormatter(logging.Formatter):
|
|
|
80
84
|
self.indent_width = indent_width
|
|
81
85
|
|
|
82
86
|
def format(self, record):
|
|
87
|
+
# Handle leading newlines: extract and preserve them
|
|
88
|
+
msg = str(record.msg) if record.msg else ""
|
|
89
|
+
leading_newlines = ""
|
|
90
|
+
while msg.startswith("\n"):
|
|
91
|
+
leading_newlines += "\n"
|
|
92
|
+
msg = msg[1:]
|
|
93
|
+
record.msg = msg
|
|
94
|
+
|
|
83
95
|
# Apply indentation if specified in record
|
|
84
96
|
indent_level = getattr(record, "indent", 0)
|
|
85
97
|
if indent_level > 0:
|
|
@@ -89,12 +101,23 @@ class SciTeXConsoleFormatter(logging.Formatter):
|
|
|
89
101
|
# Use parent formatter to apply template
|
|
90
102
|
formatted = super().format(record)
|
|
91
103
|
|
|
92
|
-
#
|
|
104
|
+
# Handle internal newlines: each line gets the level prefix
|
|
105
|
+
if "\n" in formatted:
|
|
106
|
+
lines = formatted.split("\n")
|
|
107
|
+
# First line already has prefix from parent formatter
|
|
108
|
+
# Add prefix to each continuation line
|
|
109
|
+
prefix = f"{record.levelname}: "
|
|
110
|
+
formatted = lines[0] + "\n" + "\n".join(
|
|
111
|
+
prefix + line if line.strip() else line
|
|
112
|
+
for line in lines[1:]
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Check if we can use colors (stdout is a tty and not closed, or forced)
|
|
93
116
|
try:
|
|
94
|
-
use_colors = hasattr(sys.stdout, "isatty") and sys.stdout.isatty()
|
|
117
|
+
use_colors = FORCE_COLOR or (hasattr(sys.stdout, "isatty") and sys.stdout.isatty())
|
|
95
118
|
except ValueError:
|
|
96
119
|
# stdout/stderr is closed
|
|
97
|
-
use_colors =
|
|
120
|
+
use_colors = FORCE_COLOR
|
|
98
121
|
|
|
99
122
|
if use_colors:
|
|
100
123
|
# Check for custom color override
|
|
@@ -103,15 +126,15 @@ class SciTeXConsoleFormatter(logging.Formatter):
|
|
|
103
126
|
if custom_color and custom_color in self.COLOR_NAMES:
|
|
104
127
|
# Use custom color
|
|
105
128
|
color = self.COLOR_NAMES[custom_color]
|
|
106
|
-
return f"{color}{formatted}{self.RESET}"
|
|
129
|
+
return f"{leading_newlines}{color}{formatted}{self.RESET}"
|
|
107
130
|
else:
|
|
108
131
|
# Use default color for log level
|
|
109
132
|
levelname = record.levelname
|
|
110
133
|
if levelname in self.COLORS:
|
|
111
134
|
color = self.COLORS[levelname]
|
|
112
|
-
return f"{color}{formatted}{self.RESET}"
|
|
135
|
+
return f"{leading_newlines}{color}{formatted}{self.RESET}"
|
|
113
136
|
|
|
114
|
-
return formatted
|
|
137
|
+
return f"{leading_newlines}{formatted}"
|
|
115
138
|
|
|
116
139
|
|
|
117
140
|
class SciTeXFileFormatter(logging.Formatter):
|
|
@@ -129,6 +152,7 @@ __all__ = [
|
|
|
129
152
|
"SciTeXFileFormatter",
|
|
130
153
|
"LOG_FORMAT",
|
|
131
154
|
"FORMAT_TEMPLATES",
|
|
155
|
+
"FORCE_COLOR",
|
|
132
156
|
]
|
|
133
157
|
|
|
134
158
|
# EOF
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-12-21"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/logging/_warnings.py
|
|
5
|
+
|
|
6
|
+
"""Warning system for SciTeX, mimicking Python's warnings module.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
import scitex.logging as logging
|
|
10
|
+
from scitex.logging import UnitWarning
|
|
11
|
+
|
|
12
|
+
# Emit a warning
|
|
13
|
+
logging.warn("Missing units on axis label", UnitWarning)
|
|
14
|
+
|
|
15
|
+
# Filter warnings (like warnings.filterwarnings)
|
|
16
|
+
logging.filterwarnings("ignore", category=UnitWarning)
|
|
17
|
+
logging.filterwarnings("error", category=UnitWarning) # Raise as exception
|
|
18
|
+
logging.filterwarnings("always", category=UnitWarning) # Always show
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import logging as _logging
|
|
22
|
+
from typing import Dict, Optional, Type, Set
|
|
23
|
+
|
|
24
|
+
# =============================================================================
|
|
25
|
+
# Warning Categories (similar to Python's warning classes)
|
|
26
|
+
# =============================================================================
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SciTeXWarning(UserWarning):
|
|
30
|
+
"""Base warning class for all SciTeX warnings."""
|
|
31
|
+
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UnitWarning(SciTeXWarning):
|
|
36
|
+
"""Warning for axis label unit issues (educational for SI conventions).
|
|
37
|
+
|
|
38
|
+
Raised when:
|
|
39
|
+
- Axis labels are missing units
|
|
40
|
+
- Units use parentheses instead of brackets (SI prefers [])
|
|
41
|
+
- Units use division instead of negative exponents (m/s vs m·s⁻¹)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class StyleWarning(SciTeXWarning):
|
|
48
|
+
"""Warning for style/formatting issues."""
|
|
49
|
+
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class SciTeXDeprecationWarning(SciTeXWarning):
|
|
54
|
+
"""Warning for deprecated SciTeX features."""
|
|
55
|
+
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PerformanceWarning(SciTeXWarning):
|
|
60
|
+
"""Warning for performance issues."""
|
|
61
|
+
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class DataLossWarning(SciTeXWarning):
|
|
66
|
+
"""Warning for potential data loss."""
|
|
67
|
+
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# =============================================================================
|
|
72
|
+
# Warning Filter Registry
|
|
73
|
+
# =============================================================================
|
|
74
|
+
|
|
75
|
+
# Actions: "ignore", "error", "always", "default", "once", "module"
|
|
76
|
+
_filters: Dict[Type[SciTeXWarning], str] = {}
|
|
77
|
+
_seen_warnings: Set[str] = set() # For "once" action
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def filterwarnings(
|
|
81
|
+
action: str,
|
|
82
|
+
category: Type[SciTeXWarning] = SciTeXWarning,
|
|
83
|
+
message: Optional[str] = None,
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Control warning behavior (like warnings.filterwarnings).
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
action : str
|
|
90
|
+
One of:
|
|
91
|
+
- "ignore": Never show this warning
|
|
92
|
+
- "error": Raise as exception
|
|
93
|
+
- "always": Always show
|
|
94
|
+
- "default": Show first occurrence per location
|
|
95
|
+
- "once": Show only once total
|
|
96
|
+
- "module": Show once per module
|
|
97
|
+
category : type
|
|
98
|
+
Warning category (default: SciTeXWarning = all)
|
|
99
|
+
message : str, optional
|
|
100
|
+
Regex pattern to match warning message (not implemented yet)
|
|
101
|
+
|
|
102
|
+
Examples
|
|
103
|
+
--------
|
|
104
|
+
>>> import scitex.logging as logging
|
|
105
|
+
>>> from scitex.logging import UnitWarning
|
|
106
|
+
>>> logging.filterwarnings("ignore", category=UnitWarning)
|
|
107
|
+
"""
|
|
108
|
+
valid_actions = {"ignore", "error", "always", "default", "once", "module"}
|
|
109
|
+
if action not in valid_actions:
|
|
110
|
+
raise ValueError(f"Invalid action '{action}'. Must be one of: {valid_actions}")
|
|
111
|
+
|
|
112
|
+
_filters[category] = action
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def resetwarnings() -> None:
|
|
116
|
+
"""Reset all warning filters to default behavior."""
|
|
117
|
+
global _filters, _seen_warnings
|
|
118
|
+
_filters = {}
|
|
119
|
+
_seen_warnings = set()
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _get_action(category: Type[SciTeXWarning]) -> str:
|
|
123
|
+
"""Get the action for a warning category, checking inheritance."""
|
|
124
|
+
# Check exact match first
|
|
125
|
+
if category in _filters:
|
|
126
|
+
return _filters[category]
|
|
127
|
+
|
|
128
|
+
# Check parent classes
|
|
129
|
+
for filter_cat, action in _filters.items():
|
|
130
|
+
if issubclass(category, filter_cat):
|
|
131
|
+
return action
|
|
132
|
+
|
|
133
|
+
# Default action
|
|
134
|
+
return "default"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# =============================================================================
|
|
138
|
+
# Warning Emission
|
|
139
|
+
# =============================================================================
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def warn(
|
|
143
|
+
message: str,
|
|
144
|
+
category: Type[SciTeXWarning] = SciTeXWarning,
|
|
145
|
+
stacklevel: int = 2,
|
|
146
|
+
) -> None:
|
|
147
|
+
"""Emit a warning (like warnings.warn but integrated with scitex.logging).
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
message : str
|
|
152
|
+
Warning message
|
|
153
|
+
category : type
|
|
154
|
+
Warning category (default: SciTeXWarning)
|
|
155
|
+
stacklevel : int
|
|
156
|
+
Stack level for source location (default: 2 = caller)
|
|
157
|
+
|
|
158
|
+
Examples
|
|
159
|
+
--------
|
|
160
|
+
>>> import scitex.logging as logging
|
|
161
|
+
>>> from scitex.logging import UnitWarning
|
|
162
|
+
>>> logging.warn("X axis has no units", UnitWarning)
|
|
163
|
+
"""
|
|
164
|
+
import inspect
|
|
165
|
+
|
|
166
|
+
action = _get_action(category)
|
|
167
|
+
|
|
168
|
+
# Handle action
|
|
169
|
+
if action == "ignore":
|
|
170
|
+
return
|
|
171
|
+
|
|
172
|
+
if action == "error":
|
|
173
|
+
raise category(message)
|
|
174
|
+
|
|
175
|
+
# Get source location for "once", "module", "default" actions
|
|
176
|
+
frame = inspect.currentframe()
|
|
177
|
+
for _ in range(stacklevel):
|
|
178
|
+
if frame is not None:
|
|
179
|
+
frame = frame.f_back
|
|
180
|
+
|
|
181
|
+
location = ""
|
|
182
|
+
if frame is not None:
|
|
183
|
+
filename = frame.f_code.co_filename
|
|
184
|
+
lineno = frame.f_lineno
|
|
185
|
+
location = f"{filename}:{lineno}"
|
|
186
|
+
|
|
187
|
+
# Check if already seen
|
|
188
|
+
warn_key = f"{category.__name__}:{message}:{location}"
|
|
189
|
+
|
|
190
|
+
if action == "once":
|
|
191
|
+
if warn_key in _seen_warnings:
|
|
192
|
+
return
|
|
193
|
+
_seen_warnings.add(warn_key)
|
|
194
|
+
elif action == "default":
|
|
195
|
+
# Show first per location
|
|
196
|
+
loc_key = f"{category.__name__}:{location}"
|
|
197
|
+
if loc_key in _seen_warnings:
|
|
198
|
+
return
|
|
199
|
+
_seen_warnings.add(loc_key)
|
|
200
|
+
elif action == "module":
|
|
201
|
+
# Show once per module
|
|
202
|
+
if frame is not None:
|
|
203
|
+
module_key = f"{category.__name__}:{frame.f_code.co_filename}"
|
|
204
|
+
if module_key in _seen_warnings:
|
|
205
|
+
return
|
|
206
|
+
_seen_warnings.add(module_key)
|
|
207
|
+
|
|
208
|
+
# Emit via scitex.logging
|
|
209
|
+
logger = _logging.getLogger("scitex.warnings")
|
|
210
|
+
category_name = category.__name__
|
|
211
|
+
|
|
212
|
+
# Format: "UnitWarning: message"
|
|
213
|
+
logger.warning(f"{category_name}: {message}")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# =============================================================================
|
|
217
|
+
# Convenience Warning Functions
|
|
218
|
+
# =============================================================================
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def warn_deprecated(
|
|
222
|
+
old_name: str, new_name: str, version: Optional[str] = None
|
|
223
|
+
) -> None:
|
|
224
|
+
"""Issue a deprecation warning."""
|
|
225
|
+
message = f"{old_name} is deprecated. Use {new_name} instead."
|
|
226
|
+
if version:
|
|
227
|
+
message += f" Will be removed in version {version}."
|
|
228
|
+
warn(message, SciTeXDeprecationWarning, stacklevel=3)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def warn_performance(operation: str, suggestion: str) -> None:
|
|
232
|
+
"""Issue a performance warning."""
|
|
233
|
+
message = f"Performance warning in {operation}: {suggestion}"
|
|
234
|
+
warn(message, PerformanceWarning, stacklevel=3)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def warn_data_loss(operation: str, detail: str) -> None:
|
|
238
|
+
"""Issue a data loss warning."""
|
|
239
|
+
message = f"Potential data loss in {operation}: {detail}"
|
|
240
|
+
warn(message, DataLossWarning, stacklevel=3)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
__all__ = [
|
|
244
|
+
# Warning categories
|
|
245
|
+
"SciTeXWarning",
|
|
246
|
+
"UnitWarning",
|
|
247
|
+
"StyleWarning",
|
|
248
|
+
"SciTeXDeprecationWarning",
|
|
249
|
+
"PerformanceWarning",
|
|
250
|
+
"DataLossWarning",
|
|
251
|
+
# Functions
|
|
252
|
+
"warn",
|
|
253
|
+
"filterwarnings",
|
|
254
|
+
"resetwarnings",
|
|
255
|
+
# Convenience functions
|
|
256
|
+
"warn_deprecated",
|
|
257
|
+
"warn_performance",
|
|
258
|
+
"warn_data_loss",
|
|
259
|
+
]
|
|
260
|
+
|
|
261
|
+
# EOF
|
scitex/plt/__init__.py
CHANGED
|
@@ -179,7 +179,10 @@ try:
|
|
|
179
179
|
except Exception:
|
|
180
180
|
pass # Use matplotlib default colors if color module fails
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
try:
|
|
183
|
+
from ._tpl import termplot
|
|
184
|
+
except ImportError:
|
|
185
|
+
termplot = None
|
|
183
186
|
from . import color
|
|
184
187
|
from . import utils
|
|
185
188
|
from . import ax
|
scitex/plt/_figrecipe.py
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: "2026-01-01 (ywatanabe)"
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/plt/_figrecipe.py
|
|
4
|
+
# ----------------------------------------
|
|
5
|
+
"""
|
|
6
|
+
Figrecipe integration for scitex.
|
|
7
|
+
|
|
8
|
+
This module provides integration with figrecipe for reproducible matplotlib figures.
|
|
9
|
+
Uses csv_format="single" by default for backward compatibility with scitex's
|
|
10
|
+
SigmaPlot-compatible CSV format.
|
|
11
|
+
|
|
12
|
+
Usage
|
|
13
|
+
-----
|
|
14
|
+
>>> import scitex.plt as splt
|
|
15
|
+
>>> fig, ax = splt.subplots()
|
|
16
|
+
>>> ax.plot([1, 2, 3], [4, 5, 6], id='data')
|
|
17
|
+
>>> splt.save_recipe(fig, 'figure.yaml') # Saves recipe with single CSV
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any, Dict, Literal, Optional, Tuple, Union
|
|
22
|
+
|
|
23
|
+
from scitex import logging
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
# Check if figrecipe is available
|
|
28
|
+
try:
|
|
29
|
+
import figrecipe as fr
|
|
30
|
+
|
|
31
|
+
FIGRECIPE_AVAILABLE = True
|
|
32
|
+
except ImportError:
|
|
33
|
+
FIGRECIPE_AVAILABLE = False
|
|
34
|
+
fr = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_figrecipe_available() -> bool:
|
|
38
|
+
"""Check if figrecipe is installed."""
|
|
39
|
+
return FIGRECIPE_AVAILABLE
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def subplots(
|
|
43
|
+
nrows: int = 1,
|
|
44
|
+
ncols: int = 1,
|
|
45
|
+
**kwargs,
|
|
46
|
+
) -> Tuple[Any, Any]:
|
|
47
|
+
"""Create recording-enabled subplots using figrecipe.
|
|
48
|
+
|
|
49
|
+
This is a wrapper around figrecipe.subplots() that creates
|
|
50
|
+
figures with recording capabilities for reproducibility.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
nrows, ncols : int
|
|
55
|
+
Number of rows and columns.
|
|
56
|
+
**kwargs
|
|
57
|
+
Additional arguments passed to figrecipe.subplots().
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
fig : RecordingFigure
|
|
62
|
+
Figrecipe's wrapped figure.
|
|
63
|
+
axes : RecordingAxes or ndarray
|
|
64
|
+
Wrapped axes.
|
|
65
|
+
|
|
66
|
+
Raises
|
|
67
|
+
------
|
|
68
|
+
ImportError
|
|
69
|
+
If figrecipe is not installed.
|
|
70
|
+
"""
|
|
71
|
+
if not FIGRECIPE_AVAILABLE:
|
|
72
|
+
raise ImportError(
|
|
73
|
+
"figrecipe is not installed. Install with: pip install figrecipe"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return fr.subplots(nrows, ncols, **kwargs)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def save_recipe(
|
|
80
|
+
fig,
|
|
81
|
+
path: Union[str, Path],
|
|
82
|
+
csv_format: Literal["single", "separate"] = "single",
|
|
83
|
+
data_format: Literal["csv", "npz", "inline"] = "csv",
|
|
84
|
+
validate: bool = True,
|
|
85
|
+
verbose: bool = True,
|
|
86
|
+
**kwargs,
|
|
87
|
+
) -> Optional[Tuple[Path, Path]]:
|
|
88
|
+
"""Save figure recipe using figrecipe with scitex-compatible CSV format.
|
|
89
|
+
|
|
90
|
+
This function saves a matplotlib figure as a reproducible recipe using
|
|
91
|
+
figrecipe. By default, uses csv_format="single" for backward compatibility
|
|
92
|
+
with scitex's SigmaPlot-compatible CSV format.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
fig : matplotlib.figure.Figure or RecordingFigure
|
|
97
|
+
The figure to save.
|
|
98
|
+
path : str or Path
|
|
99
|
+
Output path (.yaml for recipe, .png/.pdf for image+recipe).
|
|
100
|
+
csv_format : str
|
|
101
|
+
CSV format: 'single' (scitex-compatible, default) or 'separate'.
|
|
102
|
+
- 'single': All columns in one CSV with scitex naming convention
|
|
103
|
+
- 'separate': One CSV per variable (figrecipe default)
|
|
104
|
+
data_format : str
|
|
105
|
+
Data format: 'csv' (default), 'npz', or 'inline'.
|
|
106
|
+
validate : bool
|
|
107
|
+
If True (default), validate reproducibility after saving.
|
|
108
|
+
verbose : bool
|
|
109
|
+
If True (default), print save status.
|
|
110
|
+
**kwargs
|
|
111
|
+
Additional arguments passed to figrecipe.save().
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
tuple or None
|
|
116
|
+
(image_path, yaml_path) if successful, None if figrecipe unavailable.
|
|
117
|
+
|
|
118
|
+
Examples
|
|
119
|
+
--------
|
|
120
|
+
>>> import scitex.plt as splt
|
|
121
|
+
>>> fig, ax = splt.subplots()
|
|
122
|
+
>>> ax.plot([1, 2, 3], [4, 5, 6])
|
|
123
|
+
>>> splt.save_recipe(fig, 'output.yaml') # Single CSV format (scitex-compatible)
|
|
124
|
+
>>> splt.save_recipe(fig, 'output.yaml', csv_format='separate') # Separate CSVs
|
|
125
|
+
"""
|
|
126
|
+
if not FIGRECIPE_AVAILABLE:
|
|
127
|
+
logger.warning(
|
|
128
|
+
"figrecipe is not installed. Recipe not saved. "
|
|
129
|
+
"Install with: pip install figrecipe"
|
|
130
|
+
)
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
path = Path(path)
|
|
134
|
+
|
|
135
|
+
# Handle different figure types
|
|
136
|
+
# If it's a scitex FigWrapper, extract the matplotlib figure
|
|
137
|
+
if hasattr(fig, "_fig_mpl"):
|
|
138
|
+
mpl_fig = fig._fig_mpl
|
|
139
|
+
elif hasattr(fig, "figure"):
|
|
140
|
+
mpl_fig = fig.figure
|
|
141
|
+
else:
|
|
142
|
+
mpl_fig = fig
|
|
143
|
+
|
|
144
|
+
# Check if fig is already a figrecipe RecordingFigure
|
|
145
|
+
if hasattr(fig, "_recorder"):
|
|
146
|
+
# Already a RecordingFigure, use figrecipe's save directly
|
|
147
|
+
return fr.save(
|
|
148
|
+
fig,
|
|
149
|
+
path,
|
|
150
|
+
data_format=data_format,
|
|
151
|
+
csv_format=csv_format,
|
|
152
|
+
validate=validate,
|
|
153
|
+
verbose=verbose,
|
|
154
|
+
**kwargs,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# For regular matplotlib figures, we need to wrap them first
|
|
158
|
+
# This requires re-creating the figure with figrecipe
|
|
159
|
+
logger.warning(
|
|
160
|
+
"Figure is not a RecordingFigure. For full recipe support, "
|
|
161
|
+
"create figures with fr.subplots() or splt.subplots_recipe()."
|
|
162
|
+
)
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def load_recipe(path: Union[str, Path]) -> Tuple[Any, Any]:
|
|
167
|
+
"""Load and reproduce a figure from a recipe file.
|
|
168
|
+
|
|
169
|
+
Parameters
|
|
170
|
+
----------
|
|
171
|
+
path : str or Path
|
|
172
|
+
Path to .yaml recipe file.
|
|
173
|
+
|
|
174
|
+
Returns
|
|
175
|
+
-------
|
|
176
|
+
fig : matplotlib.figure.Figure
|
|
177
|
+
Reproduced figure.
|
|
178
|
+
axes : Axes or list of Axes
|
|
179
|
+
Reproduced axes.
|
|
180
|
+
|
|
181
|
+
Raises
|
|
182
|
+
------
|
|
183
|
+
ImportError
|
|
184
|
+
If figrecipe is not installed.
|
|
185
|
+
"""
|
|
186
|
+
if not FIGRECIPE_AVAILABLE:
|
|
187
|
+
raise ImportError(
|
|
188
|
+
"figrecipe is not installed. Install with: pip install figrecipe"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return fr.reproduce(path)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def recipe_info(path: Union[str, Path]) -> Dict[str, Any]:
|
|
195
|
+
"""Get information about a recipe without reproducing.
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
path : str or Path
|
|
200
|
+
Path to .yaml recipe file.
|
|
201
|
+
|
|
202
|
+
Returns
|
|
203
|
+
-------
|
|
204
|
+
dict
|
|
205
|
+
Recipe information including figure settings, calls, etc.
|
|
206
|
+
|
|
207
|
+
Raises
|
|
208
|
+
------
|
|
209
|
+
ImportError
|
|
210
|
+
If figrecipe is not installed.
|
|
211
|
+
"""
|
|
212
|
+
if not FIGRECIPE_AVAILABLE:
|
|
213
|
+
raise ImportError(
|
|
214
|
+
"figrecipe is not installed. Install with: pip install figrecipe"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return fr.info(path)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
# Convenience aliases
|
|
221
|
+
reproduce = load_recipe
|
|
222
|
+
info = recipe_info
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
__all__ = [
|
|
226
|
+
"FIGRECIPE_AVAILABLE",
|
|
227
|
+
"check_figrecipe_available",
|
|
228
|
+
"subplots",
|
|
229
|
+
"save_recipe",
|
|
230
|
+
"load_recipe",
|
|
231
|
+
"reproduce",
|
|
232
|
+
"recipe_info",
|
|
233
|
+
"info",
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
# EOF
|
|
@@ -189,10 +189,14 @@ class AxisWrapper(
|
|
|
189
189
|
"errorbar",
|
|
190
190
|
"step",
|
|
191
191
|
"stem",
|
|
192
|
+
# Fill and area plots
|
|
193
|
+
"fill",
|
|
194
|
+
"stackplot",
|
|
192
195
|
# Statistical plots
|
|
193
196
|
"hist2d",
|
|
194
197
|
"hexbin",
|
|
195
198
|
"pie",
|
|
199
|
+
"eventplot",
|
|
196
200
|
# Contour plots
|
|
197
201
|
"contour",
|
|
198
202
|
"contourf",
|
|
@@ -202,6 +206,8 @@ class AxisWrapper(
|
|
|
202
206
|
"imshow",
|
|
203
207
|
"matshow",
|
|
204
208
|
"spy",
|
|
209
|
+
"pcolormesh",
|
|
210
|
+
"pcolor",
|
|
205
211
|
# Quiver plots
|
|
206
212
|
"quiver",
|
|
207
213
|
"streamplot",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|