scitex 2.8.1__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/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/edit/panel_loader.py +1 -1
- scitex/fig/io/_bundle.py +7 -7
- 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 -32
- 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} +168 -97
- scitex/io/bundle/_nested.py +713 -0
- scitex/io/bundle/_types.py +74 -0
- scitex/io/{_zip_bundle.py → bundle/_zip.py} +93 -45
- 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/_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/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/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/_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.8.1.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
- {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/RECORD +412 -97
- 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.8.1.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
- {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Millimeter-based layout control for matplotlib figures."""
|
|
3
|
+
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from ._AxesWrapper import AxesWrapper
|
|
8
|
+
from ._AxisWrapper import AxisWrapper
|
|
9
|
+
from ._FigWrapper import FigWrapper
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_with_mm_control(
|
|
13
|
+
*args,
|
|
14
|
+
track=True,
|
|
15
|
+
sharex=False,
|
|
16
|
+
sharey=False,
|
|
17
|
+
axes_width_mm=None,
|
|
18
|
+
axes_height_mm=None,
|
|
19
|
+
margin_left_mm=None,
|
|
20
|
+
margin_right_mm=None,
|
|
21
|
+
margin_bottom_mm=None,
|
|
22
|
+
margin_top_mm=None,
|
|
23
|
+
space_w_mm=None,
|
|
24
|
+
space_h_mm=None,
|
|
25
|
+
axes_thickness_mm=None,
|
|
26
|
+
tick_length_mm=None,
|
|
27
|
+
tick_thickness_mm=None,
|
|
28
|
+
trace_thickness_mm=None,
|
|
29
|
+
marker_size_mm=None,
|
|
30
|
+
axis_font_size_pt=None,
|
|
31
|
+
tick_font_size_pt=None,
|
|
32
|
+
title_font_size_pt=None,
|
|
33
|
+
legend_font_size_pt=None,
|
|
34
|
+
suptitle_font_size_pt=None,
|
|
35
|
+
label_pad_pt=None,
|
|
36
|
+
tick_pad_pt=None,
|
|
37
|
+
title_pad_pt=None,
|
|
38
|
+
font_family=None,
|
|
39
|
+
n_ticks=None,
|
|
40
|
+
mode=None,
|
|
41
|
+
dpi=None,
|
|
42
|
+
styles=None,
|
|
43
|
+
transparent=None,
|
|
44
|
+
theme=None,
|
|
45
|
+
**kwargs,
|
|
46
|
+
):
|
|
47
|
+
"""Create figure with mm-based control over axes dimensions.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
tuple
|
|
52
|
+
(FigWrapper, AxisWrapper or AxesWrapper)
|
|
53
|
+
"""
|
|
54
|
+
from scitex.plt.utils import apply_style_mm, mm_to_inch
|
|
55
|
+
|
|
56
|
+
# Parse nrows, ncols from args or kwargs
|
|
57
|
+
nrows, ncols = 1, 1
|
|
58
|
+
if len(args) >= 1:
|
|
59
|
+
nrows = args[0]
|
|
60
|
+
elif "nrows" in kwargs:
|
|
61
|
+
nrows = kwargs.pop("nrows")
|
|
62
|
+
if len(args) >= 2:
|
|
63
|
+
ncols = args[1]
|
|
64
|
+
elif "ncols" in kwargs:
|
|
65
|
+
ncols = kwargs.pop("ncols")
|
|
66
|
+
|
|
67
|
+
n_axes = nrows * ncols
|
|
68
|
+
|
|
69
|
+
# Apply mode-specific defaults
|
|
70
|
+
if mode == "display":
|
|
71
|
+
scale_factor = 3.0
|
|
72
|
+
dpi = dpi or 100
|
|
73
|
+
else:
|
|
74
|
+
scale_factor = 1.0
|
|
75
|
+
dpi = dpi or 300
|
|
76
|
+
|
|
77
|
+
# Set defaults with scaling
|
|
78
|
+
if axes_width_mm is None:
|
|
79
|
+
axes_width_mm = 30.0 * scale_factor
|
|
80
|
+
elif mode == "display":
|
|
81
|
+
axes_width_mm = axes_width_mm * scale_factor
|
|
82
|
+
|
|
83
|
+
if axes_height_mm is None:
|
|
84
|
+
axes_height_mm = 21.0 * scale_factor
|
|
85
|
+
elif mode == "display":
|
|
86
|
+
axes_height_mm = axes_height_mm * scale_factor
|
|
87
|
+
|
|
88
|
+
margin_left_mm = (
|
|
89
|
+
margin_left_mm if margin_left_mm is not None else (5.0 * scale_factor)
|
|
90
|
+
)
|
|
91
|
+
margin_right_mm = (
|
|
92
|
+
margin_right_mm if margin_right_mm is not None else (2.0 * scale_factor)
|
|
93
|
+
)
|
|
94
|
+
margin_bottom_mm = (
|
|
95
|
+
margin_bottom_mm if margin_bottom_mm is not None else (5.0 * scale_factor)
|
|
96
|
+
)
|
|
97
|
+
margin_top_mm = margin_top_mm if margin_top_mm is not None else (2.0 * scale_factor)
|
|
98
|
+
space_w_mm = space_w_mm if space_w_mm is not None else (3.0 * scale_factor)
|
|
99
|
+
space_h_mm = space_h_mm if space_h_mm is not None else (3.0 * scale_factor)
|
|
100
|
+
|
|
101
|
+
# Handle list vs scalar for axes dimensions
|
|
102
|
+
if isinstance(axes_width_mm, (list, tuple)):
|
|
103
|
+
ax_widths_mm = list(axes_width_mm)
|
|
104
|
+
if len(ax_widths_mm) != n_axes:
|
|
105
|
+
raise ValueError(
|
|
106
|
+
f"axes_width_mm list length ({len(ax_widths_mm)}) "
|
|
107
|
+
f"must match nrows*ncols ({n_axes})"
|
|
108
|
+
)
|
|
109
|
+
else:
|
|
110
|
+
ax_widths_mm = [axes_width_mm] * n_axes
|
|
111
|
+
|
|
112
|
+
if isinstance(axes_height_mm, (list, tuple)):
|
|
113
|
+
ax_heights_mm = list(axes_height_mm)
|
|
114
|
+
if len(ax_heights_mm) != n_axes:
|
|
115
|
+
raise ValueError(
|
|
116
|
+
f"axes_height_mm list length ({len(ax_heights_mm)}) "
|
|
117
|
+
f"must match nrows*ncols ({n_axes})"
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
ax_heights_mm = [axes_height_mm] * n_axes
|
|
121
|
+
|
|
122
|
+
# Calculate figure size from axes grid
|
|
123
|
+
ax_widths_2d = np.array(ax_widths_mm).reshape(nrows, ncols)
|
|
124
|
+
ax_heights_2d = np.array(ax_heights_mm).reshape(nrows, ncols)
|
|
125
|
+
|
|
126
|
+
max_widths_per_col = ax_widths_2d.max(axis=0)
|
|
127
|
+
max_heights_per_row = ax_heights_2d.max(axis=1)
|
|
128
|
+
|
|
129
|
+
total_width_mm = (
|
|
130
|
+
margin_left_mm
|
|
131
|
+
+ max_widths_per_col.sum()
|
|
132
|
+
+ (ncols - 1) * space_w_mm
|
|
133
|
+
+ margin_right_mm
|
|
134
|
+
)
|
|
135
|
+
total_height_mm = (
|
|
136
|
+
margin_bottom_mm
|
|
137
|
+
+ max_heights_per_row.sum()
|
|
138
|
+
+ (nrows - 1) * space_h_mm
|
|
139
|
+
+ margin_top_mm
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Create figure
|
|
143
|
+
figsize_inch = (mm_to_inch(total_width_mm), mm_to_inch(total_height_mm))
|
|
144
|
+
if transparent:
|
|
145
|
+
fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi, facecolor="none")
|
|
146
|
+
else:
|
|
147
|
+
fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi)
|
|
148
|
+
|
|
149
|
+
# Store theme on figure
|
|
150
|
+
if theme is not None:
|
|
151
|
+
fig_mpl._scitex_theme = theme
|
|
152
|
+
|
|
153
|
+
# Create axes array and position each one manually
|
|
154
|
+
axes_mpl_list = []
|
|
155
|
+
ax_idx = 0
|
|
156
|
+
|
|
157
|
+
for row in range(nrows):
|
|
158
|
+
for col in range(ncols):
|
|
159
|
+
# Calculate position
|
|
160
|
+
left_mm = margin_left_mm + max_widths_per_col[:col].sum() + col * space_w_mm
|
|
161
|
+
rows_below = nrows - row - 1
|
|
162
|
+
bottom_mm = (
|
|
163
|
+
margin_bottom_mm
|
|
164
|
+
+ max_heights_per_row[row + 1 :].sum()
|
|
165
|
+
+ rows_below * space_h_mm
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Convert to figure coordinates [0-1]
|
|
169
|
+
left = left_mm / total_width_mm
|
|
170
|
+
bottom = bottom_mm / total_height_mm
|
|
171
|
+
width = ax_widths_mm[ax_idx] / total_width_mm
|
|
172
|
+
height = ax_heights_mm[ax_idx] / total_height_mm
|
|
173
|
+
|
|
174
|
+
# Create axes
|
|
175
|
+
ax_mpl = fig_mpl.add_axes([left, bottom, width, height])
|
|
176
|
+
if transparent:
|
|
177
|
+
ax_mpl.patch.set_alpha(0.0)
|
|
178
|
+
axes_mpl_list.append(ax_mpl)
|
|
179
|
+
|
|
180
|
+
# Tag with metadata
|
|
181
|
+
ax_mpl._scitex_metadata = {
|
|
182
|
+
"created_with": "scitex.plt.subplots",
|
|
183
|
+
"mode": mode or "publication",
|
|
184
|
+
"axes_size_mm": (ax_widths_mm[ax_idx], ax_heights_mm[ax_idx]),
|
|
185
|
+
"position_in_grid": (row, col),
|
|
186
|
+
}
|
|
187
|
+
ax_idx += 1
|
|
188
|
+
|
|
189
|
+
# Apply styling to each axes
|
|
190
|
+
suptitle_font_size_pt_value = None
|
|
191
|
+
for i, ax_mpl in enumerate(axes_mpl_list):
|
|
192
|
+
# Determine which style dict to use
|
|
193
|
+
if styles is not None:
|
|
194
|
+
if isinstance(styles, list):
|
|
195
|
+
if len(styles) != n_axes:
|
|
196
|
+
raise ValueError(
|
|
197
|
+
f"styles list length ({len(styles)}) "
|
|
198
|
+
f"must match nrows*ncols ({n_axes})"
|
|
199
|
+
)
|
|
200
|
+
style_dict = styles[i]
|
|
201
|
+
else:
|
|
202
|
+
style_dict = styles
|
|
203
|
+
else:
|
|
204
|
+
# Build style dict from individual parameters
|
|
205
|
+
style_dict = {}
|
|
206
|
+
if axes_thickness_mm is not None:
|
|
207
|
+
style_dict["axis_thickness_mm"] = axes_thickness_mm
|
|
208
|
+
if tick_length_mm is not None:
|
|
209
|
+
style_dict["tick_length_mm"] = tick_length_mm
|
|
210
|
+
if tick_thickness_mm is not None:
|
|
211
|
+
style_dict["tick_thickness_mm"] = tick_thickness_mm
|
|
212
|
+
if trace_thickness_mm is not None:
|
|
213
|
+
style_dict["trace_thickness_mm"] = trace_thickness_mm
|
|
214
|
+
if marker_size_mm is not None:
|
|
215
|
+
style_dict["marker_size_mm"] = marker_size_mm
|
|
216
|
+
if axis_font_size_pt is not None:
|
|
217
|
+
style_dict["axis_font_size_pt"] = axis_font_size_pt
|
|
218
|
+
if tick_font_size_pt is not None:
|
|
219
|
+
style_dict["tick_font_size_pt"] = tick_font_size_pt
|
|
220
|
+
if title_font_size_pt is not None:
|
|
221
|
+
style_dict["title_font_size_pt"] = title_font_size_pt
|
|
222
|
+
if legend_font_size_pt is not None:
|
|
223
|
+
style_dict["legend_font_size_pt"] = legend_font_size_pt
|
|
224
|
+
if suptitle_font_size_pt is not None:
|
|
225
|
+
style_dict["suptitle_font_size_pt"] = suptitle_font_size_pt
|
|
226
|
+
if label_pad_pt is not None:
|
|
227
|
+
style_dict["label_pad_pt"] = label_pad_pt
|
|
228
|
+
if tick_pad_pt is not None:
|
|
229
|
+
style_dict["tick_pad_pt"] = tick_pad_pt
|
|
230
|
+
if title_pad_pt is not None:
|
|
231
|
+
style_dict["title_pad_pt"] = title_pad_pt
|
|
232
|
+
if font_family is not None:
|
|
233
|
+
style_dict["font_family"] = font_family
|
|
234
|
+
if n_ticks is not None:
|
|
235
|
+
style_dict["n_ticks"] = n_ticks
|
|
236
|
+
|
|
237
|
+
# Always add theme to style_dict
|
|
238
|
+
if theme is not None:
|
|
239
|
+
style_dict["theme"] = theme
|
|
240
|
+
|
|
241
|
+
# Extract suptitle font size if available
|
|
242
|
+
if "suptitle_font_size_pt" in style_dict:
|
|
243
|
+
suptitle_font_size_pt_value = style_dict["suptitle_font_size_pt"]
|
|
244
|
+
|
|
245
|
+
# Apply style if not empty
|
|
246
|
+
if style_dict:
|
|
247
|
+
apply_style_mm(ax_mpl, style_dict)
|
|
248
|
+
ax_mpl._scitex_metadata["style_mm"] = style_dict
|
|
249
|
+
|
|
250
|
+
# Store suptitle font size in figure metadata
|
|
251
|
+
if suptitle_font_size_pt_value is not None:
|
|
252
|
+
fig_mpl._scitex_suptitle_font_size_pt = suptitle_font_size_pt_value
|
|
253
|
+
|
|
254
|
+
# Wrap the figure
|
|
255
|
+
fig_scitex = FigWrapper(fig_mpl)
|
|
256
|
+
|
|
257
|
+
# Reshape axes list
|
|
258
|
+
axes_array_mpl = np.array(axes_mpl_list).reshape(nrows, ncols)
|
|
259
|
+
|
|
260
|
+
# Handle single axis case
|
|
261
|
+
if n_axes == 1:
|
|
262
|
+
ax_mpl_scalar = axes_array_mpl.item()
|
|
263
|
+
axis_scitex = AxisWrapper(fig_scitex, ax_mpl_scalar, track)
|
|
264
|
+
fig_scitex.axes = [axis_scitex]
|
|
265
|
+
ax_mpl_scalar._scitex_wrapper = axis_scitex
|
|
266
|
+
return fig_scitex, axis_scitex
|
|
267
|
+
|
|
268
|
+
# Handle multiple axes case
|
|
269
|
+
axes_flat_scitex_list = []
|
|
270
|
+
for ax_mpl in axes_mpl_list:
|
|
271
|
+
ax_scitex = AxisWrapper(fig_scitex, ax_mpl, track)
|
|
272
|
+
ax_mpl._scitex_wrapper = ax_scitex
|
|
273
|
+
axes_flat_scitex_list.append(ax_scitex)
|
|
274
|
+
|
|
275
|
+
axes_array_scitex = np.array(axes_flat_scitex_list).reshape(nrows, ncols)
|
|
276
|
+
axes_scitex = AxesWrapper(fig_scitex, axes_array_scitex)
|
|
277
|
+
fig_scitex.axes = axes_scitex
|
|
278
|
+
|
|
279
|
+
return fig_scitex, axes_scitex
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# EOF
|
scitex/plt/gallery/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-12-
|
|
3
|
+
# Timestamp: "2025-12-18 (ywatanabe)"
|
|
4
4
|
# File: /home/ywatanabe/proj/scitex-code/src/scitex/plt/gallery/__init__.py
|
|
5
5
|
|
|
6
6
|
"""
|
|
@@ -19,11 +19,108 @@ Usage:
|
|
|
19
19
|
|
|
20
20
|
# List available plots
|
|
21
21
|
stx.plt.gallery.list()
|
|
22
|
+
|
|
23
|
+
# Get plot spec and data for bundle creation
|
|
24
|
+
spec = stx.plt.gallery.get_plot_spec("line", "plot")
|
|
25
|
+
data = stx.plt.gallery.get_plot_data("line", "plot")
|
|
22
26
|
"""
|
|
23
27
|
|
|
24
28
|
from ._generate import generate
|
|
25
29
|
from ._registry import CATEGORIES, list_plots
|
|
30
|
+
from ._plots import PLOT_FUNCTIONS
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_plot_spec(category: str, plot_name: str) -> dict:
|
|
34
|
+
"""Get spec dictionary for a gallery plot.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
category : str
|
|
39
|
+
Plot category (e.g., "line", "scatter", "categorical")
|
|
40
|
+
plot_name : str
|
|
41
|
+
Plot name within the category (e.g., "plot", "scatter", "bar")
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
dict
|
|
46
|
+
Spec dictionary for the plot type.
|
|
47
|
+
"""
|
|
48
|
+
if category not in CATEGORIES:
|
|
49
|
+
raise ValueError(f"Unknown category: {category}. Available: {list(CATEGORIES.keys())}")
|
|
50
|
+
|
|
51
|
+
if plot_name not in CATEGORIES[category]["plots"]:
|
|
52
|
+
raise ValueError(f"Unknown plot: {plot_name} in category {category}")
|
|
53
|
+
|
|
54
|
+
# Build a minimal spec for this plot type
|
|
55
|
+
return {
|
|
56
|
+
"schema": {"name": "scitex.plt.plot", "version": "1.0.0"},
|
|
57
|
+
"plot_type": plot_name,
|
|
58
|
+
"category": category,
|
|
59
|
+
"axes": {"xlabel": "", "ylabel": ""},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_plot_data(category: str, plot_name: str):
|
|
64
|
+
"""Get sample data for a gallery plot as DataFrame.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
category : str
|
|
69
|
+
Plot category (e.g., "line", "scatter", "categorical")
|
|
70
|
+
plot_name : str
|
|
71
|
+
Plot name within the category (e.g., "plot", "scatter", "bar")
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
pandas.DataFrame or None
|
|
76
|
+
Sample data for the plot, or None if plot doesn't use CSV data.
|
|
77
|
+
"""
|
|
78
|
+
import io
|
|
79
|
+
import tempfile
|
|
80
|
+
from pathlib import Path
|
|
81
|
+
|
|
82
|
+
if category not in CATEGORIES:
|
|
83
|
+
raise ValueError(f"Unknown category: {category}. Available: {list(CATEGORIES.keys())}")
|
|
84
|
+
|
|
85
|
+
if plot_name not in CATEGORIES[category]["plots"]:
|
|
86
|
+
raise ValueError(f"Unknown plot: {plot_name} in category {category}")
|
|
87
|
+
|
|
88
|
+
if plot_name not in PLOT_FUNCTIONS:
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
import scitex as stx
|
|
93
|
+
from scitex.plt.styles.presets import SCITEX_STYLE
|
|
94
|
+
|
|
95
|
+
# Create a temporary figure
|
|
96
|
+
style = SCITEX_STYLE.copy()
|
|
97
|
+
style["figsize"] = (4, 3)
|
|
98
|
+
fig, ax = stx.plt.subplots(**style)
|
|
99
|
+
|
|
100
|
+
# Generate plot
|
|
101
|
+
plot_func = PLOT_FUNCTIONS[plot_name]
|
|
102
|
+
fig, ax = plot_func(fig, ax, stx)
|
|
103
|
+
|
|
104
|
+
# Export to CSV and parse
|
|
105
|
+
csv_buffer = io.StringIO()
|
|
106
|
+
ax.export_as_csv(csv_buffer)
|
|
107
|
+
csv_buffer.seek(0)
|
|
108
|
+
|
|
109
|
+
import pandas as pd
|
|
110
|
+
df = pd.read_csv(csv_buffer)
|
|
111
|
+
|
|
112
|
+
# Close figure
|
|
113
|
+
stx.plt.close(fig._fig_mpl if hasattr(fig, "_fig_mpl") else fig)
|
|
114
|
+
|
|
115
|
+
return df
|
|
116
|
+
|
|
117
|
+
except Exception as e:
|
|
118
|
+
# Some plots may not have exportable CSV data
|
|
119
|
+
import warnings
|
|
120
|
+
warnings.warn(f"Could not get data for {category}/{plot_name}: {e}")
|
|
121
|
+
return None
|
|
122
|
+
|
|
26
123
|
|
|
27
|
-
__all__ = ["generate", "list_plots", "CATEGORIES"]
|
|
124
|
+
__all__ = ["generate", "list_plots", "CATEGORIES", "get_plot_spec", "get_plot_data"]
|
|
28
125
|
|
|
29
126
|
# EOF
|
|
@@ -119,7 +119,9 @@ def _apply_tick_locator(ax):
|
|
|
119
119
|
try:
|
|
120
120
|
|
|
121
121
|
def is_categorical_axis(axis):
|
|
122
|
-
|
|
122
|
+
# Use get_converter() for matplotlib 3.10+ compatibility
|
|
123
|
+
converter = getattr(axis, 'get_converter', lambda: axis.converter)()
|
|
124
|
+
if isinstance(converter, StrCategoryConverter):
|
|
123
125
|
return True
|
|
124
126
|
if hasattr(axis, "units") and isinstance(axis.units, UnitData):
|
|
125
127
|
return True
|
|
@@ -9,11 +9,14 @@ from typing import Dict
|
|
|
9
9
|
from typing import Optional
|
|
10
10
|
from typing import Tuple
|
|
11
11
|
|
|
12
|
+
import logging
|
|
12
13
|
import matplotlib.pyplot as plt
|
|
13
14
|
import numpy as np
|
|
14
15
|
import scitex
|
|
15
16
|
from scitex.dict import DotDict
|
|
16
17
|
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
def configure_mpl(
|
|
19
22
|
plt,
|
|
@@ -343,28 +346,22 @@ def configure_mpl(
|
|
|
343
346
|
plt.rcParams.update(mpl_config)
|
|
344
347
|
|
|
345
348
|
if verbose:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
349
|
+
colors_str = "\n".join(f" {color_str}: {rgba}" for color_str, rgba in RGBA.items())
|
|
350
|
+
config_msg = (
|
|
351
|
+
f"\n{'-' * 40}\n"
|
|
352
|
+
f"Matplotlib has been configured as follows:\n\n"
|
|
353
|
+
f"Figure DPI (Display): {dpi_display} DPI\n"
|
|
354
|
+
f"Figure DPI (Save): {dpi_save} DPI\n"
|
|
351
355
|
f"Figure Size (Not the Axis Size): "
|
|
352
356
|
f"{fig_size_mm[0] * fig_scale:.1f} x "
|
|
353
|
-
f"{fig_size_mm[1] * fig_scale:.1f} mm (width x height)"
|
|
357
|
+
f"{fig_size_mm[1] * fig_scale:.1f} mm (width x height)\n"
|
|
358
|
+
f"\nHide Top and Right Axes: {hide_top_right_spines}\n"
|
|
359
|
+
f"Line Width: {line_width}\n"
|
|
360
|
+
f"\nCustom Colors (RGBA):\n"
|
|
361
|
+
f"{colors_str}\n"
|
|
362
|
+
f"{'-' * 40}"
|
|
354
363
|
)
|
|
355
|
-
|
|
356
|
-
# print(f" Base Size: {base_size:.1f}pt")
|
|
357
|
-
# print(f" Title: {title_size:.1f}pt (125% of base, min 10pt)")
|
|
358
|
-
# print(f" Axis Labels: {label_size:.1f}pt (100% of base, min 9pt)")
|
|
359
|
-
# print(f" Tick Labels: {small_size:.1f}pt (85% of base, min 8pt)")
|
|
360
|
-
# print(f" Legend: {small_size:.1f}pt (85% of base, min 8pt)")
|
|
361
|
-
print(f"\nHide Top and Right Axes: {hide_top_right_spines}")
|
|
362
|
-
print(f"Line Width: {line_width}")
|
|
363
|
-
# print(f"Number of Ticks: {n_ticks}")
|
|
364
|
-
print(f"\nCustom Colors (RGBA):")
|
|
365
|
-
for color_str, rgba in RGBA.items():
|
|
366
|
-
print(f" {color_str}: {rgba}")
|
|
367
|
-
print("-" * 40)
|
|
364
|
+
logger.info(config_msg)
|
|
368
365
|
|
|
369
366
|
# Store n_ticks for later use
|
|
370
367
|
plt._n_ticks = n_ticks
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
# Timestamp: "2025-12-09 (ywatanabe)"
|
|
4
3
|
# File: /home/ywatanabe/proj/scitex-code/src/scitex/repro/_RandomStateManager.py
|
|
5
4
|
# ----------------------------------------
|
|
6
5
|
from __future__ import annotations
|
|
6
|
+
|
|
7
7
|
import os
|
|
8
8
|
|
|
9
9
|
__FILE__ = __file__
|
|
@@ -21,6 +21,7 @@ Main API:
|
|
|
21
21
|
|
|
22
22
|
import hashlib
|
|
23
23
|
import json
|
|
24
|
+
import logging
|
|
24
25
|
import pickle
|
|
25
26
|
from contextlib import contextmanager
|
|
26
27
|
from pathlib import Path
|
|
@@ -28,6 +29,8 @@ from typing import Any
|
|
|
28
29
|
|
|
29
30
|
from scitex.config import get_paths
|
|
30
31
|
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
31
34
|
# Global singleton instance
|
|
32
35
|
_GLOBAL_INSTANCE = None
|
|
33
36
|
|
|
@@ -62,7 +65,7 @@ class RandomStateManager:
|
|
|
62
65
|
self._jax_key = None # Initialize to None, will be set if jax is available
|
|
63
66
|
|
|
64
67
|
if verbose:
|
|
65
|
-
|
|
68
|
+
logger.info(f"RandomStateManager initialized with seed {seed}")
|
|
66
69
|
|
|
67
70
|
# Auto-fix all available seeds
|
|
68
71
|
self._auto_fix_seeds(verbose=verbose)
|
|
@@ -138,7 +141,7 @@ class RandomStateManager:
|
|
|
138
141
|
pass
|
|
139
142
|
|
|
140
143
|
if verbose and fixed_modules:
|
|
141
|
-
|
|
144
|
+
logger.info(f"Fixed random seeds for: {', '.join(fixed_modules)}")
|
|
142
145
|
|
|
143
146
|
def get_np_generator(self, name: str):
|
|
144
147
|
"""
|
|
@@ -225,7 +228,6 @@ class RandomStateManager:
|
|
|
225
228
|
>>> # Next run:
|
|
226
229
|
>>> rng.verify(data, "train_data") # Verifies match
|
|
227
230
|
"""
|
|
228
|
-
import numpy as np
|
|
229
231
|
|
|
230
232
|
# Auto-generate name if needed
|
|
231
233
|
if name is None:
|
|
@@ -249,7 +251,7 @@ class RandomStateManager:
|
|
|
249
251
|
|
|
250
252
|
# Check cache
|
|
251
253
|
if cache_file.exists():
|
|
252
|
-
with open(cache_file
|
|
254
|
+
with open(cache_file) as f:
|
|
253
255
|
cached = json.load(f)
|
|
254
256
|
|
|
255
257
|
matches = cached["hash"] == obj_hash
|
|
@@ -315,7 +317,10 @@ class RandomStateManager:
|
|
|
315
317
|
if isinstance(obj, jnp.ndarray):
|
|
316
318
|
obj_np = np.array(obj)
|
|
317
319
|
return hashlib.sha256(obj_np.tobytes()).hexdigest()[:32]
|
|
318
|
-
except ImportError:
|
|
320
|
+
except (ImportError, AttributeError, RuntimeError):
|
|
321
|
+
# ImportError: jax not installed
|
|
322
|
+
# AttributeError: circular import in jax._src.clusters
|
|
323
|
+
# RuntimeError: other jax initialization errors
|
|
319
324
|
pass
|
|
320
325
|
|
|
321
326
|
# Pandas DataFrame/Series
|
|
@@ -504,7 +509,6 @@ class RandomStateManager:
|
|
|
504
509
|
>>> rng.clear_cache(["test1", "test2"]) # Clear multiple
|
|
505
510
|
>>> rng.clear_cache("experiment_*") # Clear pattern
|
|
506
511
|
"""
|
|
507
|
-
import glob
|
|
508
512
|
|
|
509
513
|
if not self._cache_dir.exists():
|
|
510
514
|
return 0
|
|
@@ -614,7 +618,6 @@ def main(args):
|
|
|
614
618
|
- Reproducible random generation
|
|
615
619
|
- Verification of reproducibility
|
|
616
620
|
"""
|
|
617
|
-
import numpy as np
|
|
618
621
|
|
|
619
622
|
# Create RandomStateManager (already created by session.start)
|
|
620
623
|
print(f"\n{'=' * 60}")
|
|
@@ -650,7 +653,9 @@ def main(args):
|
|
|
650
653
|
|
|
651
654
|
if __name__ == "__main__":
|
|
652
655
|
import sys
|
|
656
|
+
|
|
653
657
|
import matplotlib.pyplot as plt
|
|
658
|
+
|
|
654
659
|
import scitex as stx
|
|
655
660
|
|
|
656
661
|
args = parse_args()
|
scitex/resource/__init__.py
CHANGED
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
"""Scitex resource module."""
|
|
3
3
|
|
|
4
4
|
from ._get_processor_usages import get_processor_usages
|
|
5
|
-
from ._get_specs import
|
|
5
|
+
from ._get_specs import (
|
|
6
|
+
_cpu_info,
|
|
7
|
+
_disk_info,
|
|
8
|
+
_memory_info,
|
|
9
|
+
_network_info,
|
|
10
|
+
_supple_nvidia_info,
|
|
11
|
+
_supple_os_info,
|
|
12
|
+
_supple_python_info,
|
|
13
|
+
_system_info,
|
|
14
|
+
get_specs,
|
|
15
|
+
)
|
|
6
16
|
from ._log_processor_usages import log_processor_usages, main
|
|
7
17
|
|
|
8
18
|
__all__ = [
|
|
@@ -10,4 +20,12 @@ __all__ = [
|
|
|
10
20
|
"get_specs",
|
|
11
21
|
"log_processor_usages",
|
|
12
22
|
"main",
|
|
23
|
+
"_cpu_info",
|
|
24
|
+
"_disk_info",
|
|
25
|
+
"_memory_info",
|
|
26
|
+
"_network_info",
|
|
27
|
+
"_supple_nvidia_info",
|
|
28
|
+
"_supple_os_info",
|
|
29
|
+
"_supple_python_info",
|
|
30
|
+
"_system_info",
|
|
13
31
|
]
|