scitex 2.10.2__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.
Files changed (363) hide show
  1. scitex/__init__.py +1 -4
  2. scitex/__version__.py +1 -1
  3. scitex/_install_guide.py +14 -2
  4. scitex/bridge/_figrecipe.py +1 -1
  5. scitex/bridge/_helpers.py +1 -1
  6. scitex/bridge/_plt_vis.py +1 -1
  7. scitex/bridge/_stats_plt.py +1 -1
  8. scitex/bridge/_stats_vis.py +2 -2
  9. scitex/{fig → canvas}/__init__.py +84 -96
  10. scitex/{fig → canvas}/backend/_parser.py +1 -1
  11. scitex/{fig → canvas}/canvas.py +13 -14
  12. scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
  13. scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
  14. scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
  15. scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
  16. scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
  17. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
  18. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
  19. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
  20. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
  21. scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
  22. scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
  23. scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
  24. scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
  25. scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
  26. scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
  27. scitex/{fig → canvas}/io/__init__.py +32 -38
  28. scitex/{fig → canvas}/io/_bundle.py +217 -154
  29. scitex/{fig → canvas}/io/_canvas.py +1 -1
  30. scitex/{fig → canvas}/io/_data.py +1 -1
  31. scitex/{fig → canvas}/io/_export.py +1 -1
  32. scitex/{fig → canvas}/io/_load.py +1 -1
  33. scitex/{fig → canvas}/io/_panel.py +1 -1
  34. scitex/{fig → canvas}/io/_save.py +1 -1
  35. scitex/{fig → canvas}/model/__init__.py +1 -1
  36. scitex/{fig → canvas}/model/_annotations.py +1 -1
  37. scitex/{fig → canvas}/model/_axes.py +1 -1
  38. scitex/{fig → canvas}/model/_figure.py +1 -1
  39. scitex/{fig → canvas}/model/_guides.py +1 -1
  40. scitex/{fig → canvas}/model/_plot.py +1 -1
  41. scitex/{fig → canvas}/model/_styles.py +1 -1
  42. scitex/{fig → canvas}/utils/__init__.py +1 -1
  43. scitex/cli/convert.py +10 -6
  44. scitex/diagram/README.md +7 -7
  45. scitex/io/__init__.py +7 -19
  46. scitex/io/_load.py +15 -19
  47. scitex/io/_load_modules/_canvas.py +2 -2
  48. scitex/io/_load_modules/_con.py +5 -5
  49. scitex/io/_load_modules/_eeg.py +16 -12
  50. scitex/io/_save.py +11 -16
  51. scitex/io/_save_modules/__init__.py +6 -10
  52. scitex/io/_save_modules/_canvas.py +3 -3
  53. scitex/io/_save_modules/_plot_bundle.py +112 -0
  54. scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
  55. scitex/io/_save_modules/_stx_bundle.py +16 -16
  56. scitex/io/bundle/README.md +89 -80
  57. scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
  58. scitex/io/bundle/__init__.py +67 -35
  59. scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
  60. scitex/io/bundle/_core.py +184 -97
  61. scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
  62. scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
  63. scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
  64. scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
  65. scitex/io/bundle/_manifest.py +99 -0
  66. scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
  67. scitex/io/bundle/_nested.py +113 -100
  68. scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
  69. scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
  70. scitex/io/bundle/_types.py +41 -16
  71. scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
  72. scitex/io/bundle/_zip.py +21 -31
  73. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
  74. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
  75. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
  76. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
  77. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
  78. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
  79. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
  80. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
  81. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
  82. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
  83. scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
  84. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
  85. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
  86. scitex/io/bundle/schemas/__init__.py +30 -0
  87. scitex/parallel/_run.py +5 -4
  88. scitex/path/_find.py +60 -83
  89. scitex/path/_get_module_path.py +23 -21
  90. scitex/path/_get_spath.py +6 -27
  91. scitex/path/_getsize.py +23 -9
  92. scitex/path/_increment_version.py +31 -38
  93. scitex/path/_mk_spath.py +26 -29
  94. scitex/path/_path.py +5 -12
  95. scitex/path/_split.py +27 -15
  96. scitex/path/_this_path.py +23 -9
  97. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
  98. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
  99. scitex/plt/gallery/_generate.py +76 -50
  100. scitex/plt/io/__init__.py +17 -19
  101. scitex/plt/io/_bundle.py +99 -52
  102. scitex/plt/io/_layered_bundle.py +303 -168
  103. scitex/plt/utils/_csv_column_naming.py +250 -118
  104. scitex/schema/__init__.py +69 -73
  105. scitex/schema/_canvas.py +1 -1
  106. scitex/schema/_stats.py +2 -2
  107. scitex/stats/__init__.py +30 -33
  108. scitex/stats/_schema.py +1 -1
  109. scitex/stats/io/__init__.py +10 -11
  110. scitex/stats/io/_bundle.py +16 -16
  111. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/METADATA +191 -72
  112. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/RECORD +237 -360
  113. scitex/fig/editor/_defaults.py +0 -300
  114. scitex/fig/editor/edit/panel_loader.py +0 -232
  115. scitex/fig/editor/flask_editor/_bbox.py +0 -1299
  116. scitex/fig/editor/flask_editor/_core.py +0 -1429
  117. scitex/fig/editor/flask_editor/_renderer.py +0 -813
  118. scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
  119. scitex/fts/README.md +0 -262
  120. scitex/fts/TODO.md +0 -66
  121. scitex/fts/__init__.py +0 -90
  122. scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
  123. scitex/fts/_bundle/__init__.py +0 -38
  124. scitex/fts/_bundle/_utils/__init__.py +0 -55
  125. scitex/fts/_bundle/_utils/_const.py +0 -26
  126. scitex/fts/_bundle/_utils/_errors.py +0 -73
  127. scitex/fts/_bundle/_utils/_generate.py +0 -21
  128. scitex/fts/_bundle/_utils/_types.py +0 -76
  129. scitex/fts/_bundle/_zipbundle.py +0 -165
  130. scitex/fts/_fig/__init__.py +0 -22
  131. scitex/fts/_fig/_backend/_parser.py +0 -188
  132. scitex/fts/_fig/_editor/__init__.py +0 -14
  133. scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
  134. scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
  135. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
  136. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
  137. scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
  138. scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
  139. scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
  140. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
  141. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
  142. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
  143. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
  144. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
  145. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
  146. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
  147. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
  148. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
  149. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
  150. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
  151. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
  152. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
  153. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
  154. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
  155. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
  156. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
  157. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
  158. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
  159. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
  160. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
  161. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
  162. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
  163. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
  164. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
  165. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
  166. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
  167. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
  168. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
  169. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
  170. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
  171. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
  172. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
  173. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
  174. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
  175. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
  176. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
  177. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
  178. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
  179. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
  180. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
  181. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
  182. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
  183. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
  184. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
  185. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
  186. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
  187. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
  188. scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
  189. scitex/fts/_fig/_models/_Annotations.py +0 -115
  190. scitex/fts/_fig/_models/_Axes.py +0 -152
  191. scitex/fts/_fig/_models/_Figure.py +0 -138
  192. scitex/fts/_fig/_models/_Plot.py +0 -123
  193. scitex/fts/_fig/_utils/_plot_layout.py +0 -397
  194. scitex/fts/_kinds/_figure/_composite.py +0 -345
  195. scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
  196. scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
  197. scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
  198. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
  199. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
  200. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
  201. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
  202. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
  203. scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
  204. scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
  205. scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
  206. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
  207. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
  208. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
  209. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
  210. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
  211. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
  212. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
  213. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
  214. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
  215. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
  216. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
  217. scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
  218. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
  219. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
  220. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
  221. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
  222. scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
  223. scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
  224. scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
  225. scitex/fts/_kinds/_table/_latex/_export.py +0 -279
  226. scitex/fts/_stats/__init__.py +0 -48
  227. scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
  228. scitex/fts/_stats/_dataclasses/__init__.py +0 -48
  229. scitex/fts/_tables/__init__.py +0 -65
  230. scitex/fts/_tables/_latex/__init__.py +0 -93
  231. scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
  232. scitex/fts/_tables/_latex/_editor/_app.py +0 -725
  233. scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
  234. scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
  235. scitex/fts/_tables/_latex/_table_exporter.py +0 -362
  236. scitex/fts/_tables/_latex/_utils.py +0 -369
  237. scitex/fts/_tables/_latex/_validator.py +0 -445
  238. scitex/io/_save_modules/_pltz_bundle.py +0 -356
  239. /scitex/{fig → canvas}/README.md +0 -0
  240. /scitex/{fig → canvas}/backend/__init__.py +0 -0
  241. /scitex/{fig → canvas}/backend/_export.py +0 -0
  242. /scitex/{fig → canvas}/backend/_render.py +0 -0
  243. /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
  244. /scitex/{fig → canvas}/editor/__init__.py +0 -0
  245. /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
  246. /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
  247. /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
  248. /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
  249. /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
  250. /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
  251. /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
  252. /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
  253. /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
  254. /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
  255. /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
  256. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
  257. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
  258. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
  259. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
  260. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
  261. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
  262. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
  263. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
  264. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
  265. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
  266. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
  267. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
  268. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
  269. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
  270. /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
  271. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
  272. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
  273. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
  274. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
  275. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
  276. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
  277. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
  278. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
  279. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
  280. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
  281. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
  282. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
  283. /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
  284. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
  285. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
  286. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
  287. /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
  288. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
  289. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
  290. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
  291. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
  292. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
  293. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
  294. /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
  295. /scitex/{fig → canvas}/io/_directory.py +0 -0
  296. /scitex/{fig → canvas}/model/_plot_types.py +0 -0
  297. /scitex/{fig → canvas}/utils/_defaults.py +0 -0
  298. /scitex/{fig → canvas}/utils/_validate.py +0 -0
  299. /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
  300. /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
  301. /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
  302. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
  303. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
  304. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
  305. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
  306. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
  307. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
  308. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
  309. /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
  310. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
  311. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
  312. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
  313. /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
  314. /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
  315. /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
  316. /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
  317. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
  318. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
  319. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
  320. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
  321. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
  322. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
  323. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
  324. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
  325. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
  326. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
  327. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
  328. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
  329. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
  330. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
  331. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
  332. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
  333. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
  334. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
  335. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
  336. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
  337. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
  338. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
  339. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
  340. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
  341. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
  342. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
  343. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
  344. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
  345. /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
  346. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
  347. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
  348. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
  349. /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
  350. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
  351. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
  352. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
  353. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
  354. /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
  355. /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
  356. /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
  357. /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
  358. /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
  359. /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
  360. /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
  361. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/WHEEL +0 -0
  362. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/entry_points.txt +0 -0
  363. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,30 +1,29 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Timestamp: "2025-12-16 (ywatanabe)"
