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.
Files changed (504) hide show
  1. scitex/__init__.py +1 -4
  2. scitex/__main__.py +24 -5
  3. scitex/__version__.py +1 -1
  4. scitex/_install_guide.py +14 -2
  5. scitex/_optional_deps.py +33 -0
  6. scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
  7. scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
  8. scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
  9. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
  10. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
  11. scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
  12. scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
  13. scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
  14. scitex/ai/plt/_plot_feature_importance.py +1 -1
  15. scitex/ai/plt/_plot_learning_curve.py +1 -1
  16. scitex/ai/plt/_plot_optuna_study.py +1 -1
  17. scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
  18. scitex/ai/plt/_plot_roc_curve.py +1 -1
  19. scitex/ai/plt/_stx_conf_mat.py +1 -1
  20. scitex/ai/training/_LearningCurveLogger.py +1 -1
  21. scitex/audio/mcp_server.py +38 -8
  22. scitex/bridge/_figrecipe.py +1 -1
  23. scitex/bridge/_helpers.py +1 -1
  24. scitex/bridge/_plt_vis.py +1 -1
  25. scitex/bridge/_stats_plt.py +1 -1
  26. scitex/bridge/_stats_vis.py +2 -2
  27. scitex/browser/automation/CookieHandler.py +1 -1
  28. scitex/browser/core/BrowserMixin.py +1 -1
  29. scitex/browser/core/ChromeProfileManager.py +1 -1
  30. scitex/browser/debugging/_browser_logger.py +1 -1
  31. scitex/browser/debugging/_highlight_element.py +1 -1
  32. scitex/browser/debugging/_show_grid.py +1 -1
  33. scitex/browser/interaction/click_center.py +1 -1
  34. scitex/browser/interaction/click_with_fallbacks.py +1 -1
  35. scitex/browser/interaction/close_popups.py +1 -1
  36. scitex/browser/interaction/fill_with_fallbacks.py +1 -1
  37. scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
  38. scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
  39. scitex/browser/stealth/HumanBehavior.py +1 -1
  40. scitex/browser/stealth/StealthManager.py +1 -1
  41. scitex/{fig → canvas}/__init__.py +84 -96
  42. scitex/canvas/_mcp_handlers.py +372 -0
  43. scitex/canvas/_mcp_tool_schemas.py +219 -0
  44. scitex/{fig → canvas}/backend/_parser.py +1 -1
  45. scitex/{fig → canvas}/canvas.py +13 -14
  46. scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
  47. scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
  48. scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
  49. scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
  50. scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
  51. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
  52. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
  53. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
  54. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
  55. scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
  56. scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
  57. scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
  58. scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
  59. scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
  60. scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
  61. scitex/{fig → canvas}/io/__init__.py +32 -38
  62. scitex/{fig → canvas}/io/_bundle.py +217 -154
  63. scitex/{fig → canvas}/io/_canvas.py +1 -1
  64. scitex/{fig → canvas}/io/_data.py +1 -1
  65. scitex/{fig → canvas}/io/_export.py +1 -1
  66. scitex/{fig → canvas}/io/_load.py +1 -1
  67. scitex/{fig → canvas}/io/_panel.py +1 -1
  68. scitex/{fig → canvas}/io/_save.py +1 -1
  69. scitex/canvas/mcp_server.py +151 -0
  70. scitex/{fig → canvas}/model/__init__.py +1 -1
  71. scitex/{fig → canvas}/model/_annotations.py +1 -1
  72. scitex/{fig → canvas}/model/_axes.py +1 -1
  73. scitex/{fig → canvas}/model/_figure.py +1 -1
  74. scitex/{fig → canvas}/model/_guides.py +1 -1
  75. scitex/{fig → canvas}/model/_plot.py +1 -1
  76. scitex/{fig → canvas}/model/_styles.py +1 -1
  77. scitex/{fig → canvas}/utils/__init__.py +1 -1
  78. scitex/capture/mcp_server.py +41 -12
  79. scitex/cli/audio.py +233 -0
  80. scitex/cli/capture.py +307 -0
  81. scitex/cli/convert.py +10 -6
  82. scitex/cli/main.py +27 -4
  83. scitex/cli/repro.py +233 -0
  84. scitex/cli/resource.py +240 -0
  85. scitex/cli/stats.py +325 -0
  86. scitex/cli/template.py +236 -0
  87. scitex/cli/tex.py +286 -0
  88. scitex/cli/web.py +11 -12
  89. scitex/dev/__init__.py +3 -0
  90. scitex/dev/_pyproject.py +405 -0
  91. scitex/dev/plt/__init__.py +2 -2
  92. scitex/dev/plt/mpl/get_dir_ax.py +1 -1
  93. scitex/dev/plt/mpl/get_signatures.py +1 -1
  94. scitex/dev/plt/mpl/get_signatures_details.py +1 -1
  95. scitex/diagram/README.md +7 -7
  96. scitex/diagram/_mcp_handlers.py +400 -0
  97. scitex/diagram/_mcp_tool_schemas.py +157 -0
  98. scitex/diagram/mcp_server.py +151 -0
  99. scitex/dsp/_demo_sig.py +51 -5
  100. scitex/dsp/_mne.py +13 -2
  101. scitex/dsp/_modulation_index.py +15 -3
  102. scitex/dsp/_pac.py +23 -5
  103. scitex/dsp/_psd.py +16 -4
  104. scitex/dsp/_resample.py +24 -4
  105. scitex/dsp/_transform.py +16 -3
  106. scitex/dsp/add_noise.py +15 -1
  107. scitex/dsp/norm.py +17 -2
  108. scitex/dsp/reference.py +17 -1
  109. scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
  110. scitex/dsp/utils/_zero_pad.py +18 -4
  111. scitex/dt/_normalize_timestamp.py +1 -1
  112. scitex/git/_session.py +1 -1
  113. scitex/io/__init__.py +7 -19
  114. scitex/io/_load.py +15 -19
  115. scitex/io/_load_modules/_canvas.py +2 -2
  116. scitex/io/_load_modules/_con.py +17 -6
  117. scitex/io/_load_modules/_eeg.py +28 -13
  118. scitex/io/_load_modules/_optuna.py +21 -63
  119. scitex/io/_load_modules/_torch.py +11 -3
  120. scitex/io/_save.py +11 -16
  121. scitex/io/_save_modules/__init__.py +6 -10
  122. scitex/io/_save_modules/_canvas.py +3 -3
  123. scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
  124. scitex/io/_save_modules/_plot_bundle.py +112 -0
  125. scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
  126. scitex/io/_save_modules/_stx_bundle.py +16 -16
  127. scitex/io/_save_modules/_torch.py +11 -3
  128. scitex/io/bundle/README.md +89 -80
  129. scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
  130. scitex/io/bundle/__init__.py +67 -35
  131. scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
  132. scitex/io/bundle/_core.py +184 -97
  133. scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
  134. scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
  135. scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
  136. scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
  137. scitex/io/bundle/_manifest.py +99 -0
  138. scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
  139. scitex/io/bundle/_nested.py +113 -100
  140. scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
  141. scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
  142. scitex/io/bundle/_types.py +41 -16
  143. scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
  144. scitex/io/bundle/_zip.py +21 -31
  145. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
  146. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
  147. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
  148. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
  149. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
  150. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
  151. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
  152. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
  153. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
  154. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
  155. scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
  156. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
  157. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
  158. scitex/io/bundle/schemas/__init__.py +30 -0
  159. scitex/mcp_server.py +159 -0
  160. scitex/parallel/_run.py +5 -4
  161. scitex/path/_find.py +60 -83
  162. scitex/path/_get_module_path.py +23 -21
  163. scitex/path/_get_spath.py +6 -27
  164. scitex/path/_getsize.py +23 -9
  165. scitex/path/_increment_version.py +31 -38
  166. scitex/path/_mk_spath.py +26 -29
  167. scitex/path/_path.py +5 -12
  168. scitex/path/_split.py +27 -15
  169. scitex/path/_this_path.py +23 -9
  170. scitex/plt/_mcp_handlers.py +361 -0
  171. scitex/plt/_mcp_tool_schemas.py +169 -0
  172. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
  173. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
  174. scitex/plt/gallery/_generate.py +76 -50
  175. scitex/plt/io/__init__.py +17 -19
  176. scitex/plt/io/_bundle.py +99 -52
  177. scitex/plt/io/_layered_bundle.py +303 -168
  178. scitex/plt/mcp_server.py +205 -0
  179. scitex/plt/utils/_csv_column_naming.py +250 -118
  180. scitex/repro/README_RandomStateManager.md +3 -3
  181. scitex/repro/_RandomStateManager.py +14 -14
  182. scitex/repro/_gen_ID.py +1 -1
  183. scitex/repro/_gen_timestamp.py +1 -1
  184. scitex/repro/_hash_array.py +4 -4
  185. scitex/schema/__init__.py +69 -73
  186. scitex/schema/_canvas.py +1 -1
  187. scitex/schema/_stats.py +2 -2
  188. scitex/scholar/__main__.py +24 -2
  189. scitex/scholar/_mcp_handlers.py +685 -0
  190. scitex/scholar/_mcp_tool_schemas.py +339 -0
  191. scitex/scholar/docs/template.py +1 -1
  192. scitex/scholar/examples/07_storage_integration.py +1 -1
  193. scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
  194. scitex/scholar/impact_factor/jcr/build_database.py +1 -1
  195. scitex/scholar/mcp_server.py +315 -0
  196. scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
  197. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
  198. scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
  199. scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
  200. scitex/scholar/storage/PaperIO.py +1 -1
  201. scitex/session/README.md +4 -4
  202. scitex/session/__init__.py +1 -1
  203. scitex/session/_decorator.py +9 -9
  204. scitex/session/_lifecycle.py +5 -5
  205. scitex/session/template.py +1 -1
  206. scitex/stats/__init__.py +30 -33
  207. scitex/stats/__main__.py +281 -0
  208. scitex/stats/_mcp_handlers.py +1191 -0
  209. scitex/stats/_mcp_tool_schemas.py +384 -0
  210. scitex/stats/_schema.py +1 -1
  211. scitex/stats/correct/_correct_bonferroni.py +1 -1
  212. scitex/stats/correct/_correct_fdr.py +1 -1
  213. scitex/stats/correct/_correct_fdr_.py +1 -1
  214. scitex/stats/correct/_correct_holm.py +1 -1
  215. scitex/stats/correct/_correct_sidak.py +1 -1
  216. scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
  217. scitex/stats/effect_sizes/_cohens_d.py +1 -1
  218. scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
  219. scitex/stats/effect_sizes/_eta_squared.py +1 -1
  220. scitex/stats/effect_sizes/_prob_superiority.py +1 -1
  221. scitex/stats/io/__init__.py +10 -11
  222. scitex/stats/io/_bundle.py +16 -16
  223. scitex/stats/mcp_server.py +405 -0
  224. scitex/stats/posthoc/_dunnett.py +1 -1
  225. scitex/stats/posthoc/_games_howell.py +1 -1
  226. scitex/stats/posthoc/_tukey_hsd.py +1 -1
  227. scitex/stats/power/_power.py +1 -1
  228. scitex/stats/utils/_effect_size.py +1 -1
  229. scitex/stats/utils/_formatters.py +1 -1
  230. scitex/stats/utils/_power.py +1 -1
  231. scitex/template/_mcp_handlers.py +259 -0
  232. scitex/template/_mcp_tool_schemas.py +112 -0
  233. scitex/template/mcp_server.py +186 -0
  234. scitex/utils/_verify_scitex_format.py +2 -2
  235. scitex/utils/template.py +1 -1
  236. scitex/web/__init__.py +12 -11
  237. scitex/web/_scraping.py +26 -265
  238. scitex/web/download_images.py +316 -0
  239. scitex/writer/Writer.py +1 -1
  240. scitex/writer/_clone_writer_project.py +1 -1
  241. scitex/writer/_validate_tree_structures.py +1 -1
  242. scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
  243. scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
  244. scitex/writer/dataclasses/core/_Document.py +1 -1
  245. scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
  246. scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
  247. scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
  248. scitex/writer/utils/.legacy_git_retry.py +7 -5
  249. scitex/writer/utils/_parse_latex_logs.py +1 -1
  250. scitex-2.13.0.dist-info/METADATA +1231 -0
  251. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/RECORD +376 -470
  252. scitex-2.13.0.dist-info/entry_points.txt +11 -0
  253. scitex/fig/editor/_defaults.py +0 -300
  254. scitex/fig/editor/edit/panel_loader.py +0 -232
  255. scitex/fig/editor/flask_editor/_bbox.py +0 -1299
  256. scitex/fig/editor/flask_editor/_core.py +0 -1429
  257. scitex/fig/editor/flask_editor/_renderer.py +0 -813
  258. scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
  259. scitex/fts/README.md +0 -262
  260. scitex/fts/TODO.md +0 -66
  261. scitex/fts/__init__.py +0 -90
  262. scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
  263. scitex/fts/_bundle/__init__.py +0 -38
  264. scitex/fts/_bundle/_utils/__init__.py +0 -55
  265. scitex/fts/_bundle/_utils/_const.py +0 -26
  266. scitex/fts/_bundle/_utils/_errors.py +0 -73
  267. scitex/fts/_bundle/_utils/_generate.py +0 -21
  268. scitex/fts/_bundle/_utils/_types.py +0 -76
  269. scitex/fts/_bundle/_zipbundle.py +0 -165
  270. scitex/fts/_fig/__init__.py +0 -22
  271. scitex/fts/_fig/_backend/_parser.py +0 -188
  272. scitex/fts/_fig/_editor/__init__.py +0 -14
  273. scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
  274. scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
  275. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
  276. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
  277. scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
  278. scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
  279. scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
  280. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
  281. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
  282. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
  283. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
  284. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
  285. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
  286. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
  287. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
  288. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
  289. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
  290. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
  291. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
  292. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
  293. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
  294. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
  295. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
  296. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
  297. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
  298. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
  299. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
  300. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
  301. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
  302. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
  303. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
  304. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
  305. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
  306. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
  307. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
  308. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
  309. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
  310. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
  311. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
  312. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
  313. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
  314. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
  315. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
  316. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
  317. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
  318. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
  319. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
  320. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
  321. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
  322. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
  323. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
  324. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
  325. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
  326. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
  327. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
  328. scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
  329. scitex/fts/_fig/_models/_Annotations.py +0 -115
  330. scitex/fts/_fig/_models/_Axes.py +0 -152
  331. scitex/fts/_fig/_models/_Figure.py +0 -138
  332. scitex/fts/_fig/_models/_Plot.py +0 -123
  333. scitex/fts/_fig/_utils/_plot_layout.py +0 -397
  334. scitex/fts/_kinds/_figure/_composite.py +0 -345
  335. scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
  336. scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
  337. scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
  338. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
  339. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
  340. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
  341. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
  342. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
  343. scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
  344. scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
  345. scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
  346. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
  347. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
  348. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
  349. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
  350. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
  351. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
  352. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
  353. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
  354. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
  355. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
  356. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
  357. scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
  358. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
  359. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
  360. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
  361. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
  362. scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
  363. scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
  364. scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
  365. scitex/fts/_kinds/_table/_latex/_export.py +0 -279
  366. scitex/fts/_stats/__init__.py +0 -48
  367. scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
  368. scitex/fts/_stats/_dataclasses/__init__.py +0 -48
  369. scitex/fts/_tables/__init__.py +0 -65
  370. scitex/fts/_tables/_latex/__init__.py +0 -93
  371. scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
  372. scitex/fts/_tables/_latex/_editor/_app.py +0 -725
  373. scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
  374. scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
  375. scitex/fts/_tables/_latex/_table_exporter.py +0 -362
  376. scitex/fts/_tables/_latex/_utils.py +0 -369
  377. scitex/fts/_tables/_latex/_validator.py +0 -445
  378. scitex/io/_save_modules/_pltz_bundle.py +0 -356
  379. scitex-2.10.3.dist-info/METADATA +0 -952
  380. scitex-2.10.3.dist-info/entry_points.txt +0 -2
  381. /scitex/{fig → canvas}/README.md +0 -0
  382. /scitex/{fig → canvas}/backend/__init__.py +0 -0
  383. /scitex/{fig → canvas}/backend/_export.py +0 -0
  384. /scitex/{fig → canvas}/backend/_render.py +0 -0
  385. /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
  386. /scitex/{fig → canvas}/editor/__init__.py +0 -0
  387. /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
  388. /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
  389. /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
  390. /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
  391. /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
  392. /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
  393. /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
  394. /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
  395. /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
  396. /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
  397. /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
  398. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
  399. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
  400. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
  401. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
  402. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
  403. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
  404. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
  405. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
  406. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
  407. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
  408. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
  409. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
  410. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
  411. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
  412. /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
  413. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
  414. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
  415. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
  416. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
  417. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
  418. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
  419. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
  420. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
  421. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
  422. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
  423. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
  424. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
  425. /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
  426. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
  427. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
  428. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
  429. /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
  430. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
  431. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
  432. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
  433. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
  434. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
  435. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
  436. /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
  437. /scitex/{fig → canvas}/io/_directory.py +0 -0
  438. /scitex/{fig → canvas}/model/_plot_types.py +0 -0
  439. /scitex/{fig → canvas}/utils/_defaults.py +0 -0
  440. /scitex/{fig → canvas}/utils/_validate.py +0 -0
  441. /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
  442. /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
  443. /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
  444. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
  445. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
  446. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
  447. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
  448. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
  449. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
  450. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
  451. /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
  452. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
  453. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
  454. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
  455. /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
  456. /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
  457. /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
  458. /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
  459. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
  460. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
  461. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
  462. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
  463. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
  464. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
  465. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
  466. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
  467. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
  468. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
  469. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
  470. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
  471. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
  472. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
  473. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
  474. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
  475. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
  476. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
  477. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
  478. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
  479. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
  480. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
  481. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
  482. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
  483. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
  484. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
  485. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
  486. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
  487. /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
  488. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
  489. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
  490. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
  491. /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
  492. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
  493. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
  494. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
  495. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
  496. /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
  497. /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
  498. /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
  499. /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
  500. /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
  501. /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
  502. /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
  503. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
  504. {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
- "NodeRefs",
24
- "Node",
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
- """FTS Bundle loading utilities.
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 (node.json at root).
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, Node
25
- from .._fig import Encoding, Theme
26
- from .._stats import Stats
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["Node"],
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 (node, encoding, theme, stats, data_info)
46
+ Tuple of (spec, encoding, theme, stats, data_info)
47
47
  """
48
- from ._dataclasses import DataInfo, Node
49
- from .._fig import Encoding, Theme
50
- from .._stats import Stats
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
- node = None
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 FTS: node.json at root
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
- # Node / spec.json
72
+ # Spec / spec.json
73
73
  if structure == "v2":
74
- node_data = storage.read_json("canonical/spec.json")
74
+ spec_data = storage.read_json("canonical/spec.json")
75
75
  elif structure == "sio":
76
- node_data = storage.read_json("spec.json")
76
+ spec_data = storage.read_json("spec.json")
77
77
  else:
78
- node_data = storage.read_json("node.json")
79
- if node_data:
80
- node = Node.from_dict(node_data)
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 node, encoding, theme, stats, data_info
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: 2025-12-20
3
- # File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_bundle/_mpl_helpers.py
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 FTS bundle creation."""
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 .._fig import Encoding, Theme
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 actual CSV column names.
48
+ """Build encoding from CSV column names (simple or verbose format).
38
49
 
39
- Handles two formats:
40
- 1. Verbose: ax-row-{row}-col-{col}_trace-id-{id}_variable-{var}
41
- 2. Simple: column names like 'x', 'y' (user-provided DataFrames)
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 .._fig._dataclasses import ChannelEncoding, Encoding, TraceEncoding
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 = numeric_cols[1] if numeric_cols[1] != x_col else numeric_cols[0]
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 .._fig._dataclasses import Encoding
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
- return _build_encoding_from_history(scitex_ax.history)
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 .._fig import Theme
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 extract_path_data, extract_selectable_regions
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(png_buf, format="png", dpi=dpi, facecolor=HITMAP_BACKGROUND_COLOR)
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 FTS bundle from matplotlib figure.
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 ._FTS import FTS
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 = FTS(path, create=True, kind="plot", name=name, size_mm=size_mm)
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._node.payload_schema = "scitex.fts.payload.plot@1"
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("canonical/data_info.json", json.dumps(data_info, indent=2).encode())
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("artifacts/cache/geometry_px.json", json.dumps(geometry, indent=2).encode())
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("artifacts/cache/render_manifest.json", json.dumps(manifest, indent=2).encode())
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,