scitex 2.10.3__py3-none-any.whl → 2.11.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/__version__.py +1 -1
- scitex/_install_guide.py +14 -2
- 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/{fig → canvas}/__init__.py +84 -96
- 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/{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/cli/convert.py +10 -6
- scitex/diagram/README.md +7 -7
- 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 +5 -5
- scitex/io/_load_modules/_eeg.py +16 -12
- 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/_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/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/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/_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/utils/_csv_column_naming.py +250 -118
- scitex/schema/__init__.py +69 -73
- scitex/schema/_canvas.py +1 -1
- scitex/schema/_stats.py +2 -2
- scitex/stats/__init__.py +30 -33
- scitex/stats/_schema.py +1 -1
- scitex/stats/io/__init__.py +10 -11
- scitex/stats/io/_bundle.py +16 -16
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/METADATA +190 -73
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/RECORD +237 -360
- 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/{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.11.0.dist-info}/WHEEL +0 -0
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# File: ./src/scitex/vis/editor/_flask_editor.py
|
|
3
|
-
"""Web-based figure editor using Flask.
|
|
4
|
-
|
|
5
|
-
This module re-exports from the flask_editor package for backward compatibility.
|
|
6
|
-
The actual implementation is in the flask_editor/ subpackage.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from ._flask_editor import (
|
|
10
|
-
WebEditor,
|
|
11
|
-
check_port_available,
|
|
12
|
-
find_available_port,
|
|
13
|
-
kill_process_on_port,
|
|
14
|
-
plot_from_csv,
|
|
15
|
-
render_preview_with_bboxes,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
# Legacy aliases for backward compatibility
|
|
19
|
-
_find_available_port = find_available_port
|
|
20
|
-
_kill_process_on_port = kill_process_on_port
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
__all__ = [
|
|
24
|
-
"WebEditor",
|
|
25
|
-
"find_available_port",
|
|
26
|
-
"kill_process_on_port",
|
|
27
|
-
"check_port_available",
|
|
28
|
-
"render_preview_with_bboxes",
|
|
29
|
-
"plot_from_csv",
|
|
30
|
-
# Legacy aliases
|
|
31
|
-
"_find_available_port",
|
|
32
|
-
"_kill_process_on_port",
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# EOF
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# File: ./src/scitex/vis/model/annotations.py
|
|
3
|
-
"""Annotation JSON model for scitex.fig."""
|
|
4
|
-
|
|
5
|
-
from dataclasses import asdict, dataclass, field
|
|
6
|
-
from typing import Any, Dict, Optional, Tuple
|
|
7
|
-
|
|
8
|
-
from ._Styles import TextStyle
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class AnnotationModel:
|
|
13
|
-
"""
|
|
14
|
-
Annotation model for text, arrows, and shapes on plots.
|
|
15
|
-
|
|
16
|
-
Separates structure from style properties for easier:
|
|
17
|
-
- UI property panel generation
|
|
18
|
-
- Style copy/paste
|
|
19
|
-
- Batch style application
|
|
20
|
-
|
|
21
|
-
Supports:
|
|
22
|
-
- text: Simple text annotations
|
|
23
|
-
- annotate: Text with optional arrows
|
|
24
|
-
- arrow: Arrows without text
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
# Annotation type
|
|
28
|
-
annotation_type: str # "text", "annotate", "arrow"
|
|
29
|
-
|
|
30
|
-
# Text content
|
|
31
|
-
text: Optional[str] = None
|
|
32
|
-
|
|
33
|
-
# Position (data coordinates)
|
|
34
|
-
x: float = 0.0
|
|
35
|
-
y: float = 0.0
|
|
36
|
-
|
|
37
|
-
# For annotate: arrow properties
|
|
38
|
-
xytext: Optional[Tuple[float, float]] = None # Text position
|
|
39
|
-
|
|
40
|
-
# Annotation ID for reference
|
|
41
|
-
annotation_id: Optional[str] = None
|
|
42
|
-
|
|
43
|
-
# Style properties (separated for clean UI/copy/paste)
|
|
44
|
-
style: TextStyle = field(default_factory=TextStyle)
|
|
45
|
-
|
|
46
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
47
|
-
"""Convert to dictionary for JSON serialization."""
|
|
48
|
-
d = asdict(self)
|
|
49
|
-
# Convert tuples to lists for JSON compatibility
|
|
50
|
-
if d.get("xytext") is not None:
|
|
51
|
-
d["xytext"] = list(d["xytext"])
|
|
52
|
-
d["style"] = self.style.to_dict()
|
|
53
|
-
return d
|
|
54
|
-
|
|
55
|
-
@classmethod
|
|
56
|
-
def from_dict(cls, data: Dict[str, Any]) -> "AnnotationModel":
|
|
57
|
-
"""Create AnnotationModel from dictionary."""
|
|
58
|
-
# Convert lists back to tuples
|
|
59
|
-
if "xytext" in data and data["xytext"] is not None:
|
|
60
|
-
data["xytext"] = tuple(data["xytext"])
|
|
61
|
-
|
|
62
|
-
# Handle old format (backward compatibility)
|
|
63
|
-
if "style" not in data:
|
|
64
|
-
# Extract style properties from flat structure
|
|
65
|
-
style_fields = TextStyle.__annotations__.keys()
|
|
66
|
-
style_data = {k: v for k, v in data.items() if k in style_fields}
|
|
67
|
-
data = {k: v for k, v in data.items() if k not in style_fields}
|
|
68
|
-
data["style"] = style_data
|
|
69
|
-
|
|
70
|
-
# Extract and parse style
|
|
71
|
-
style_data = data.pop("style", {})
|
|
72
|
-
obj = cls(**{k: v for k, v in data.items() if k in cls.__annotations__})
|
|
73
|
-
obj.style = TextStyle.from_dict(style_data)
|
|
74
|
-
return obj
|
|
75
|
-
|
|
76
|
-
def validate(self) -> bool:
|
|
77
|
-
"""
|
|
78
|
-
Validate the annotation model.
|
|
79
|
-
|
|
80
|
-
Returns
|
|
81
|
-
-------
|
|
82
|
-
bool
|
|
83
|
-
True if valid, raises ValueError otherwise
|
|
84
|
-
"""
|
|
85
|
-
valid_annotation_types = ["text", "annotate", "arrow"]
|
|
86
|
-
|
|
87
|
-
if self.annotation_type not in valid_annotation_types:
|
|
88
|
-
raise ValueError(
|
|
89
|
-
f"Invalid annotation_type: {self.annotation_type}. "
|
|
90
|
-
f"Must be one of {valid_annotation_types}"
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
# Type-specific validation
|
|
94
|
-
if self.annotation_type in ["text", "annotate"]:
|
|
95
|
-
if not self.text:
|
|
96
|
-
raise ValueError(f"{self.annotation_type} requires 'text' parameter")
|
|
97
|
-
|
|
98
|
-
if self.annotation_type == "annotate":
|
|
99
|
-
if self.xytext is None:
|
|
100
|
-
raise ValueError("annotate requires 'xytext' parameter")
|
|
101
|
-
|
|
102
|
-
# Validate alignment (now in style)
|
|
103
|
-
valid_ha = ["left", "center", "right"]
|
|
104
|
-
valid_va = ["top", "center", "bottom", "baseline"]
|
|
105
|
-
|
|
106
|
-
if self.style.ha not in valid_ha:
|
|
107
|
-
raise ValueError(f"Invalid ha: {self.style.ha}. Must be one of {valid_ha}")
|
|
108
|
-
|
|
109
|
-
if self.style.va not in valid_va:
|
|
110
|
-
raise ValueError(f"Invalid va: {self.style.va}. Must be one of {valid_va}")
|
|
111
|
-
|
|
112
|
-
return True
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
# EOF
|
scitex/fts/_fig/_models/_Axes.py
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# File: ./src/scitex/vis/model/axes.py
|
|
3
|
-
"""Axes JSON model for scitex.fig."""
|
|
4
|
-
|
|
5
|
-
from dataclasses import asdict, dataclass, field
|
|
6
|
-
from typing import Any, Dict, List, Optional
|
|
7
|
-
|
|
8
|
-
from ._Styles import AxesStyle
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class AxesModel:
|
|
13
|
-
"""
|
|
14
|
-
Axes model representing a single subplot.
|
|
15
|
-
|
|
16
|
-
Separates structure/data from style properties for easier:
|
|
17
|
-
- UI property panel generation
|
|
18
|
-
- Style copy/paste
|
|
19
|
-
- Batch style application
|
|
20
|
-
|
|
21
|
-
Contains all configuration for one subplot including:
|
|
22
|
-
- Plot data and type
|
|
23
|
-
- Axis labels, limits, scales
|
|
24
|
-
- Legends, titles
|
|
25
|
-
- Annotations and guides
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
# Position in layout (0-based)
|
|
29
|
-
row: int = 0
|
|
30
|
-
col: int = 0
|
|
31
|
-
|
|
32
|
-
# Plot configurations (list of PlotModel)
|
|
33
|
-
plots: List[Dict[str, Any]] = field(default_factory=list)
|
|
34
|
-
|
|
35
|
-
# Axis labels and titles (content, not style)
|
|
36
|
-
xlabel: Optional[str] = None
|
|
37
|
-
ylabel: Optional[str] = None
|
|
38
|
-
title: Optional[str] = None
|
|
39
|
-
|
|
40
|
-
# Axis limits
|
|
41
|
-
xlim: Optional[List[float]] = None
|
|
42
|
-
ylim: Optional[List[float]] = None
|
|
43
|
-
|
|
44
|
-
# Axis scales
|
|
45
|
-
xscale: str = "linear" # "linear", "log", "symlog", "logit"
|
|
46
|
-
yscale: str = "linear"
|
|
47
|
-
|
|
48
|
-
# Ticks
|
|
49
|
-
xticks: Optional[List[float]] = None
|
|
50
|
-
yticks: Optional[List[float]] = None
|
|
51
|
-
xticklabels: Optional[List[str]] = None
|
|
52
|
-
yticklabels: Optional[List[str]] = None
|
|
53
|
-
|
|
54
|
-
# Annotations (list of AnnotationModel)
|
|
55
|
-
annotations: List[Dict[str, Any]] = field(default_factory=list)
|
|
56
|
-
|
|
57
|
-
# Guides (lines, spans, etc.)
|
|
58
|
-
guides: List[Dict[str, Any]] = field(default_factory=list)
|
|
59
|
-
|
|
60
|
-
# Axes ID for reference
|
|
61
|
-
axes_id: Optional[str] = None
|
|
62
|
-
|
|
63
|
-
# Style properties (separated for clean UI/copy/paste)
|
|
64
|
-
style: AxesStyle = field(default_factory=AxesStyle)
|
|
65
|
-
|
|
66
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
67
|
-
"""Convert to dictionary for JSON serialization."""
|
|
68
|
-
d = asdict(self)
|
|
69
|
-
d["style"] = self.style.to_dict()
|
|
70
|
-
return d
|
|
71
|
-
|
|
72
|
-
@classmethod
|
|
73
|
-
def from_dict(cls, data: Dict[str, Any]) -> "AxesModel":
|
|
74
|
-
"""Create AxesModel from dictionary."""
|
|
75
|
-
# Handle old format (backward compatibility)
|
|
76
|
-
if "style" not in data:
|
|
77
|
-
# Extract style properties from flat structure
|
|
78
|
-
style_fields = AxesStyle.__annotations__.keys()
|
|
79
|
-
style_data = {k: v for k, v in data.items() if k in style_fields}
|
|
80
|
-
data = {k: v for k, v in data.items() if k not in style_fields}
|
|
81
|
-
data["style"] = style_data
|
|
82
|
-
|
|
83
|
-
# Extract and parse style
|
|
84
|
-
style_data = data.pop("style", {})
|
|
85
|
-
obj = cls(**{k: v for k, v in data.items() if k in cls.__annotations__})
|
|
86
|
-
obj.style = AxesStyle.from_dict(style_data)
|
|
87
|
-
return obj
|
|
88
|
-
|
|
89
|
-
def add_plot(self, plot_config: Dict[str, Any]) -> None:
|
|
90
|
-
"""
|
|
91
|
-
Add a plot configuration to this axes.
|
|
92
|
-
|
|
93
|
-
Parameters
|
|
94
|
-
----------
|
|
95
|
-
plot_config : Dict[str, Any]
|
|
96
|
-
Plot configuration dictionary
|
|
97
|
-
"""
|
|
98
|
-
self.plots.append(plot_config)
|
|
99
|
-
|
|
100
|
-
def add_annotation(self, annotation_config: Dict[str, Any]) -> None:
|
|
101
|
-
"""
|
|
102
|
-
Add an annotation to this axes.
|
|
103
|
-
|
|
104
|
-
Parameters
|
|
105
|
-
----------
|
|
106
|
-
annotation_config : Dict[str, Any]
|
|
107
|
-
Annotation configuration dictionary
|
|
108
|
-
"""
|
|
109
|
-
self.annotations.append(annotation_config)
|
|
110
|
-
|
|
111
|
-
def add_guide(self, guide_config: Dict[str, Any]) -> None:
|
|
112
|
-
"""
|
|
113
|
-
Add a guide (line, span, etc.) to this axes.
|
|
114
|
-
|
|
115
|
-
Parameters
|
|
116
|
-
----------
|
|
117
|
-
guide_config : Dict[str, Any]
|
|
118
|
-
Guide configuration dictionary
|
|
119
|
-
"""
|
|
120
|
-
self.guides.append(guide_config)
|
|
121
|
-
|
|
122
|
-
def validate(self) -> bool:
|
|
123
|
-
"""
|
|
124
|
-
Validate the axes model.
|
|
125
|
-
|
|
126
|
-
Returns
|
|
127
|
-
-------
|
|
128
|
-
bool
|
|
129
|
-
True if valid, raises ValueError otherwise
|
|
130
|
-
"""
|
|
131
|
-
if self.row < 0:
|
|
132
|
-
raise ValueError(f"row must be non-negative, got {self.row}")
|
|
133
|
-
|
|
134
|
-
if self.col < 0:
|
|
135
|
-
raise ValueError(f"col must be non-negative, got {self.col}")
|
|
136
|
-
|
|
137
|
-
if self.xscale not in ["linear", "log", "symlog", "logit"]:
|
|
138
|
-
raise ValueError(f"Invalid xscale: {self.xscale}")
|
|
139
|
-
|
|
140
|
-
if self.yscale not in ["linear", "log", "symlog", "logit"]:
|
|
141
|
-
raise ValueError(f"Invalid yscale: {self.yscale}")
|
|
142
|
-
|
|
143
|
-
if self.xlim is not None and len(self.xlim) != 2:
|
|
144
|
-
raise ValueError(f"xlim must have 2 elements, got {len(self.xlim)}")
|
|
145
|
-
|
|
146
|
-
if self.ylim is not None and len(self.ylim) != 2:
|
|
147
|
-
raise ValueError(f"ylim must have 2 elements, got {len(self.ylim)}")
|
|
148
|
-
|
|
149
|
-
return True
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# EOF
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# File: ./src/scitex/vis/model/figure.py
|
|
3
|
-
"""Figure JSON model for scitex.fig."""
|
|
4
|
-
|
|
5
|
-
from dataclasses import asdict, dataclass, field
|
|
6
|
-
from typing import Any, Dict, List, Optional
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@dataclass
|
|
10
|
-
class FigureModel:
|
|
11
|
-
"""
|
|
12
|
-
Top-level figure model representing a complete publication figure.
|
|
13
|
-
|
|
14
|
-
This model captures all information needed to recreate a figure:
|
|
15
|
-
- Physical dimensions (mm units)
|
|
16
|
-
- Subplot layout
|
|
17
|
-
- Individual axes configurations
|
|
18
|
-
- Global figure properties
|
|
19
|
-
|
|
20
|
-
All measurements use mm units for publication compatibility.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
# Physical dimensions (mm)
|
|
24
|
-
width_mm: float
|
|
25
|
-
height_mm: float
|
|
26
|
-
|
|
27
|
-
# Subplot layout
|
|
28
|
-
nrows: int = 1
|
|
29
|
-
ncols: int = 1
|
|
30
|
-
|
|
31
|
-
# Axes configurations (list of AxesModel)
|
|
32
|
-
axes: List[Dict[str, Any]] = field(default_factory=list)
|
|
33
|
-
|
|
34
|
-
# Figure-level properties
|
|
35
|
-
dpi: int = 300
|
|
36
|
-
facecolor: str = "white"
|
|
37
|
-
edgecolor: str = "none"
|
|
38
|
-
|
|
39
|
-
# Spacing (mm)
|
|
40
|
-
left_mm: Optional[float] = None
|
|
41
|
-
right_mm: Optional[float] = None
|
|
42
|
-
top_mm: Optional[float] = None
|
|
43
|
-
bottom_mm: Optional[float] = None
|
|
44
|
-
wspace_mm: Optional[float] = None
|
|
45
|
-
hspace_mm: Optional[float] = None
|
|
46
|
-
|
|
47
|
-
# Suptitle
|
|
48
|
-
suptitle: Optional[str] = None
|
|
49
|
-
suptitle_fontsize: Optional[float] = None
|
|
50
|
-
suptitle_fontweight: Optional[str] = None
|
|
51
|
-
suptitle_y: Optional[float] = None
|
|
52
|
-
|
|
53
|
-
# Metadata
|
|
54
|
-
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
55
|
-
|
|
56
|
-
# Figure ID for tracking
|
|
57
|
-
figure_id: Optional[str] = None
|
|
58
|
-
|
|
59
|
-
# Version for schema evolution
|
|
60
|
-
schema_version: str = "1.0.0"
|
|
61
|
-
|
|
62
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
63
|
-
"""Convert to dictionary for JSON serialization."""
|
|
64
|
-
return asdict(self)
|
|
65
|
-
|
|
66
|
-
@classmethod
|
|
67
|
-
def from_dict(cls, data: Dict[str, Any]) -> "FigureModel":
|
|
68
|
-
"""Create FigureModel from dictionary."""
|
|
69
|
-
return cls(**data)
|
|
70
|
-
|
|
71
|
-
def validate(self) -> bool:
|
|
72
|
-
"""
|
|
73
|
-
Validate the figure model.
|
|
74
|
-
|
|
75
|
-
Returns
|
|
76
|
-
-------
|
|
77
|
-
bool
|
|
78
|
-
True if valid, raises ValueError otherwise
|
|
79
|
-
"""
|
|
80
|
-
if self.width_mm <= 0:
|
|
81
|
-
raise ValueError(f"width_mm must be positive, got {self.width_mm}")
|
|
82
|
-
|
|
83
|
-
if self.height_mm <= 0:
|
|
84
|
-
raise ValueError(f"height_mm must be positive, got {self.height_mm}")
|
|
85
|
-
|
|
86
|
-
if self.nrows <= 0:
|
|
87
|
-
raise ValueError(f"nrows must be positive, got {self.nrows}")
|
|
88
|
-
|
|
89
|
-
if self.ncols <= 0:
|
|
90
|
-
raise ValueError(f"ncols must be positive, got {self.ncols}")
|
|
91
|
-
|
|
92
|
-
if self.dpi <= 0:
|
|
93
|
-
raise ValueError(f"dpi must be positive, got {self.dpi}")
|
|
94
|
-
|
|
95
|
-
# Validate that axes count matches layout
|
|
96
|
-
expected_axes = self.nrows * self.ncols
|
|
97
|
-
if len(self.axes) > expected_axes:
|
|
98
|
-
raise ValueError(
|
|
99
|
-
f"Too many axes: expected {expected_axes} for {self.nrows}x{self.ncols} layout, "
|
|
100
|
-
f"got {len(self.axes)}"
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
return True
|
|
104
|
-
|
|
105
|
-
def get_axes_by_position(self, row: int, col: int) -> Optional[Dict[str, Any]]:
|
|
106
|
-
"""
|
|
107
|
-
Get axes configuration by subplot position.
|
|
108
|
-
|
|
109
|
-
Parameters
|
|
110
|
-
----------
|
|
111
|
-
row : int
|
|
112
|
-
Row index (0-based)
|
|
113
|
-
col : int
|
|
114
|
-
Column index (0-based)
|
|
115
|
-
|
|
116
|
-
Returns
|
|
117
|
-
-------
|
|
118
|
-
Optional[Dict[str, Any]]
|
|
119
|
-
Axes configuration or None if not found
|
|
120
|
-
"""
|
|
121
|
-
idx = row * self.ncols + col
|
|
122
|
-
if idx < len(self.axes):
|
|
123
|
-
return self.axes[idx]
|
|
124
|
-
return None
|
|
125
|
-
|
|
126
|
-
def add_axes(self, axes_config: Dict[str, Any]) -> None:
|
|
127
|
-
"""
|
|
128
|
-
Add an axes configuration to the figure.
|
|
129
|
-
|
|
130
|
-
Parameters
|
|
131
|
-
----------
|
|
132
|
-
axes_config : Dict[str, Any]
|
|
133
|
-
Axes configuration dictionary
|
|
134
|
-
"""
|
|
135
|
-
self.axes.append(axes_config)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# EOF
|
scitex/fts/_fig/_models/_Plot.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# File: ./src/scitex/vis/model/plot.py
|
|
3
|
-
"""Plot JSON model for scitex.fig."""
|
|
4
|
-
|
|
5
|
-
from dataclasses import asdict, dataclass, field
|
|
6
|
-
from typing import Any, Dict, List, Optional
|
|
7
|
-
|
|
8
|
-
from ._Styles import PlotStyle
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class PlotModel:
|
|
13
|
-
"""
|
|
14
|
-
Plot model representing a single data visualization within an axes.
|
|
15
|
-
|
|
16
|
-
Separates data/structure from style properties for easier:
|
|
17
|
-
- UI property panel generation
|
|
18
|
-
- Style copy/paste
|
|
19
|
-
- Batch style application
|
|
20
|
-
|
|
21
|
-
Supports common plot types:
|
|
22
|
-
- line, scatter, bar, barh, hist
|
|
23
|
-
- errorbar, fill_between
|
|
24
|
-
- heatmap, imshow, contour, contourf
|
|
25
|
-
- box, violin
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
# Plot type
|
|
29
|
-
plot_type: str # "line", "scatter", "bar", "errorbar", "heatmap", etc.
|
|
30
|
-
|
|
31
|
-
# Data (can be embedded or referenced)
|
|
32
|
-
data: Dict[str, Any] = field(default_factory=dict)
|
|
33
|
-
|
|
34
|
-
# Human-readable identifiers
|
|
35
|
-
plot_id: Optional[str] = None
|
|
36
|
-
label: Optional[str] = None
|
|
37
|
-
tags: List[str] = field(default_factory=list)
|
|
38
|
-
|
|
39
|
-
# Style properties (separated for clean UI/copy/paste)
|
|
40
|
-
style: PlotStyle = field(default_factory=PlotStyle)
|
|
41
|
-
|
|
42
|
-
# Additional kwargs for matplotlib (for advanced use)
|
|
43
|
-
extra_kwargs: Dict[str, Any] = field(default_factory=dict)
|
|
44
|
-
|
|
45
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
46
|
-
"""Convert to dictionary for JSON serialization."""
|
|
47
|
-
d = asdict(self)
|
|
48
|
-
d["style"] = self.style.to_dict()
|
|
49
|
-
return d
|
|
50
|
-
|
|
51
|
-
@classmethod
|
|
52
|
-
def from_dict(cls, data: Dict[str, Any]) -> "PlotModel":
|
|
53
|
-
"""Create PlotModel from dictionary."""
|
|
54
|
-
# Handle old format (backward compatibility)
|
|
55
|
-
if "style" not in data:
|
|
56
|
-
# Extract style properties from flat structure
|
|
57
|
-
style_fields = PlotStyle.__annotations__.keys()
|
|
58
|
-
style_data = {k: v for k, v in data.items() if k in style_fields}
|
|
59
|
-
data = {k: v for k, v in data.items() if k not in style_fields}
|
|
60
|
-
data["style"] = style_data
|
|
61
|
-
|
|
62
|
-
# Extract and parse style
|
|
63
|
-
style_data = data.pop("style", {})
|
|
64
|
-
obj = cls(**{k: v for k, v in data.items() if k in cls.__annotations__})
|
|
65
|
-
obj.style = PlotStyle.from_dict(style_data)
|
|
66
|
-
return obj
|
|
67
|
-
|
|
68
|
-
def validate(self) -> bool:
|
|
69
|
-
"""
|
|
70
|
-
Validate the plot model.
|
|
71
|
-
|
|
72
|
-
Returns
|
|
73
|
-
-------
|
|
74
|
-
bool
|
|
75
|
-
True if valid, raises ValueError otherwise
|
|
76
|
-
"""
|
|
77
|
-
# Currently implemented plot types
|
|
78
|
-
# TODO: Add box, violin, step, stem when renderers are implemented
|
|
79
|
-
valid_plot_types = [
|
|
80
|
-
"line",
|
|
81
|
-
"scatter",
|
|
82
|
-
"bar",
|
|
83
|
-
"barh",
|
|
84
|
-
"hist",
|
|
85
|
-
"errorbar",
|
|
86
|
-
"fill_between",
|
|
87
|
-
"heatmap",
|
|
88
|
-
"imshow",
|
|
89
|
-
"contour",
|
|
90
|
-
"contourf",
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
if self.plot_type not in valid_plot_types:
|
|
94
|
-
raise ValueError(
|
|
95
|
-
f"Invalid plot_type: {self.plot_type}. "
|
|
96
|
-
f"Must be one of {valid_plot_types}"
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
# Validate data exists
|
|
100
|
-
if not self.data:
|
|
101
|
-
raise ValueError("Plot must have data")
|
|
102
|
-
|
|
103
|
-
# Type-specific validation
|
|
104
|
-
if self.plot_type in ["heatmap", "imshow"]:
|
|
105
|
-
if "z" not in self.data and "img" not in self.data:
|
|
106
|
-
raise ValueError(f"{self.plot_type} requires 'z' or 'img' in data")
|
|
107
|
-
|
|
108
|
-
elif self.plot_type in ["line", "scatter", "errorbar"]:
|
|
109
|
-
if "x" not in self.data or "y" not in self.data:
|
|
110
|
-
raise ValueError(f"{self.plot_type} requires 'x' and 'y' in data")
|
|
111
|
-
|
|
112
|
-
elif self.plot_type in ["bar", "barh"]:
|
|
113
|
-
if "x" not in self.data or "height" not in self.data:
|
|
114
|
-
# Allow alternative format with y instead of height
|
|
115
|
-
if "y" not in self.data:
|
|
116
|
-
raise ValueError(
|
|
117
|
-
f"{self.plot_type} requires 'x' and 'height' (or 'y') in data"
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
return True
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
# EOF
|