2
+ # Timestamp: 2026-01-07
4
3
  # File: /home/ywatanabe/proj/scitex-code/src/scitex/io/bundle/_nested.py
5
4
 
6
5
  """
7
6
  SciTeX Nested Bundle Access - Transparent access to nested bundles.
8
7
 
9
- Provides unified API to access nested bundles (pltz inside figz) regardless
8
+ Provides unified API to access nested bundles (plot inside figure) regardless
10
9
  of whether they are stored as:
11
- - ZIP files (.figz, .pltz)
12
- - Directories (.figz.d, .pltz.d)
13
- - Nested paths (Figure1.figz/A.pltz.d or Figure1.figz.d/A.pltz.d)
10
+ - ZIP files (.figure.zip, .plot.zip)
11
+ - Directories (.figure, .plot)
12
+ - Nested paths (Figure1.figure.zip/A.plot or Figure1.figure/A.plot)
14
13
 
15
14
  Usage:
16
15
  from scitex.io.bundle import nested
17
16
 
18
- # Get pltz bundle from inside figz (works with both ZIP and directory)
19
- pltz_data = nested.resolve("Figure1.figz/A.pltz.d")
20
- pltz_data = nested.resolve("Figure1.figz.d/A.pltz.d")
17
+ # Get plot bundle from inside figure (works with both ZIP and directory)
18
+ plot_data = nested.resolve("Figure1.figure.zip/A.plot")
19
+ plot_data = nested.resolve("Figure1.figure/A.plot")
21
20
 
22
21
  # Get specific file from nested bundle
23
- png_bytes = nested.get_file("Figure1.figz/A.pltz.d/exports/plot.png")
24
- spec = nested.get_json("Figure1.figz/A.pltz.d/spec.json")
22
+ png_bytes = nested.get_file("Figure1.figure/A.plot/exports/plot.png")
23
+ spec = nested.get_json("Figure1.figure/A.plot/spec.json")
25
24
 
26
25
  # Get preview image (common use case)
27
- preview_bytes = nested.get_preview("Figure1.figz/A.pltz.d")
26
+ preview_bytes = nested.get_preview("Figure1.figure/A.plot")
28
27
  """
