scitex 2.10.3__py3-none-any.whl → 2.13.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 +1 -4
- scitex/__main__.py +24 -5
- scitex/__version__.py +1 -1
- scitex/_install_guide.py +14 -2
- scitex/_optional_deps.py +33 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
- scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
- scitex/ai/plt/_plot_feature_importance.py +1 -1
- scitex/ai/plt/_plot_learning_curve.py +1 -1
- scitex/ai/plt/_plot_optuna_study.py +1 -1
- scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
- scitex/ai/plt/_plot_roc_curve.py +1 -1
- scitex/ai/plt/_stx_conf_mat.py +1 -1
- scitex/ai/training/_LearningCurveLogger.py +1 -1
- scitex/audio/mcp_server.py +38 -8
- scitex/bridge/_figrecipe.py +1 -1
- scitex/bridge/_helpers.py +1 -1
- scitex/bridge/_plt_vis.py +1 -1
- scitex/bridge/_stats_plt.py +1 -1
- scitex/bridge/_stats_vis.py +2 -2
- scitex/browser/automation/CookieHandler.py +1 -1
- scitex/browser/core/BrowserMixin.py +1 -1
- scitex/browser/core/ChromeProfileManager.py +1 -1
- scitex/browser/debugging/_browser_logger.py +1 -1
- scitex/browser/debugging/_highlight_element.py +1 -1
- scitex/browser/debugging/_show_grid.py +1 -1
- scitex/browser/interaction/click_center.py +1 -1
- scitex/browser/interaction/click_with_fallbacks.py +1 -1
- scitex/browser/interaction/close_popups.py +1 -1
- scitex/browser/interaction/fill_with_fallbacks.py +1 -1
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
- scitex/browser/stealth/HumanBehavior.py +1 -1
- scitex/browser/stealth/StealthManager.py +1 -1
- scitex/{fig → canvas}/__init__.py +84 -96
- scitex/canvas/_mcp_handlers.py +372 -0
- scitex/canvas/_mcp_tool_schemas.py +219 -0
- scitex/{fig → canvas}/backend/_parser.py +1 -1
- scitex/{fig → canvas}/canvas.py +13 -14
- scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
- scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
- scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
- scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
- scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
- scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
- scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
- scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
- scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
- scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
- scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
- scitex/{fig → canvas}/io/__init__.py +32 -38
- scitex/{fig → canvas}/io/_bundle.py +217 -154
- scitex/{fig → canvas}/io/_canvas.py +1 -1
- scitex/{fig → canvas}/io/_data.py +1 -1
- scitex/{fig → canvas}/io/_export.py +1 -1
- scitex/{fig → canvas}/io/_load.py +1 -1
- scitex/{fig → canvas}/io/_panel.py +1 -1
- scitex/{fig → canvas}/io/_save.py +1 -1
- scitex/canvas/mcp_server.py +151 -0
- scitex/{fig → canvas}/model/__init__.py +1 -1
- scitex/{fig → canvas}/model/_annotations.py +1 -1
- scitex/{fig → canvas}/model/_axes.py +1 -1
- scitex/{fig → canvas}/model/_figure.py +1 -1
- scitex/{fig → canvas}/model/_guides.py +1 -1
- scitex/{fig → canvas}/model/_plot.py +1 -1
- scitex/{fig → canvas}/model/_styles.py +1 -1
- scitex/{fig → canvas}/utils/__init__.py +1 -1
- scitex/capture/mcp_server.py +41 -12
- scitex/cli/audio.py +233 -0
- scitex/cli/capture.py +307 -0
- scitex/cli/convert.py +10 -6
- scitex/cli/main.py +27 -4
- scitex/cli/repro.py +233 -0
- scitex/cli/resource.py +240 -0
- scitex/cli/stats.py +325 -0
- scitex/cli/template.py +236 -0
- scitex/cli/tex.py +286 -0
- scitex/cli/web.py +11 -12
- scitex/dev/__init__.py +3 -0
- scitex/dev/_pyproject.py +405 -0
- scitex/dev/plt/__init__.py +2 -2
- scitex/dev/plt/mpl/get_dir_ax.py +1 -1
- scitex/dev/plt/mpl/get_signatures.py +1 -1
- scitex/dev/plt/mpl/get_signatures_details.py +1 -1
- scitex/diagram/README.md +7 -7
- scitex/diagram/_mcp_handlers.py +400 -0
- scitex/diagram/_mcp_tool_schemas.py +157 -0
- scitex/diagram/mcp_server.py +151 -0
- scitex/dsp/_demo_sig.py +51 -5
- scitex/dsp/_mne.py +13 -2
- scitex/dsp/_modulation_index.py +15 -3
- scitex/dsp/_pac.py +23 -5
- scitex/dsp/_psd.py +16 -4
- scitex/dsp/_resample.py +24 -4
- scitex/dsp/_transform.py +16 -3
- scitex/dsp/add_noise.py +15 -1
- scitex/dsp/norm.py +17 -2
- scitex/dsp/reference.py +17 -1
- scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
- scitex/dsp/utils/_zero_pad.py +18 -4
- scitex/dt/_normalize_timestamp.py +1 -1
- scitex/git/_session.py +1 -1
- scitex/io/__init__.py +7 -19
- scitex/io/_load.py +15 -19
- scitex/io/_load_modules/_canvas.py +2 -2
- scitex/io/_load_modules/_con.py +17 -6
- scitex/io/_load_modules/_eeg.py +28 -13
- scitex/io/_load_modules/_optuna.py +21 -63
- scitex/io/_load_modules/_torch.py +11 -3
- scitex/io/_save.py +11 -16
- scitex/io/_save_modules/__init__.py +6 -10
- scitex/io/_save_modules/_canvas.py +3 -3
- scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
- scitex/io/_save_modules/_plot_bundle.py +112 -0
- scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
- scitex/io/_save_modules/_stx_bundle.py +16 -16
- scitex/io/_save_modules/_torch.py +11 -3
- scitex/io/bundle/README.md +89 -80
- scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
- scitex/io/bundle/__init__.py +67 -35
- scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
- scitex/io/bundle/_core.py +184 -97
- scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
- scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
- scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
- scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
- scitex/io/bundle/_manifest.py +99 -0
- scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
- scitex/io/bundle/_nested.py +113 -100
- scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
- scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
- scitex/io/bundle/_types.py +41 -16
- scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
- scitex/io/bundle/_zip.py +21 -31
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
- scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
- scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
- scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
- scitex/io/bundle/schemas/__init__.py +30 -0
- scitex/mcp_server.py +159 -0
- scitex/parallel/_run.py +5 -4
- scitex/path/_find.py +60 -83
- scitex/path/_get_module_path.py +23 -21
- scitex/path/_get_spath.py +6 -27
- scitex/path/_getsize.py +23 -9
- scitex/path/_increment_version.py +31 -38
- scitex/path/_mk_spath.py +26 -29
- scitex/path/_path.py +5 -12
- scitex/path/_split.py +27 -15
- scitex/path/_this_path.py +23 -9
- scitex/plt/_mcp_handlers.py +361 -0
- scitex/plt/_mcp_tool_schemas.py +169 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
- scitex/plt/gallery/_generate.py +76 -50
- scitex/plt/io/__init__.py +17 -19
- scitex/plt/io/_bundle.py +99 -52
- scitex/plt/io/_layered_bundle.py +303 -168
- scitex/plt/mcp_server.py +205 -0
- scitex/plt/utils/_csv_column_naming.py +250 -118
- scitex/repro/README_RandomStateManager.md +3 -3
- scitex/repro/_RandomStateManager.py +14 -14
- scitex/repro/_gen_ID.py +1 -1
- scitex/repro/_gen_timestamp.py +1 -1
- scitex/repro/_hash_array.py +4 -4
- scitex/schema/__init__.py +69 -73
- scitex/schema/_canvas.py +1 -1
- scitex/schema/_stats.py +2 -2
- scitex/scholar/__main__.py +24 -2
- scitex/scholar/_mcp_handlers.py +685 -0
- scitex/scholar/_mcp_tool_schemas.py +339 -0
- scitex/scholar/docs/template.py +1 -1
- scitex/scholar/examples/07_storage_integration.py +1 -1
- scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
- scitex/scholar/impact_factor/jcr/build_database.py +1 -1
- scitex/scholar/mcp_server.py +315 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
- scitex/scholar/storage/PaperIO.py +1 -1
- scitex/session/README.md +4 -4
- scitex/session/__init__.py +1 -1
- scitex/session/_decorator.py +9 -9
- scitex/session/_lifecycle.py +5 -5
- scitex/session/template.py +1 -1
- scitex/stats/__init__.py +30 -33
- scitex/stats/__main__.py +281 -0
- scitex/stats/_mcp_handlers.py +1191 -0
- scitex/stats/_mcp_tool_schemas.py +384 -0
- scitex/stats/_schema.py +1 -1
- scitex/stats/correct/_correct_bonferroni.py +1 -1
- scitex/stats/correct/_correct_fdr.py +1 -1
- scitex/stats/correct/_correct_fdr_.py +1 -1
- scitex/stats/correct/_correct_holm.py +1 -1
- scitex/stats/correct/_correct_sidak.py +1 -1
- scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
- scitex/stats/effect_sizes/_cohens_d.py +1 -1
- scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
- scitex/stats/effect_sizes/_eta_squared.py +1 -1
- scitex/stats/effect_sizes/_prob_superiority.py +1 -1
- scitex/stats/io/__init__.py +10 -11
- scitex/stats/io/_bundle.py +16 -16
- scitex/stats/mcp_server.py +405 -0
- scitex/stats/posthoc/_dunnett.py +1 -1
- scitex/stats/posthoc/_games_howell.py +1 -1
- scitex/stats/posthoc/_tukey_hsd.py +1 -1
- scitex/stats/power/_power.py +1 -1
- scitex/stats/utils/_effect_size.py +1 -1
- scitex/stats/utils/_formatters.py +1 -1
- scitex/stats/utils/_power.py +1 -1
- scitex/template/_mcp_handlers.py +259 -0
- scitex/template/_mcp_tool_schemas.py +112 -0
- scitex/template/mcp_server.py +186 -0
- scitex/utils/_verify_scitex_format.py +2 -2
- scitex/utils/template.py +1 -1
- scitex/web/__init__.py +12 -11
- scitex/web/_scraping.py +26 -265
- scitex/web/download_images.py +316 -0
- scitex/writer/Writer.py +1 -1
- scitex/writer/_clone_writer_project.py +1 -1
- scitex/writer/_validate_tree_structures.py +1 -1
- scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
- scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
- scitex/writer/dataclasses/core/_Document.py +1 -1
- scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
- scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
- scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
- scitex/writer/utils/.legacy_git_retry.py +7 -5
- scitex/writer/utils/_parse_latex_logs.py +1 -1
- scitex-2.13.0.dist-info/METADATA +1231 -0
- {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/RECORD +376 -470
- scitex-2.13.0.dist-info/entry_points.txt +11 -0
- scitex/fig/editor/_defaults.py +0 -300
- scitex/fig/editor/edit/panel_loader.py +0 -232
- scitex/fig/editor/flask_editor/_bbox.py +0 -1299
- scitex/fig/editor/flask_editor/_core.py +0 -1429
- scitex/fig/editor/flask_editor/_renderer.py +0 -813
- scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
- scitex/fts/README.md +0 -262
- scitex/fts/TODO.md +0 -66
- scitex/fts/__init__.py +0 -90
- scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
- scitex/fts/_bundle/__init__.py +0 -38
- scitex/fts/_bundle/_utils/__init__.py +0 -55
- scitex/fts/_bundle/_utils/_const.py +0 -26
- scitex/fts/_bundle/_utils/_errors.py +0 -73
- scitex/fts/_bundle/_utils/_generate.py +0 -21
- scitex/fts/_bundle/_utils/_types.py +0 -76
- scitex/fts/_bundle/_zipbundle.py +0 -165
- scitex/fts/_fig/__init__.py +0 -22
- scitex/fts/_fig/_backend/_parser.py +0 -188
- scitex/fts/_fig/_editor/__init__.py +0 -14
- scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
- scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
- scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
- scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
- scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
- scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
- scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
- scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
- scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
- scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
- scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
- scitex/fts/_fig/_models/_Annotations.py +0 -115
- scitex/fts/_fig/_models/_Axes.py +0 -152
- scitex/fts/_fig/_models/_Figure.py +0 -138
- scitex/fts/_fig/_models/_Plot.py +0 -123
- scitex/fts/_fig/_utils/_plot_layout.py +0 -397
- scitex/fts/_kinds/_figure/_composite.py +0 -345
- scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
- scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
- scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
- scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
- scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
- scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
- scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
- scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
- scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
- scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
- scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
- scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
- scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
- scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
- scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
- scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
- scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
- scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
- scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
- scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
- scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
- scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
- scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
- scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
- scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
- scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
- scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
- scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
- scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
- scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
- scitex/fts/_kinds/_table/_latex/_export.py +0 -279
- scitex/fts/_stats/__init__.py +0 -48
- scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
- scitex/fts/_stats/_dataclasses/__init__.py +0 -48
- scitex/fts/_tables/__init__.py +0 -65
- scitex/fts/_tables/_latex/__init__.py +0 -93
- scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
- scitex/fts/_tables/_latex/_editor/_app.py +0 -725
- scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
- scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
- scitex/fts/_tables/_latex/_table_exporter.py +0 -362
- scitex/fts/_tables/_latex/_utils.py +0 -369
- scitex/fts/_tables/_latex/_validator.py +0 -445
- scitex/io/_save_modules/_pltz_bundle.py +0 -356
- scitex-2.10.3.dist-info/METADATA +0 -952
- scitex-2.10.3.dist-info/entry_points.txt +0 -2
- /scitex/{fig → canvas}/README.md +0 -0
- /scitex/{fig → canvas}/backend/__init__.py +0 -0
- /scitex/{fig → canvas}/backend/_export.py +0 -0
- /scitex/{fig → canvas}/backend/_render.py +0 -0
- /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
- /scitex/{fig → canvas}/editor/__init__.py +0 -0
- /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
- /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
- /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
- /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
- /scitex/{fig → canvas}/io/_directory.py +0 -0
- /scitex/{fig → canvas}/model/_plot_types.py +0 -0
- /scitex/{fig → canvas}/utils/_defaults.py +0 -0
- /scitex/{fig → canvas}/utils/_validate.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
- {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
- {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -11,17 +11,17 @@ from ._ColumnDef import ColumnDef
|
|
|
11
11
|
from ._DataFormat import DataFormat
|
|
12
12
|
from ._DataInfo import DATA_INFO_VERSION, DataInfo
|
|
13
13
|
from ._DataSource import DataSource
|
|
14
|
-
from ._Node import Node, ShapeParams, TextContent
|
|
15
|
-
from ._NodeRefs import NodeRefs
|
|
16
14
|
from ._SizeMM import SizeMM
|
|
15
|
+
from ._Spec import ShapeParams, Spec, TextContent
|
|
16
|
+
from ._SpecRefs import SpecRefs
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
19
|
# Core models
|
|
20
20
|
"BBox",
|
|
21
21
|
"SizeMM",
|
|
22
22
|
"Axes",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"Spec",
|
|
24
|
+
"SpecRefs",
|
|
25
25
|
"TextContent",
|
|
26
26
|
"ShapeParams",
|
|
27
27
|
# Data Info
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# Timestamp: 2025-12-20
|
|
3
3
|
# File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_bundle/_loader.py
|
|
4
4
|
|
|
5
|
-
"""
|
|
5
|
+
"""SciTeX Bundle loading utilities.
|
|
6
6
|
|
|
7
7
|
Loads bundles using the new canonical/artifacts/payload/children structure.
|
|
8
|
-
Supports backwards compatibility with old flat structure (
|
|
8
|
+
Supports backwards compatibility with old flat structure (spec.json at root).
|
|
9
9
|
|
|
10
10
|
New structure:
|
|
11
11
|
canonical/spec.json (was node.json)
|
|
@@ -21,15 +21,15 @@ from typing import TYPE_CHECKING, Optional, Tuple
|
|
|
21
21
|
from ._storage import get_storage
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
|
-
from ._dataclasses import DataInfo,
|
|
25
|
-
from
|
|
26
|
-
from
|
|
24
|
+
from ._dataclasses import DataInfo, Spec
|
|
25
|
+
from .kinds._plot._dataclasses import Encoding, Theme
|
|
26
|
+
from .kinds._stats._dataclasses import Stats
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def load_bundle_components(
|
|
30
30
|
path: Path,
|
|
31
31
|
) -> Tuple[
|
|
32
|
-
Optional["
|
|
32
|
+
Optional["Spec"],
|
|
33
33
|
Optional["Encoding"],
|
|
34
34
|
Optional["Theme"],
|
|
35
35
|
Optional["Stats"],
|
|
@@ -43,15 +43,15 @@ def load_bundle_components(
|
|
|
43
43
|
path: Bundle path (directory or ZIP)
|
|
44
44
|
|
|
45
45
|
Returns:
|
|
46
|
-
Tuple of (
|
|
46
|
+
Tuple of (spec, encoding, theme, stats, data_info)
|
|
47
47
|
"""
|
|
48
|
-
from ._dataclasses import DataInfo,
|
|
49
|
-
from
|
|
50
|
-
from
|
|
48
|
+
from ._dataclasses import DataInfo, Spec
|
|
49
|
+
from .kinds._plot._dataclasses import Encoding, Theme
|
|
50
|
+
from .kinds._stats._dataclasses import Stats
|
|
51
51
|
|
|
52
52
|
storage = get_storage(path)
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
spec = None
|
|
55
55
|
encoding = None
|
|
56
56
|
theme = None
|
|
57
57
|
stats = None
|
|
@@ -59,7 +59,7 @@ def load_bundle_components(
|
|
|
59
59
|
|
|
60
60
|
# Detect structure: new (canonical/) or legacy (flat)
|
|
61
61
|
# - New: canonical/spec.json
|
|
62
|
-
# - Legacy
|
|
62
|
+
# - Legacy v1: node.json at root
|
|
63
63
|
# - Legacy sio.save(): spec.json at root
|
|
64
64
|
if storage.exists("canonical/spec.json"):
|
|
65
65
|
structure = "v2" # New canonical/ structure
|
|
@@ -69,15 +69,15 @@ def load_bundle_components(
|
|
|
69
69
|
structure = "v1" # Legacy node.json structure
|
|
70
70
|
is_new_structure = structure == "v2"
|
|
71
71
|
|
|
72
|
-
#
|
|
72
|
+
# Spec / spec.json
|
|
73
73
|
if structure == "v2":
|
|
74
|
-
|
|
74
|
+
spec_data = storage.read_json("canonical/spec.json")
|
|
75
75
|
elif structure == "sio":
|
|
76
|
-
|
|
76
|
+
spec_data = storage.read_json("spec.json")
|
|
77
77
|
else:
|
|
78
|
-
|
|
79
|
-
if
|
|
80
|
-
|
|
78
|
+
spec_data = storage.read_json("node.json")
|
|
79
|
+
if spec_data:
|
|
80
|
+
spec = Spec.from_dict(spec_data)
|
|
81
81
|
|
|
82
82
|
# Encoding
|
|
83
83
|
if is_new_structure:
|
|
@@ -111,7 +111,7 @@ def load_bundle_components(
|
|
|
111
111
|
if data_info_data:
|
|
112
112
|
data_info = DataInfo.from_dict(data_info_data)
|
|
113
113
|
|
|
114
|
-
return
|
|
114
|
+
return spec, encoding, theme, stats, data_info
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
def get_bundle_structure_version(path: Path) -> str:
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2026-01-07
|
|
3
|
+
# File: src/scitex/io/bundle/_manifest.py
|
|
4
|
+
|
|
5
|
+
"""Bundle manifest handling.
|
|
6
|
+
|
|
7
|
+
Manifests are JSON files inside bundles that identify the bundle type
|
|
8
|
+
and version. This provides a more reliable way to identify bundle types
|
|
9
|
+
than relying solely on file extensions.
|
|
10
|
+
|
|
11
|
+
Example manifest.json:
|
|
12
|
+
{
|
|
13
|
+
"scitex": {
|
|
14
|
+
"type": "plot",
|
|
15
|
+
"version": "1.0.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any, Dict, Optional
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"MANIFEST_FILENAME",
|
|
26
|
+
"create_manifest",
|
|
27
|
+
"write_manifest",
|
|
28
|
+
"read_manifest",
|
|
29
|
+
"get_type_from_manifest",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
MANIFEST_FILENAME = "manifest.json"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def create_manifest(bundle_type: str, version: str = "1.0.0") -> Dict[str, Any]:
|
|
36
|
+
"""Create a manifest dictionary.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
bundle_type: Type of bundle ('plot', 'figure', 'stats')
|
|
40
|
+
version: Bundle format version
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Manifest dictionary
|
|
44
|
+
"""
|
|
45
|
+
return {"scitex": {"type": bundle_type, "version": version}}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def write_manifest(bundle_path: Path, bundle_type: str, version: str = "1.0.0") -> None:
|
|
49
|
+
"""Write manifest.json to bundle directory.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
bundle_path: Path to bundle directory
|
|
53
|
+
bundle_type: Type of bundle
|
|
54
|
+
version: Bundle format version
|
|
55
|
+
"""
|
|
56
|
+
manifest = create_manifest(bundle_type, version)
|
|
57
|
+
manifest_path = Path(bundle_path) / MANIFEST_FILENAME
|
|
58
|
+
with open(manifest_path, "w") as f:
|
|
59
|
+
json.dump(manifest, f, indent=2)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def read_manifest(bundle_path: Path) -> Optional[Dict[str, Any]]:
|
|
63
|
+
"""Read manifest.json from bundle.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
bundle_path: Path to bundle (directory or ZIP)
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Manifest dictionary or None if not found
|
|
70
|
+
"""
|
|
71
|
+
bundle_path = Path(bundle_path)
|
|
72
|
+
manifest_path = bundle_path / MANIFEST_FILENAME
|
|
73
|
+
|
|
74
|
+
if not manifest_path.exists():
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
with open(manifest_path) as f:
|
|
79
|
+
return json.load(f)
|
|
80
|
+
except (OSError, json.JSONDecodeError):
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_type_from_manifest(bundle_path: Path) -> Optional[str]:
|
|
85
|
+
"""Get bundle type from manifest.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
bundle_path: Path to bundle
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Bundle type string or None if manifest not found/invalid
|
|
92
|
+
"""
|
|
93
|
+
manifest = read_manifest(bundle_path)
|
|
94
|
+
if manifest and "scitex" in manifest:
|
|
95
|
+
return manifest["scitex"].get("type")
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# EOF
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# Timestamp:
|
|
3
|
-
# File: /home/ywatanabe/proj/scitex-code/src/scitex/
|
|
2
|
+
# Timestamp: 2026-01-07
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/io/bundle/_mpl_helpers.py
|
|
4
4
|
|
|
5
|
-
"""Matplotlib helper functions for
|
|
5
|
+
"""Matplotlib helper functions for bundle creation."""
|
|
6
6
|
|
|
7
7
|
import warnings
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Optional
|
|
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from matplotlib.figure import Figure as MplFigure
|
|
12
12
|
|
|
13
|
-
from
|
|
13
|
+
from .kinds._plot._dataclasses import Encoding, Theme
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _get_scitex_axes(fig: "MplFigure") -> Optional[Any]:
|
|
@@ -33,16 +33,27 @@ def _get_scitex_axes(fig: "MplFigure") -> Optional[Any]:
|
|
|
33
33
|
return None
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def _simplify_csv_columns(csv_df: "Any") -> "Any":
|
|
37
|
+
"""CSV columns already use figrecipe-compatible format: r{row}c{col}_{caller}-{id}_{var}.
|
|
38
|
+
|
|
39
|
+
This function is now a pass-through since the new format is already simple and consistent.
|
|
40
|
+
Kept for backward compatibility with any code that calls it.
|
|
41
|
+
"""
|
|
42
|
+
# New format r{row}c{col}_{caller}-{id}_{var} is already simple
|
|
43
|
+
# No simplification needed
|
|
44
|
+
return csv_df
|
|
45
|
+
|
|
46
|
+
|
|
36
47
|
def _build_encoding_from_csv_columns(csv_df: "Any") -> "Encoding":
|
|
37
|
-
"""Build encoding from
|
|
48
|
+
"""Build encoding from CSV column names (simple or verbose format).
|
|
38
49
|
|
|
39
|
-
Handles
|
|
40
|
-
1.
|
|
41
|
-
2.
|
|
50
|
+
Handles:
|
|
51
|
+
1. Simple: x, y, trace_x, trace_y, ax0_0_trace_x
|
|
52
|
+
2. Verbose: ax-row-{row}-col-{col}_trace-id-{id}_variable-{var}
|
|
42
53
|
|
|
43
54
|
This ensures encoding references match actual data columns.
|
|
44
55
|
"""
|
|
45
|
-
from
|
|
56
|
+
from .kinds._plot._dataclasses import ChannelEncoding, Encoding, TraceEncoding
|
|
46
57
|
|
|
47
58
|
if csv_df is None or csv_df.empty:
|
|
48
59
|
return Encoding(traces=[])
|
|
@@ -89,7 +100,9 @@ def _build_encoding_from_csv_columns(csv_df: "Any") -> "Encoding":
|
|
|
89
100
|
if x_col is None:
|
|
90
101
|
x_col = numeric_cols[0]
|
|
91
102
|
if y_col is None:
|
|
92
|
-
y_col =
|
|
103
|
+
y_col = (
|
|
104
|
+
numeric_cols[1] if numeric_cols[1] != x_col else numeric_cols[0]
|
|
105
|
+
)
|
|
93
106
|
elif len(numeric_cols) == 1:
|
|
94
107
|
if x_col is None:
|
|
95
108
|
x_col = numeric_cols[0]
|
|
@@ -127,14 +140,10 @@ def validate_encoding_csv_link(encoding: "Encoding", csv_df: "Any") -> list:
|
|
|
127
140
|
for trace in encoding.traces:
|
|
128
141
|
if trace.x and trace.x.column:
|
|
129
142
|
if trace.x.column not in csv_columns:
|
|
130
|
-
errors.append(
|
|
131
|
-
f"Encoding references missing column: {trace.x.column}"
|
|
132
|
-
)
|
|
143
|
+
errors.append(f"Encoding references missing column: {trace.x.column}")
|
|
133
144
|
if trace.y and trace.y.column:
|
|
134
145
|
if trace.y.column not in csv_columns:
|
|
135
|
-
errors.append(
|
|
136
|
-
f"Encoding references missing column: {trace.y.column}"
|
|
137
|
-
)
|
|
146
|
+
errors.append(f"Encoding references missing column: {trace.y.column}")
|
|
138
147
|
|
|
139
148
|
return errors
|
|
140
149
|
|
|
@@ -183,18 +192,84 @@ def extract_data_from_mpl_figure(fig: "MplFigure") -> Optional[Any]:
|
|
|
183
192
|
return pd.DataFrame(padded)
|
|
184
193
|
|
|
185
194
|
|
|
195
|
+
def _build_encoding_from_history(
|
|
196
|
+
history: dict, ax_row: int = 0, ax_col: int = 0
|
|
197
|
+
) -> "Encoding":
|
|
198
|
+
"""Build encoding from scitex.plt axes history.
|
|
199
|
+
|
|
200
|
+
Converts tracking history to Encoding with column names matching
|
|
201
|
+
the figrecipe-compatible CSV format: r{row}c{col}_{caller}-{id}_{var}
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
history : dict
|
|
206
|
+
History dict: {trace_id: (trace_id, method, tracked_dict, kwargs)}
|
|
207
|
+
ax_row : int
|
|
208
|
+
Row position of axes in grid
|
|
209
|
+
ax_col : int
|
|
210
|
+
Column position of axes in grid
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
Encoding
|
|
215
|
+
Encoding object with traces referencing CSV column names.
|
|
216
|
+
"""
|
|
217
|
+
from scitex.plt.utils._csv_column_naming import get_csv_column_name, sanitize_id
|
|
218
|
+
|
|
219
|
+
from .kinds._plot._dataclasses import ChannelEncoding, Encoding, TraceEncoding
|
|
220
|
+
|
|
221
|
+
traces = []
|
|
222
|
+
|
|
223
|
+
# Track per-method counters for auto-generated IDs
|
|
224
|
+
method_counters = {}
|
|
225
|
+
|
|
226
|
+
for record_id, record in history.items():
|
|
227
|
+
if not isinstance(record, tuple) or len(record) < 4:
|
|
228
|
+
continue
|
|
229
|
+
|
|
230
|
+
id_val, method, tracked_dict, kwargs = record
|
|
231
|
+
|
|
232
|
+
# Extract user-provided id from kwargs if present
|
|
233
|
+
user_id = kwargs.get("id") if kwargs else None
|
|
234
|
+
|
|
235
|
+
# Determine trace_id: use user-provided id or auto-generate
|
|
236
|
+
if user_id:
|
|
237
|
+
trace_id = sanitize_id(user_id)
|
|
238
|
+
else:
|
|
239
|
+
# Auto-generate: per-method counter
|
|
240
|
+
counter = method_counters.get(method, 0)
|
|
241
|
+
method_counters[method] = counter + 1
|
|
242
|
+
trace_id = str(counter)
|
|
243
|
+
|
|
244
|
+
# Build column names using the new format
|
|
245
|
+
x_col = get_csv_column_name("x", ax_row, ax_col, method, trace_id=trace_id)
|
|
246
|
+
y_col = get_csv_column_name("y", ax_row, ax_col, method, trace_id=trace_id)
|
|
247
|
+
|
|
248
|
+
# Create trace encoding
|
|
249
|
+
trace = TraceEncoding(
|
|
250
|
+
trace_id=f"{method}-{trace_id}",
|
|
251
|
+
x=ChannelEncoding(column=x_col),
|
|
252
|
+
y=ChannelEncoding(column=y_col),
|
|
253
|
+
)
|
|
254
|
+
traces.append(trace)
|
|
255
|
+
|
|
256
|
+
return Encoding(traces=traces)
|
|
257
|
+
|
|
258
|
+
|
|
186
259
|
def build_encoding_from_mpl_figure(fig: "MplFigure") -> "Encoding":
|
|
187
260
|
"""Build encoding specification from matplotlib figure.
|
|
188
261
|
|
|
189
262
|
Uses scitex.plt tracking if available (captures actual plot method),
|
|
190
263
|
otherwise falls back to detecting from rendered figure.
|
|
191
264
|
"""
|
|
192
|
-
from
|
|
265
|
+
from .kinds._plot._dataclasses import Encoding
|
|
193
266
|
|
|
194
267
|
# Try scitex.plt tracking first (knows exact plot method)
|
|
195
268
|
scitex_ax = _get_scitex_axes(fig)
|
|
196
269
|
if scitex_ax is not None and hasattr(scitex_ax, "history") and scitex_ax.history:
|
|
197
|
-
|
|
270
|
+
encoding = _build_encoding_from_history(scitex_ax.history)
|
|
271
|
+
if encoding and encoding.traces:
|
|
272
|
+
return encoding
|
|
198
273
|
|
|
199
274
|
# Fallback: detect from rendered figure
|
|
200
275
|
from ._extractors import build_bar_traces, build_line_traces, build_scatter_traces
|
|
@@ -212,7 +287,7 @@ def build_encoding_from_mpl_figure(fig: "MplFigure") -> "Encoding":
|
|
|
212
287
|
|
|
213
288
|
def build_theme_from_mpl_figure(fig: "MplFigure") -> "Theme":
|
|
214
289
|
"""Build theme specification from matplotlib figure."""
|
|
215
|
-
from
|
|
290
|
+
from .kinds._plot._dataclasses import Theme
|
|
216
291
|
|
|
217
292
|
return Theme()
|
|
218
293
|
|
|
@@ -220,7 +295,10 @@ def build_theme_from_mpl_figure(fig: "MplFigure") -> "Theme":
|
|
|
220
295
|
def extract_geometry_from_mpl_figure(fig: "MplFigure") -> dict:
|
|
221
296
|
"""Extract geometry data from matplotlib figure for hit testing."""
|
|
222
297
|
try:
|
|
223
|
-
from scitex.plt.utils._hitmap import
|
|
298
|
+
from scitex.plt.utils._hitmap import (
|
|
299
|
+
extract_path_data,
|
|
300
|
+
extract_selectable_regions,
|
|
301
|
+
)
|
|
224
302
|
|
|
225
303
|
return {
|
|
226
304
|
"path_data": extract_path_data(fig),
|
|
@@ -257,7 +335,9 @@ def generate_hitmap_from_mpl_figure(fig: "MplFigure", dpi: int = 300) -> tuple:
|
|
|
257
335
|
png_buf = io.BytesIO()
|
|
258
336
|
with warnings.catch_warnings():
|
|
259
337
|
warnings.filterwarnings("ignore", message=".*tight_layout.*")
|
|
260
|
-
fig.savefig(
|
|
338
|
+
fig.savefig(
|
|
339
|
+
png_buf, format="png", dpi=dpi, facecolor=HITMAP_BACKGROUND_COLOR
|
|
340
|
+
)
|
|
261
341
|
png_bytes = png_buf.getvalue()
|
|
262
342
|
|
|
263
343
|
svg_buf = io.BytesIO()
|
|
@@ -283,7 +363,7 @@ def from_matplotlib(
|
|
|
283
363
|
csv_df: Optional[Any] = None,
|
|
284
364
|
dpi: int = 300,
|
|
285
365
|
):
|
|
286
|
-
"""Create
|
|
366
|
+
"""Create Bundle from matplotlib figure.
|
|
287
367
|
|
|
288
368
|
Args:
|
|
289
369
|
fig: Matplotlib figure object
|
|
@@ -300,7 +380,7 @@ def from_matplotlib(
|
|
|
300
380
|
import json
|
|
301
381
|
from pathlib import Path
|
|
302
382
|
|
|
303
|
-
from .
|
|
383
|
+
from ._Bundle import Bundle
|
|
304
384
|
from ._saver import save_bundle_components
|
|
305
385
|
|
|
306
386
|
path = Path(path)
|
|
@@ -311,13 +391,18 @@ def from_matplotlib(
|
|
|
311
391
|
"height": round(fig_height_inch * 25.4, 2),
|
|
312
392
|
}
|
|
313
393
|
|
|
314
|
-
bundle =
|
|
394
|
+
bundle = Bundle(path, create=True, kind="plot", name=name, size_mm=size_mm)
|
|
315
395
|
|
|
316
396
|
if csv_df is None:
|
|
317
397
|
csv_df = extract_data_from_mpl_figure(fig)
|
|
318
398
|
|
|
319
399
|
if csv_df is not None and not csv_df.empty:
|
|
320
|
-
bundle.
|
|
400
|
+
bundle._spec.payload_schema = "scitex.io.bundle.payload.plot@1"
|
|
401
|
+
|
|
402
|
+
# Simplify CSV column names for bundle (figrecipe-style)
|
|
403
|
+
# Converts: ax-row-0-col-0_trace-id-sine_variable-x → sine_x (or just x)
|
|
404
|
+
if csv_df is not None and not csv_df.empty:
|
|
405
|
+
csv_df = _simplify_csv_columns(csv_df)
|
|
321
406
|
|
|
322
407
|
# Build encoding from actual CSV columns (single source of truth)
|
|
323
408
|
# This ensures encoding references match real data columns
|
|
@@ -342,7 +427,9 @@ def from_matplotlib(
|
|
|
342
427
|
"dtypes": {col: str(dtype) for col, dtype in csv_df.dtypes.items()},
|
|
343
428
|
"shape": list(csv_df.shape),
|
|
344
429
|
}
|
|
345
|
-
storage.write(
|
|
430
|
+
storage.write(
|
|
431
|
+
"canonical/data_info.json", json.dumps(data_info, indent=2).encode()
|
|
432
|
+
)
|
|
346
433
|
|
|
347
434
|
for fmt in ["png", "svg", "pdf"]:
|
|
348
435
|
buf = io.BytesIO()
|
|
@@ -353,7 +440,9 @@ def from_matplotlib(
|
|
|
353
440
|
|
|
354
441
|
geometry = extract_geometry_from_mpl_figure(fig)
|
|
355
442
|
geometry["space"] = "figure_px"
|
|
356
|
-
storage.write(
|
|
443
|
+
storage.write(
|
|
444
|
+
"artifacts/cache/geometry_px.json", json.dumps(geometry, indent=2).encode()
|
|
445
|
+
)
|
|
357
446
|
|
|
358
447
|
hitmap_png, hitmap_svg = generate_hitmap_from_mpl_figure(fig, dpi)
|
|
359
448
|
if hitmap_png:
|
|
@@ -362,7 +451,9 @@ def from_matplotlib(
|
|
|
362
451
|
storage.write("artifacts/cache/hitmap.svg", hitmap_svg)
|
|
363
452
|
|
|
364
453
|
manifest = {"dpi": dpi, "formats": ["png", "svg", "pdf"], "size_mm": size_mm}
|
|
365
|
-
storage.write(
|
|
454
|
+
storage.write(
|
|
455
|
+
"artifacts/cache/render_manifest.json", json.dumps(manifest, indent=2).encode()
|
|
456
|
+
)
|
|
366
457
|
|
|
367
458
|
save_bundle_components(
|
|
368
459
|
path,
|