scitex 2.8.1__py3-none-any.whl → 2.10.2__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.2.dist-info}/METADATA +368 -183
- {scitex-2.8.1.dist-info → scitex-2.10.2.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.2.dist-info}/WHEEL +0 -0
- {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/entry_points.txt +0 -0
- {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/licenses/LICENSE +0 -0
scitex/schema/_theme.py
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-12-19
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/schema/_theme.py
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Theme Schema - Pure Aesthetics for Visual Presentation.
|
|
7
|
+
|
|
8
|
+
This module defines the theme layer that controls visual appearance
|
|
9
|
+
without affecting scientific meaning. Theme can be changed without
|
|
10
|
+
affecting reproducibility of the data representation.
|
|
11
|
+
|
|
12
|
+
Theme (theme.json) - Aesthetics Only:
|
|
13
|
+
- Colors and color palettes
|
|
14
|
+
- Fonts and typography
|
|
15
|
+
- Line styles and widths
|
|
16
|
+
- Marker styles and sizes
|
|
17
|
+
- Layout and spacing
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
from dataclasses import asdict, dataclass, field
|
|
22
|
+
from typing import Any, Dict, List, Optional
|
|
23
|
+
|
|
24
|
+
THEME_VERSION = "1.0.0"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class ColorScheme:
|
|
29
|
+
"""
|
|
30
|
+
Color scheme specification.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
mode : str
|
|
35
|
+
Color mode (light, dark, auto)
|
|
36
|
+
background : str
|
|
37
|
+
Figure background color
|
|
38
|
+
axes_bg : str
|
|
39
|
+
Axes background color
|
|
40
|
+
text : str
|
|
41
|
+
Text color
|
|
42
|
+
spine : str
|
|
43
|
+
Axes spine color
|
|
44
|
+
tick : str
|
|
45
|
+
Tick mark color
|
|
46
|
+
grid : str
|
|
47
|
+
Grid line color
|
|
48
|
+
palette : str, optional
|
|
49
|
+
Named color palette for traces
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
mode: str = "light"
|
|
53
|
+
background: str = "transparent"
|
|
54
|
+
axes_bg: str = "white"
|
|
55
|
+
text: str = "black"
|
|
56
|
+
spine: str = "black"
|
|
57
|
+
tick: str = "black"
|
|
58
|
+
grid: str = "#cccccc"
|
|
59
|
+
palette: Optional[str] = None
|
|
60
|
+
|
|
61
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
62
|
+
result = {
|
|
63
|
+
"mode": self.mode,
|
|
64
|
+
"background": self.background,
|
|
65
|
+
"axes_bg": self.axes_bg,
|
|
66
|
+
"text": self.text,
|
|
67
|
+
"spine": self.spine,
|
|
68
|
+
"tick": self.tick,
|
|
69
|
+
"grid": self.grid,
|
|
70
|
+
}
|
|
71
|
+
if self.palette:
|
|
72
|
+
result["palette"] = self.palette
|
|
73
|
+
return result
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ColorScheme":
|
|
77
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class Typography:
|
|
82
|
+
"""
|
|
83
|
+
Typography specification.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
family : str
|
|
88
|
+
Font family
|
|
89
|
+
size_pt : float
|
|
90
|
+
Base font size in points
|
|
91
|
+
title_size_pt : float
|
|
92
|
+
Title font size in points
|
|
93
|
+
label_size_pt : float
|
|
94
|
+
Axis label font size in points
|
|
95
|
+
tick_size_pt : float
|
|
96
|
+
Tick label font size in points
|
|
97
|
+
legend_size_pt : float
|
|
98
|
+
Legend font size in points
|
|
99
|
+
weight : str
|
|
100
|
+
Font weight (normal, bold, etc.)
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
family: str = "sans-serif"
|
|
104
|
+
size_pt: float = 7.0
|
|
105
|
+
title_size_pt: float = 8.0
|
|
106
|
+
label_size_pt: float = 7.0
|
|
107
|
+
tick_size_pt: float = 6.0
|
|
108
|
+
legend_size_pt: float = 6.0
|
|
109
|
+
weight: str = "normal"
|
|
110
|
+
|
|
111
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
112
|
+
return asdict(self)
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Typography":
|
|
116
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass
|
|
120
|
+
class LineDefaults:
|
|
121
|
+
"""Default line style settings."""
|
|
122
|
+
|
|
123
|
+
width: float = 1.0
|
|
124
|
+
style: str = "-" # solid
|
|
125
|
+
alpha: float = 1.0
|
|
126
|
+
|
|
127
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
128
|
+
return asdict(self)
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def from_dict(cls, data: Dict[str, Any]) -> "LineDefaults":
|
|
132
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dataclass
|
|
136
|
+
class MarkerDefaults:
|
|
137
|
+
"""Default marker style settings."""
|
|
138
|
+
|
|
139
|
+
size: float = 6.0
|
|
140
|
+
style: str = "o"
|
|
141
|
+
edge_width: float = 0.5
|
|
142
|
+
edge_color: str = "auto" # auto means same as fill or black
|
|
143
|
+
|
|
144
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
145
|
+
return asdict(self)
|
|
146
|
+
|
|
147
|
+
@classmethod
|
|
148
|
+
def from_dict(cls, data: Dict[str, Any]) -> "MarkerDefaults":
|
|
149
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass
|
|
153
|
+
class TraceStyle:
|
|
154
|
+
"""
|
|
155
|
+
Per-trace style overrides.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
trace_id : str
|
|
160
|
+
ID of the trace this style applies to
|
|
161
|
+
color : str, optional
|
|
162
|
+
Trace color
|
|
163
|
+
linewidth : float, optional
|
|
164
|
+
Line width
|
|
165
|
+
linestyle : str, optional
|
|
166
|
+
Line style
|
|
167
|
+
marker : str, optional
|
|
168
|
+
Marker style
|
|
169
|
+
markersize : float, optional
|
|
170
|
+
Marker size
|
|
171
|
+
alpha : float, optional
|
|
172
|
+
Opacity
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
trace_id: str
|
|
176
|
+
color: Optional[str] = None
|
|
177
|
+
linewidth: Optional[float] = None
|
|
178
|
+
linestyle: Optional[str] = None
|
|
179
|
+
marker: Optional[str] = None
|
|
180
|
+
markersize: Optional[float] = None
|
|
181
|
+
alpha: Optional[float] = None
|
|
182
|
+
|
|
183
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
184
|
+
result = {"trace_id": self.trace_id}
|
|
185
|
+
for name in [
|
|
186
|
+
"color",
|
|
187
|
+
"linewidth",
|
|
188
|
+
"linestyle",
|
|
189
|
+
"marker",
|
|
190
|
+
"markersize",
|
|
191
|
+
"alpha",
|
|
192
|
+
]:
|
|
193
|
+
val = getattr(self, name)
|
|
194
|
+
if val is not None:
|
|
195
|
+
result[name] = val
|
|
196
|
+
return result
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def from_dict(cls, data: Dict[str, Any]) -> "TraceStyle":
|
|
200
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@dataclass
|
|
204
|
+
class LegendStyle:
|
|
205
|
+
"""Legend styling options."""
|
|
206
|
+
|
|
207
|
+
visible: bool = True
|
|
208
|
+
location: str = "best"
|
|
209
|
+
frameon: bool = True
|
|
210
|
+
ncols: int = 1
|
|
211
|
+
title: Optional[str] = None
|
|
212
|
+
|
|
213
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
214
|
+
result = {
|
|
215
|
+
"visible": self.visible,
|
|
216
|
+
"location": self.location,
|
|
217
|
+
"frameon": self.frameon,
|
|
218
|
+
"ncols": self.ncols,
|
|
219
|
+
}
|
|
220
|
+
if self.title:
|
|
221
|
+
result["title"] = self.title
|
|
222
|
+
return result
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def from_dict(cls, data: Dict[str, Any]) -> "LegendStyle":
|
|
226
|
+
if isinstance(data, bool):
|
|
227
|
+
return cls(visible=data)
|
|
228
|
+
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@dataclass
|
|
232
|
+
class PlotTheme:
|
|
233
|
+
"""
|
|
234
|
+
Complete theme specification for a plot.
|
|
235
|
+
|
|
236
|
+
Stored in theme.json. Contains pure aesthetics that can be
|
|
237
|
+
changed without affecting scientific interpretation.
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
colors : ColorScheme
|
|
242
|
+
Color scheme settings
|
|
243
|
+
typography : Typography
|
|
244
|
+
Font settings
|
|
245
|
+
line : LineDefaults
|
|
246
|
+
Default line style
|
|
247
|
+
marker : MarkerDefaults
|
|
248
|
+
Default marker style
|
|
249
|
+
traces : list of TraceStyle
|
|
250
|
+
Per-trace style overrides
|
|
251
|
+
legend : LegendStyle
|
|
252
|
+
Legend styling
|
|
253
|
+
grid : bool
|
|
254
|
+
Whether to show grid
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
colors: ColorScheme = field(default_factory=ColorScheme)
|
|
258
|
+
typography: Typography = field(default_factory=Typography)
|
|
259
|
+
line: LineDefaults = field(default_factory=LineDefaults)
|
|
260
|
+
marker: MarkerDefaults = field(default_factory=MarkerDefaults)
|
|
261
|
+
traces: List[TraceStyle] = field(default_factory=list)
|
|
262
|
+
legend: LegendStyle = field(default_factory=LegendStyle)
|
|
263
|
+
grid: bool = False
|
|
264
|
+
|
|
265
|
+
# Schema metadata
|
|
266
|
+
scitex_schema: str = "scitex.plt.theme"
|
|
267
|
+
scitex_schema_version: str = THEME_VERSION
|
|
268
|
+
|
|
269
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
270
|
+
return {
|
|
271
|
+
"schema": {
|
|
272
|
+
"name": self.scitex_schema,
|
|
273
|
+
"version": self.scitex_schema_version,
|
|
274
|
+
},
|
|
275
|
+
"colors": self.colors.to_dict(),
|
|
276
|
+
"typography": self.typography.to_dict(),
|
|
277
|
+
"line": self.line.to_dict(),
|
|
278
|
+
"marker": self.marker.to_dict(),
|
|
279
|
+
"traces": [t.to_dict() for t in self.traces],
|
|
280
|
+
"legend": self.legend.to_dict(),
|
|
281
|
+
"grid": self.grid,
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
def to_json(self, indent: int = 2) -> str:
|
|
285
|
+
return json.dumps(self.to_dict(), indent=indent)
|
|
286
|
+
|
|
287
|
+
@classmethod
|
|
288
|
+
def from_dict(cls, data: Dict[str, Any]) -> "PlotTheme":
|
|
289
|
+
return cls(
|
|
290
|
+
colors=ColorScheme.from_dict(data.get("colors", {})),
|
|
291
|
+
typography=Typography.from_dict(data.get("typography", {})),
|
|
292
|
+
line=LineDefaults.from_dict(data.get("line", {})),
|
|
293
|
+
marker=MarkerDefaults.from_dict(data.get("marker", {})),
|
|
294
|
+
traces=[TraceStyle.from_dict(t) for t in data.get("traces", [])],
|
|
295
|
+
legend=LegendStyle.from_dict(data.get("legend", {})),
|
|
296
|
+
grid=data.get("grid", False),
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
@classmethod
|
|
300
|
+
def from_json(cls, json_str: str) -> "PlotTheme":
|
|
301
|
+
return cls.from_dict(json.loads(json_str))
|
|
302
|
+
|
|
303
|
+
@classmethod
|
|
304
|
+
def from_style(cls, style: dict) -> "PlotTheme":
|
|
305
|
+
"""
|
|
306
|
+
Create theme from PlotStyle dict for backward compatibility.
|
|
307
|
+
"""
|
|
308
|
+
theme_data = style.get("theme", {})
|
|
309
|
+
font_data = style.get("font", {})
|
|
310
|
+
size_data = style.get("size", {})
|
|
311
|
+
|
|
312
|
+
return cls(
|
|
313
|
+
colors=ColorScheme(
|
|
314
|
+
mode=theme_data.get("mode", "light"),
|
|
315
|
+
background=theme_data.get("colors", {}).get(
|
|
316
|
+
"background", "transparent"
|
|
317
|
+
),
|
|
318
|
+
axes_bg=theme_data.get("colors", {}).get("axes_bg", "white"),
|
|
319
|
+
text=theme_data.get("colors", {}).get("text", "black"),
|
|
320
|
+
spine=theme_data.get("colors", {}).get("spine", "black"),
|
|
321
|
+
tick=theme_data.get("colors", {}).get("tick", "black"),
|
|
322
|
+
palette=theme_data.get("palette"),
|
|
323
|
+
),
|
|
324
|
+
typography=Typography(
|
|
325
|
+
family=font_data.get("family", "sans-serif"),
|
|
326
|
+
size_pt=font_data.get("size_pt", 7.0),
|
|
327
|
+
title_size_pt=font_data.get("title_size_pt", 8.0),
|
|
328
|
+
label_size_pt=font_data.get("label_size_pt", 7.0),
|
|
329
|
+
tick_size_pt=font_data.get("tick_size_pt", 6.0),
|
|
330
|
+
),
|
|
331
|
+
traces=[
|
|
332
|
+
TraceStyle(
|
|
333
|
+
trace_id=t.get("trace_id", ""),
|
|
334
|
+
color=t.get("color"),
|
|
335
|
+
linewidth=t.get("linewidth"),
|
|
336
|
+
linestyle=t.get("linestyle"),
|
|
337
|
+
marker=t.get("marker"),
|
|
338
|
+
markersize=t.get("markersize"),
|
|
339
|
+
alpha=t.get("alpha"),
|
|
340
|
+
)
|
|
341
|
+
for t in style.get("traces", [])
|
|
342
|
+
],
|
|
343
|
+
legend=LegendStyle.from_dict(style.get("legend", {})),
|
|
344
|
+
grid=style.get("grid", False),
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
__all__ = [
|
|
349
|
+
"THEME_VERSION",
|
|
350
|
+
"ColorScheme",
|
|
351
|
+
"Typography",
|
|
352
|
+
"LineDefaults",
|
|
353
|
+
"MarkerDefaults",
|
|
354
|
+
"TraceStyle",
|
|
355
|
+
"LegendStyle",
|
|
356
|
+
"PlotTheme",
|
|
357
|
+
]
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
# EOF
|
scitex/schema/_validation.py
CHANGED
|
@@ -439,103 +439,6 @@ def validate_stat_result(stat_data: Dict[str, Any]) -> bool:
|
|
|
439
439
|
return True
|
|
440
440
|
|
|
441
441
|
|
|
442
|
-
# =============================================================================
|
|
443
|
-
# Canvas Validation
|
|
444
|
-
# =============================================================================
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
def validate_canvas(canvas_data: Dict[str, Any]) -> bool:
|
|
448
|
-
"""
|
|
449
|
-
Validate a canvas specification.
|
|
450
|
-
|
|
451
|
-
Parameters
|
|
452
|
-
----------
|
|
453
|
-
canvas_data : Dict[str, Any]
|
|
454
|
-
Canvas specification dictionary
|
|
455
|
-
|
|
456
|
-
Returns
|
|
457
|
-
-------
|
|
458
|
-
bool
|
|
459
|
-
True if valid
|
|
460
|
-
|
|
461
|
-
Raises
|
|
462
|
-
------
|
|
463
|
-
ValidationError
|
|
464
|
-
If validation fails
|
|
465
|
-
"""
|
|
466
|
-
# canvas_name is required
|
|
467
|
-
if "canvas_name" not in canvas_data:
|
|
468
|
-
raise ValidationError(
|
|
469
|
-
"Missing required field: canvas_name",
|
|
470
|
-
field="canvas_name",
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
# Validate size
|
|
474
|
-
if "size" in canvas_data:
|
|
475
|
-
size = canvas_data["size"]
|
|
476
|
-
if not isinstance(size, dict):
|
|
477
|
-
raise ValidationError(
|
|
478
|
-
"size must be a dictionary",
|
|
479
|
-
field="size",
|
|
480
|
-
value=type(size).__name__,
|
|
481
|
-
)
|
|
482
|
-
|
|
483
|
-
width = size.get("width_mm", 0)
|
|
484
|
-
height = size.get("height_mm", 0)
|
|
485
|
-
|
|
486
|
-
if width <= 0:
|
|
487
|
-
raise ValidationError(
|
|
488
|
-
"width_mm must be positive",
|
|
489
|
-
field="size.width_mm",
|
|
490
|
-
value=width,
|
|
491
|
-
)
|
|
492
|
-
|
|
493
|
-
if height <= 0:
|
|
494
|
-
raise ValidationError(
|
|
495
|
-
"height_mm must be positive",
|
|
496
|
-
field="size.height_mm",
|
|
497
|
-
value=height,
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
# Validate panels
|
|
501
|
-
if "panels" in canvas_data:
|
|
502
|
-
if not isinstance(canvas_data["panels"], list):
|
|
503
|
-
raise ValidationError(
|
|
504
|
-
"panels must be a list",
|
|
505
|
-
field="panels",
|
|
506
|
-
value=type(canvas_data["panels"]).__name__,
|
|
507
|
-
)
|
|
508
|
-
|
|
509
|
-
# Check for duplicate panel names
|
|
510
|
-
panel_names = set()
|
|
511
|
-
for i, panel in enumerate(canvas_data["panels"]):
|
|
512
|
-
name = panel.get("name")
|
|
513
|
-
if not name:
|
|
514
|
-
raise ValidationError(
|
|
515
|
-
f"Panel at index {i} is missing 'name'",
|
|
516
|
-
field=f"panels[{i}].name",
|
|
517
|
-
)
|
|
518
|
-
|
|
519
|
-
if name in panel_names:
|
|
520
|
-
raise ValidationError(
|
|
521
|
-
f"Duplicate panel name: {name}",
|
|
522
|
-
field=f"panels[{i}].name",
|
|
523
|
-
value=name,
|
|
524
|
-
)
|
|
525
|
-
panel_names.add(name)
|
|
526
|
-
|
|
527
|
-
# Validate panel type
|
|
528
|
-
panel_type = panel.get("type", "image")
|
|
529
|
-
if panel_type not in {"scitex", "image"}:
|
|
530
|
-
raise ValidationError(
|
|
531
|
-
f"Invalid panel type: {panel_type}",
|
|
532
|
-
field=f"panels[{i}].type",
|
|
533
|
-
value=panel_type,
|
|
534
|
-
)
|
|
535
|
-
|
|
536
|
-
return True
|
|
537
|
-
|
|
538
|
-
|
|
539
442
|
# =============================================================================
|
|
540
443
|
# Color Validation
|
|
541
444
|
# =============================================================================
|
|
@@ -582,7 +485,6 @@ __all__ = [
|
|
|
582
485
|
"validate_axes",
|
|
583
486
|
"validate_plot",
|
|
584
487
|
"validate_stat_result",
|
|
585
|
-
"validate_canvas",
|
|
586
488
|
"validate_color",
|
|
587
489
|
]
|
|
588
490
|
|
scitex/scholar/__init__.py
CHANGED
|
@@ -13,21 +13,63 @@ Quick Start:
|
|
|
13
13
|
scholar = Scholar()
|
|
14
14
|
papers = scholar.search("deep learning")
|
|
15
15
|
papers.save("pac.bib")
|
|
16
|
-
"""
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
Installation:
|
|
18
|
+
pip install scitex[scholar]
|
|
19
|
+
"""
|
|
20
20
|
|
|
21
|
-
#
|
|
22
|
-
from scitex.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
from scitex.scholar.
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
# Check for missing dependencies and warn user
|
|
22
|
+
from scitex._install_guide import warn_module_deps
|
|
23
|
+
|
|
24
|
+
_missing = warn_module_deps("scholar")
|
|
25
|
+
|
|
26
|
+
# Import configuration - wrap all in try/except for graceful degradation
|
|
27
|
+
try:
|
|
28
|
+
from scitex.scholar.auth import ScholarAuthManager
|
|
29
|
+
except ImportError:
|
|
30
|
+
ScholarAuthManager = None
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
from scitex.scholar.browser import ScholarBrowserManager
|
|
34
|
+
except ImportError:
|
|
35
|
+
ScholarBrowserManager = None
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
from scitex.scholar.config import ScholarConfig
|
|
39
|
+
except ImportError:
|
|
40
|
+
ScholarConfig = None
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
from scitex.scholar.core import Paper, Papers, Scholar
|
|
44
|
+
except ImportError:
|
|
45
|
+
Paper = None
|
|
46
|
+
Papers = None
|
|
47
|
+
Scholar = None
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
from scitex.scholar.metadata_engines import ScholarEngine
|
|
51
|
+
except ImportError:
|
|
52
|
+
ScholarEngine = None
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
from scitex.scholar.pdf_download import ScholarPDFDownloader
|
|
56
|
+
except ImportError:
|
|
57
|
+
ScholarPDFDownloader = None
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
from scitex.scholar.storage import ScholarLibrary
|
|
61
|
+
except ImportError:
|
|
62
|
+
ScholarLibrary = None
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
from scitex.scholar.url_finder import ScholarURLFinder
|
|
66
|
+
except ImportError:
|
|
67
|
+
ScholarURLFinder = None
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
from . import utils
|
|
71
|
+
except ImportError:
|
|
72
|
+
utils = None
|
|
31
73
|
|
|
32
74
|
__all__ = [
|
|
33
75
|
"ScholarConfig",
|
|
@@ -240,7 +282,7 @@ __all__ = [
|
|
|
240
282
|
# # else:
|
|
241
283
|
# # return Scholar
|
|
242
284
|
|
|
243
|
-
# # from scitex.
|
|
285
|
+
# # from scitex.logging import ScholarError
|
|
244
286
|
# # raise ScholarError(
|
|
245
287
|
# # f"Module attribute not found: '{name}'",
|
|
246
288
|
# # context={"module": __name__, "attribute": name},
|
|
@@ -23,7 +23,7 @@ interface for authentication operations.
|
|
|
23
23
|
from typing import Any, Dict, List, Optional
|
|
24
24
|
|
|
25
25
|
from scitex import logging
|
|
26
|
-
from scitex.
|
|
26
|
+
from scitex.logging import AuthenticationError
|
|
27
27
|
from scitex.scholar.config import ScholarConfig
|
|
28
28
|
|
|
29
29
|
from .providers.BaseAuthenticator import BaseAuthenticator
|
scitex/scholar/auth/__init__.py
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"""Authentication module for Scholar."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Optional: requires browser dependencies (playwright, aiohttp)
|
|
4
|
+
try:
|
|
5
|
+
from .ScholarAuthManager import ScholarAuthManager
|
|
6
|
+
except ImportError:
|
|
7
|
+
ScholarAuthManager = None
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from .core.AuthenticationGateway import AuthenticationGateway, URLContext
|
|
11
|
+
except ImportError:
|
|
12
|
+
AuthenticationGateway = None
|
|
13
|
+
URLContext = None
|
|
5
14
|
|
|
6
15
|
__all__ = [
|
|
7
16
|
"ScholarAuthManager",
|
|
@@ -29,7 +29,7 @@ from typing import Any, Dict, List, Optional
|
|
|
29
29
|
from playwright.async_api import async_playwright
|
|
30
30
|
|
|
31
31
|
from scitex import logging
|
|
32
|
-
from scitex.
|
|
32
|
+
from scitex.logging import ScholarError
|
|
33
33
|
from scitex.scholar.config import ScholarConfig
|
|
34
34
|
|
|
35
35
|
from ..core.BrowserAuthenticator import BrowserAuthenticator
|
scitex/scholar/core/Scholar.py
CHANGED
|
@@ -35,7 +35,7 @@ from scitex import logging
|
|
|
35
35
|
import shutil
|
|
36
36
|
|
|
37
37
|
# PDF extraction is now handled by scitex.io
|
|
38
|
-
from scitex.
|
|
38
|
+
from scitex.logging import ScholarError
|
|
39
39
|
from scitex.scholar.config import ScholarConfig
|
|
40
40
|
|
|
41
41
|
# Updated imports for current architecture
|