29
28
 
30
29
  import json
@@ -47,25 +46,24 @@ __all__ = [
47
46
 
48
47
 
49
48
  def parse_path(
50
- path: Union[str, Path]
49
+ path: Union[str, Path],
51
50
  ) -> Tuple[Optional[Path], Optional[str], Optional[str]]:
52
51
  """Parse a path to identify parent bundle, nested bundle, and file.
53
52
 
54
53
  Handles paths like:
55
- - Figure1.figz/A.pltz.d
56
- - Figure1.figz.d/A.pltz.d
57
- - Figure1.figz/A.pltz.d/exports/plot.png
58
- - Figure1.figz.d/A.pltz.d/spec.json
59
- - A.pltz.d (standalone)
60
- - A.pltz (standalone ZIP)
54
+ - Figure1.figure/A.plot
55
+ - Figure1.figure.zip/A.plot
56
+ - Figure1.figure/A.plot/exports/plot.png
57
+ - A.plot (standalone directory)
58
+ - A.plot.zip (standalone ZIP)
61
59
 
62
60
  Args:
63
61
  path: Path to parse. Can be absolute or relative.
64
62
 
65
63
  Returns:
66
64
  Tuple of (parent_bundle_path, nested_bundle_name, file_path_within_nested):
67
- - parent_bundle_path: Path to .figz or .figz.d, or None if standalone
68
- - nested_bundle_name: Name of nested bundle (e.g., "A.pltz.d"), or None
65
+ - parent_bundle_path: Path to .figure or .figure.zip, or None if standalone
66
+ - nested_bundle_name: Name of nested bundle (e.g., "A.plot"), or None
69
67
  - file_path_within_nested: Path within nested bundle, or None
70
68
  """
71
69
  p = Path(path)
@@ -75,19 +73,19 @@ def parse_path(
75
73
  nested_bundle = None
76
74
  file_within = None
77
75
 
78
- # Find the first .figz or .figz.d component
79
- figz_idx = None
76
+ # Find the first .figure.zip or .figure component
77
+ figure_idx = None
80
78
  for i, part in enumerate(parts):
81
- if part.endswith(".figz") or part.endswith(".figz.d"):
82
- figz_idx = i
79
+ if part.endswith(".figure.zip") or part.endswith(".figure"):
80
+ figure_idx = i
83
81
  break
84
82
 
85
- if figz_idx is not None:
86
- parent_bundle = Path(*parts[: figz_idx + 1])
87
- remaining = parts[figz_idx + 1 :]
83
+ if figure_idx is not None:
84
+ parent_bundle = Path(*parts[: figure_idx + 1])
85
+ remaining = parts[figure_idx + 1 :]
88
86
 
89
87
  if remaining:
90
- if remaining[0].endswith(".pltz.d") or remaining[0].endswith(".pltz"):
88
+ if remaining[0].endswith(".plot") or remaining[0].endswith(".plot.zip"):
91
89
  nested_bundle = remaining[0]
92
90
  if len(remaining) > 1:
93
91
  file_within = str(Path(*remaining[1:]))
@@ -95,7 +93,7 @@ def parse_path(
95
93
  file_within = str(Path(*remaining))
96
94
  else:
97
95
  for i, part in enumerate(parts):
98
- if part.endswith(".pltz.d") or part.endswith(".pltz"):
96
+ if part.endswith(".plot") or part.endswith(".plot.zip"):
99
97
  nested_bundle = part
100
98
  parent_bundle = Path(*parts[:i]) if i > 0 else None
101
99
  if i + 1 < len(parts):
@@ -111,17 +109,23 @@ def _find_bundle_path(base_path: Path, prefer_directory: bool = True) -> Optiona
111
109
  """Find the actual bundle path (ZIP or directory).
112
110
 
113
111
  Args:
114
- base_path: Path to search for (with or without .d extension).
115
- prefer_directory: If True, prefer .d directory over ZIP when both exist.
116
- This is important for figz bundles where panels may be in the directory
112
+ base_path: Path to search for (with or without .zip extension).
113
+ prefer_directory: If True, prefer directory over ZIP when both exist.
114
+ This is important for figure bundles where panels may be in the directory
117
115
  while the ZIP is an older export.
118
116
 
119
117
  Returns:
120
118
  Path to the bundle (directory or ZIP), or None if not found.
121
119
  """
122
- # Check for .d directory variant
123
- if base_path.suffix in (".figz", ".pltz", ".statsz"):
124
- dir_path = Path(str(base_path) + ".d")
120
+ # Check for ZIP extension (.figure.zip, .plot.zip, .stats.zip)
121
+ name = base_path.name
122
+ if (
123
+ name.endswith(".figure.zip")
124
+ or name.endswith(".plot.zip")
125
+ or name.endswith(".stats.zip")
126
+ ):
127
+ # ZIP path provided - check for directory variant
128
+ dir_path = Path(str(base_path)[:-4]) # Remove .zip
125
129
  if prefer_directory and dir_path.exists():
126
130
  return dir_path
127
131
  if base_path.exists():
@@ -129,9 +133,9 @@ def _find_bundle_path(base_path: Path, prefer_directory: bool = True) -> Optiona
129
133
  if dir_path.exists():
130
134
  return dir_path
131
135
 
132
- # Check for ZIP variant
133
- if str(base_path).endswith(".d"):
134
- zip_path = Path(str(base_path)[:-2])
136
+ # Check for directory extension (.figure, .plot, .stats)
137
+ if name.endswith(".figure") or name.endswith(".plot") or name.endswith(".stats"):
138
+ zip_path = Path(str(base_path) + ".zip")
135
139
  if not prefer_directory and zip_path.exists():
136
140
  return zip_path
137
141
  if base_path.exists():
@@ -158,20 +162,20 @@ def _read_from_zip(zip_path: Path, internal_path: str) -> bytes:
158
162
  if name.endswith("/" + internal_path) or name.endswith(internal_path):
159
163
  return zf.read(name)
160
164
 
161
- if ".pltz.d/" in internal_path:
162
- pltz_dir_name, file_in_pltz = internal_path.split(".pltz.d/", 1)
163
- pltz_dir = pltz_dir_name + ".pltz.d"
165
+ if ".plot/" in internal_path:
166
+ plot_dir_name, file_in_plot = internal_path.split(".plot/", 1)
167
+ plot_dir = plot_dir_name + ".plot"
164
168
 
165
169
  for name in namelist:
166
- if f"/{pltz_dir}/" in name or name.startswith(pltz_dir + "/"):
167
- if name.endswith("/" + file_in_pltz) or name.endswith(file_in_pltz):
170
+ if f"/{plot_dir}/" in name or name.startswith(plot_dir + "/"):
171
+ if name.endswith("/" + file_in_plot) or name.endswith(file_in_plot):
168
172
  return zf.read(name)
169
173
 
170
- base_name = pltz_dir_name
174
+ base_name = plot_dir_name
171
175
  for name in namelist:
172
- if name.endswith(".pltz") and base_name in name:
173
- pltz_data = zf.read(name)
174
- return _read_from_nested_zip(pltz_data, file_in_pltz, name)
176
+ if name.endswith(".plot.zip") and base_name in name:
177
+ plot_data = zf.read(name)
178
+ return _read_from_nested_zip(plot_data, file_in_plot, name)
175
179
 
176
180
  raise NestedBundleNotFoundError(
177
181
  f"File not found in {zip_path}: {internal_path}\n"
@@ -179,7 +183,9 @@ def _read_from_zip(zip_path: Path, internal_path: str) -> bytes:
179
183
  )
180
184
 
181
185
 
182
- def _read_from_nested_zip(zip_data: bytes, internal_path: str, zip_name: str = "") -> bytes:
186
+ def _read_from_nested_zip(
187
+ zip_data: bytes, internal_path: str, zip_name: str = ""
188
+ ) -> bytes:
183
189
  """Read file from a ZIP archive stored as bytes (nested ZIP)."""
184
190
  import io
185
191
 
@@ -189,10 +195,12 @@ def _read_from_nested_zip(zip_data: bytes, internal_path: str, zip_name: str = "
189
195
  if internal_path in namelist:
190
196
  return nested_zf.read(internal_path)
191
197
 
192
- base_name = zip_name.replace(".pltz", "") if zip_name else ""
193
- d_prefix = f"{base_name}.pltz.d/"
198
+ base_name = (
199
+ zip_name.replace(".plot.zip", "").replace(".plot", "") if zip_name else ""
200
+ )
201
+ dir_prefix = f"{base_name}.plot/"
194
202
 
195
- full_path = d_prefix + internal_path
203
+ full_path = dir_prefix + internal_path
196
204
  if full_path in namelist:
197
205
  return nested_zf.read(full_path)
198
206
 
@@ -212,8 +220,9 @@ def _read_from_directory(dir_path: Path, internal_path: str) -> bytes:
212
220
  if file_path.exists():
213
221
  return file_path.read_bytes()
214
222
 
215
- if ".pltz/" in internal_path:
216
- alt_path = internal_path.replace(".pltz/", ".pltz.d/")
223
+ # Try alternate form: .plot.zip -> .plot directory
224
+ if ".plot.zip/" in internal_path:
225
+ alt_path = internal_path.replace(".plot.zip/", ".plot/")
217
226
  alt_file_path = dir_path / alt_path
218
227
  if alt_file_path.exists():
219
228
  return alt_file_path.read_bytes()
@@ -228,9 +237,9 @@ def get_file(path: Union[str, Path]) -> bytes:
228
237
 
229
238
  Args:
230
239
  path: Full path to file, e.g.:
231
- - "Figure1.figz/A.pltz.d/exports/plot.png"
232
- - "Figure1.figz.d/A.pltz.d/exports/plot.png"
233
- - "/abs/path/Figure1.figz/A.pltz.d/spec.json"
240
+ - "Figure1.figure/A.plot/exports/plot.png"
241
+ - "Figure1.figure.zip/A.plot/exports/plot.png"
242
+ - "/abs/path/Figure1.figure/A.plot/spec.json"
234
243
 
235
244
  Returns:
236
245
  File contents as bytes.
@@ -297,8 +306,8 @@ def put_file(path: Union[str, Path], data: bytes) -> None:
297
306
 
298
307
  Args:
299
308
  path: Full path to file, e.g.:
300
- - "Figure1.figz/A.pltz.d/exports/plot.png"
301
- - "Figure1.figz.d/A.pltz.d/exports/plot.png"
309
+ - "Figure1.figure/A.plot/exports/plot.png"
310
+ - "Figure1.figure.zip/A.plot/exports/plot.png"
302
311
  data: File contents as bytes.
303
312
 
304
313
  Raises:
@@ -403,10 +412,10 @@ def get_preview(
403
412
  bundle_path: Union[str, Path],
404
413
  filename: str = None,
405
414
  ) -> bytes:
406
- """Get preview PNG from a nested pltz bundle.
415
+ """Get preview PNG from a nested plot bundle.
407
416
 
408
- Handles .pltz and .pltz.d interchangeably. Does not assume the PNG
409
- filename matches the bundle name (e.g., B.pltz.d may contain stx_scatter.png).
417
+ Handles .plot and .plot.zip interchangeably. Does not assume the PNG
418
+ filename matches the bundle name.
410
419
 
411
420
  Search order:
412
421
  1. Specific filename if provided
@@ -418,8 +427,8 @@ def get_preview(
418
427
  7. Any PNG in bundle not containing 'hitmap' or 'overview'
419
428
 
420
429
  Args:
421
- bundle_path: Path to pltz bundle (can be nested in figz).
422
- Handles both .pltz and .pltz.d extensions interchangeably.
430
+ bundle_path: Path to plot bundle (can be nested in figure).
431
+ Handles both .plot and .plot.zip extensions interchangeably.
423
432
  filename: Specific filename to look for (optional).
424
433
 
425
434
  Returns:
@@ -427,7 +436,7 @@ def get_preview(
427
436
  """
428
437
  parent_bundle, nested_bundle, file_within = parse_path(bundle_path)
429
438
 
430
- # Build base path, handling .pltz ↔ .pltz.d interchangeably
439
+ # Build base path, handling .plot ↔ .plot.zip interchangeably
431
440
  if parent_bundle and nested_bundle:
432
441
  base_path = f"{parent_bundle}/{nested_bundle}"
433
442
  elif nested_bundle:
@@ -437,15 +446,15 @@ def get_preview(
437
446
 
438
447
  # Try alternate extension if list_files fails
439
448
  def try_with_fallback(path: str) -> List[str]:
440
- """Try to list files, with .pltz ↔ .pltz.d fallback."""
449
+ """Try to list files, with .plot ↔ .plot.zip fallback."""
441
450
  try:
442
451
  return list_files(path)
443
452
  except NestedBundleNotFoundError:
444
453
  # Try alternate extension
445
- if path.endswith(".pltz"):
446
- alt_path = path + ".d"
447
- elif path.endswith(".pltz.d"):
448
- alt_path = path[:-2] # Remove .d
454
+ if path.endswith(".plot"):
455
+ alt_path = path + ".zip"
456
+ elif path.endswith(".plot.zip"):
457
+ alt_path = path[:-4] # Remove .zip
449
458
  else:
450
459
  raise
451
460
  return list_files(alt_path)
@@ -455,14 +464,14 @@ def get_preview(
455
464
  try:
456
465
  files = try_with_fallback(base_path)
457
466
  # Determine which path worked
458
- if base_path.endswith(".pltz"):
459
- alt_path = base_path + ".d"
467
+ if base_path.endswith(".plot") and not base_path.endswith(".plot.zip"):
468
+ alt_path = base_path + ".zip"
460
469
  try:
461
470
  list_files(base_path)
462
471
  except NestedBundleNotFoundError:
463
472
  working_path = alt_path
464
- elif base_path.endswith(".pltz.d"):
465
- alt_path = base_path[:-2]
473
+ elif base_path.endswith(".plot.zip"):
474
+ alt_path = base_path[:-4]
466
475
  try:
467
476
  list_files(base_path)
468
477
  except NestedBundleNotFoundError:
@@ -470,7 +479,7 @@ def get_preview(
470
479
  except NestedBundleNotFoundError:
471
480
  files = []
472
481
 
473
- bundle_name = Path(working_path).stem.replace(".pltz", "")
482
+ bundle_name = Path(working_path).stem.replace(".plot", "")
474
483
 
475
484
  # Standard locations to try
476
485
  locations = [
@@ -560,12 +569,12 @@ def list_files(bundle_path: Union[str, Path]) -> List[str]:
560
569
  if files:
561
570
  return files
562
571
 
563
- if nested_bundle.endswith(".pltz.d"):
564
- base_name = nested_bundle[:-7]
572
+ if nested_bundle.endswith(".plot"):
573
+ base_name = nested_bundle[:-5]
565
574
  for name in namelist:
566
- if name.endswith(".pltz") and base_name in name:
567
- pltz_data = zf.read(name)
568
- return _list_nested_zip_files(pltz_data, name)
575
+ if name.endswith(".plot.zip") and base_name in name:
576
+ plot_data = zf.read(name)
577
+ return _list_nested_zip_files(plot_data, name)
569
578
 
570
579
  return files
571
580
  else:
@@ -573,18 +582,18 @@ def list_files(bundle_path: Union[str, Path]) -> List[str]:
573
582
  else:
574
583
  target = actual_parent
575
584
  if nested_bundle:
576
- # Prefer .d directory over ZIP when both exist
577
- if nested_bundle.endswith(".pltz"):
578
- dir_target = actual_parent / (nested_bundle + ".d")
585
+ # Prefer directory over ZIP when both exist
586
+ if nested_bundle.endswith(".plot.zip"):
587
+ dir_target = actual_parent / nested_bundle[:-4] # Remove .zip
579
588
  if dir_target.exists():
580
589
  target = dir_target
581
590
  else:
582
591
  target = actual_parent / nested_bundle
583
- elif nested_bundle.endswith(".pltz.d"):
592
+ elif nested_bundle.endswith(".plot"):
584
593
  target = actual_parent / nested_bundle
585
594
  if not target.exists():
586
- # Try without .d
587
- zip_target = actual_parent / nested_bundle[:-2]
595
+ # Try with .zip
596
+ zip_target = actual_parent / (nested_bundle + ".zip")
588
597
  if zip_target.exists():
589
598
  target = zip_target
590
599
  else:
@@ -593,7 +602,9 @@ def list_files(bundle_path: Union[str, Path]) -> List[str]:
593
602
  if not target.exists():
594
603
  raise NestedBundleNotFoundError(f"Bundle not found: {target}")
595
604
 
596
- return [str(f.relative_to(target)) for f in target.rglob("*") if f.is_file()]
605
+ return [
606
+ str(f.relative_to(target)) for f in target.rglob("*") if f.is_file()
607
+ ]
597
608
 
598
609
  bundle = Path(bundle_path)
599
610
  actual = _find_bundle_path(bundle)
@@ -614,13 +625,15 @@ def _list_nested_zip_files(zip_data: bytes, zip_name: str = "") -> List[str]:
614
625
  with zipfile.ZipFile(io.BytesIO(zip_data), "r") as nested_zf:
615
626
  namelist = nested_zf.namelist()
616
627
 
617
- base_name = zip_name.replace(".pltz", "") if zip_name else ""
618
- d_prefix = f"{base_name}.pltz.d/"
628
+ base_name = (
629
+ zip_name.replace(".plot.zip", "").replace(".plot", "") if zip_name else ""
630
+ )
631
+ dir_prefix = f"{base_name}.plot/"
619
632
 
620
633
  files = []
621
634
  for name in namelist:
622
- if name.startswith(d_prefix):
623
- rel = name[len(d_prefix) :]
635
+ if name.startswith(dir_prefix):
636
+ rel = name[len(dir_prefix) :]
624
637
  if rel and not rel.endswith("/"):
625
638
  files.append(rel)
626
639
  elif not name.endswith("/"):
@@ -636,16 +649,16 @@ def resolve(
636
649
  """Load a nested bundle's data.
637
650
 
638
651
  Transparently handles:
639
- - Standalone .pltz or .pltz.d
640
- - Nested .pltz.d inside .figz
641
- - Nested .pltz.d inside .figz.d
652
+ - Standalone .plot or .plot.zip
653
+ - Nested .plot inside .figure
654
+ - Nested .plot inside .figure.zip
642
655
 
643
656
  Args:
644
657
  bundle_path: Path to bundle, e.g.:
645
- - "Figure1.figz/A.pltz.d"
646
- - "Figure1.figz.d/A.pltz.d"
647
- - "A.pltz.d"
648
- - "A.pltz"
658
+ - "Figure1.figure/A.plot"
659
+ - "Figure1.figure.zip/A.plot"
660
+ - "A.plot"
661
+ - "A.plot.zip"
649
662
  extract_to: If provided, extract ZIP contents to this directory.
650
663
 
651
664
  Returns:
@@ -677,7 +690,7 @@ def resolve(
677
690
  try:
678
691
  result["spec"] = get_json(f"{bundle_path}/spec.json")
679
692
  except NestedBundleNotFoundError:
680
- bundle_name = Path(bundle_path).stem.replace(".pltz", "")
693
+ bundle_name = Path(bundle_path).stem.replace(".plot", "")
681
694
  try:
682
695
  result["spec"] = get_json(f"{bundle_path}/{bundle_name}.json")
683
696
  except NestedBundleNotFoundError:
@@ -696,7 +709,7 @@ def resolve(
696
709
  csv_bytes = get_file(f"{bundle_path}/data.csv")
697
710
  result["data"] = pd.read_csv(io.BytesIO(csv_bytes))
698
711
  except (NestedBundleNotFoundError, ImportError):
699
- bundle_name = Path(bundle_path).stem.replace(".pltz", "")
712
+ bundle_name = Path(bundle_path).stem.replace(".plot", "")
700
713
  try:
701
714
  import io
702
715
 
@@ -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/_saver.py
2
+ # Timestamp: 2026-01-07
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/io/bundle/_saver.py
4
4
 
5
- """FTS Bundle saving utilities.
5
+ """Bundle saving utilities.
6
6
 
7
7
  Bundle structure (IDENTICAL for all kinds):
8
8
  bundle.zip/
@@ -38,14 +38,14 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
38
38
  from ._storage import Storage, get_storage
39
39
 
40
40
  if TYPE_CHECKING:
41
- from ._dataclasses import DataInfo, Node
42
- from .._fig import Encoding, Theme
43
- from .._stats import Stats
41
+ from ._dataclasses import DataInfo, Spec
42
+ from .kinds._plot._dataclasses import Encoding, Theme
43
+ from .kinds._stats._dataclasses import Stats
44
44
 
45
45
 
46
46
  def save_bundle_components(
47
47
  path: Path,
48
- node: Optional["Node"] = None,
48
+ spec: Optional["Spec"] = None,
49
49
  encoding: Optional["Encoding"] = None,
50
50
  theme: Optional["Theme"] = None,
51
51
  stats: Optional["Stats"] = None,
@@ -58,7 +58,7 @@ def save_bundle_components(
58
58
 
59
59
  Args:
60
60
  path: Bundle path (directory or ZIP)
61
- node: Node metadata (saved to canonical/spec.json)
61
+ spec: Spec metadata (saved to canonical/spec.json)
62
62
  encoding: Encoding specification (saved to canonical/encoding.json)
63
63
  theme: Theme specification (saved to canonical/theme.json)
64
64
  stats: Statistics (saved to payload/stats.json for kind=stats)
@@ -74,15 +74,15 @@ def save_bundle_components(
74
74
  # Use .keep files as directory markers for ZIP compatibility
75
75
  files["canonical/.keep"] = ""
76
76
  files["payload/.keep"] = ""
77
- files["payload/data.csv"] = "" # Empty CSV for consistency
77
+ # NOTE: Don't write empty payload/data.csv - it may already contain data
78
78
  files["artifacts/.keep"] = ""
79
79
  files["artifacts/exports/.keep"] = ""
80
80
  files["artifacts/cache/.keep"] = ""
81
81
  files["children/.keep"] = ""
82
82
 
83
83
  # canonical/ - Source of truth
84
- if node:
85
- files["canonical/spec.json"] = json.dumps(node.to_dict(), indent=2)
84
+ if spec:
85
+ files["canonical/spec.json"] = json.dumps(spec.to_dict(), indent=2)
86
86
 
87
87
  if encoding:
88
88
  files["canonical/encoding.json"] = encoding.to_json()
@@ -99,7 +99,7 @@ def save_bundle_components(
99
99
 
100
100
  # Write files, preserving any existing children/ files
101
101
  # For ZIP, we need to merge with existing content
102
- if hasattr(storage, 'write_all_preserve'):
102
+ if hasattr(storage, "write_all_preserve"):
103
103
  storage.write_all_preserve(files)
104
104
  else:
105
105
  # Fallback: write each file individually (preserves existing)
@@ -186,7 +186,6 @@ def generate_hitmap(
186
186
  import io
187
187
 
188
188
  import matplotlib.pyplot as plt
189
- import numpy as np
190
189
 
191
190
  # Create hitmap figure with same dimensions
192
191
  fig_size = figure.get_size_inches()
@@ -224,7 +223,7 @@ def generate_hitmap(
224
223
  plt.close(hitmap_fig)
225
224
  return png_bytes, svg_bytes
226
225
 
227
- except Exception as e:
226
+ except Exception:
228
227
  # If hitmap generation fails, return None (non-critical)
229
228
  return None, None
230
229
 
@@ -3,14 +3,14 @@
3
3
  # File: /home/ywatanabe/proj/scitex-code/src/scitex/fsb/_bundle/_storage.py
4
4
 
5
5
  """
6
- Storage Abstraction for FTS Bundles.
6
+ Storage Abstraction for SciTeX Bundles.
7
7
 
8
8
  Provides a unified interface for reading/writing bundle contents
9
9
  regardless of whether the bundle is a ZIP file or directory.
10
10
 
11
11
  Usage:
12
12
  storage = get_storage(Path("bundle.zip")) # or Path("bundle/")
13
- data = storage.read("node.json")
13
+ data = storage.read("spec.json")
14
14
  storage.write("encoding.json", json_bytes)
15
15
  """
16
16
 
@@ -22,7 +22,7 @@ from typing import List, Optional, Union
22
22
 
23
23
 
24
24
  class Storage(ABC):
25
- """Abstract storage interface for FTS bundles."""
25
+ """Abstract storage interface for SciTeX bundles."""
26
26
 
27
27
  def __init__(self, path: Path):
28
28
  self._path = path
@@ -1,12 +1,15 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Timestamp: "2025-12-16 (ywatanabe)"
4
- # File: /home/ywatanabe/proj/scitex-code/src/scitex/io/bundle/_types.py
2
+ # Timestamp: 2026-01-07
3
+ # File: src/scitex/io/bundle/_types.py
5
4
 
6
5
  """
7
6
  SciTeX Bundle Types and Constants.
8
7
 
9
8
  Defines bundle types, extensions, and error classes used across the bundle module.
9
+
10
+ Extension formats:
11
+ - ZIP: .figure.zip, .plot.zip, .stats.zip
12
+ - Directory: .figure/, .plot/, .stats/
10
13
  """
11
14
 
12
15
  from typing import Tuple
@@ -18,18 +21,28 @@ __all__ = [
18
21
  "BundleNotFoundError",
19
22
  "NestedBundleNotFoundError",
20
23
  "EXTENSIONS",
21
- "FIGZ",
22
- "PLTZ",
23
- "STATSZ",
24
+ "DIR_EXTENSIONS",
25
+ "FIGURE",
26
+ "PLOT",
27
+ "STATS",
24
28
  ]
25
29
 
26
- # Bundle extensions
27
- EXTENSIONS: Tuple[str, ...] = (".figz", ".pltz", ".statsz")
30
+ # =============================================================================
31
+ # ZIP extensions
32
+ # =============================================================================
33
+ EXTENSIONS: Tuple[str, ...] = (".figure.zip", ".plot.zip", ".stats.zip")
34
+
35
+ # =============================================================================
36
+ # Directory extensions
37
+ # =============================================================================
38
+ DIR_EXTENSIONS: Tuple[str, ...] = (".figure", ".plot", ".stats")
28
39
 
29
- # Bundle type constants (for convenience)
30
- FIGZ = "figz"
31
- PLTZ = "pltz"
32
- STATSZ = "statsz"
40
+ # =============================================================================
41
+ # Bundle type constants
42
+ # =============================================================================
43
+ FIGURE = "figure"
44
+ PLOT = "plot"
45
+ STATS = "stats"
33
46
 
34
47
 
35
48
  class BundleType:
@@ -38,13 +51,25 @@ class BundleType:
38
51
  Usage:
39
52
  from scitex.io.bundle import BundleType
40
53
 
41
- if bundle_type == BundleType.FIGZ:
54
+ if bundle_type == BundleType.FIGURE:
42
55
  ...
43
56
  """
44
57
 
45
- FIGZ = "figz"
46
- PLTZ = "pltz"
47
- STATSZ = "statsz"
58
+ FIGURE = "figure"
59
+ PLOT = "plot"
60
+ STATS = "stats"
61
+
62
+ @classmethod
63
+ def normalize(cls, bundle_type: str) -> str:
64
+ """Normalize bundle type to standard name.
65
+
66
+ Args:
67
+ bundle_type: Bundle type string.
68
+
69
+ Returns:
70
+ Normalized type ('figure', 'plot', 'stats').
71
+ """
72
+ return bundle_type.lower()
48
73
 
49
74
 
50
75
  class BundleError(Exception):