scitex 2.10.3__py3-none-any.whl → 2.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.3.dist-info → scitex-2.11.0.dist-info}/METADATA +190 -73
  112. {scitex-2.10.3.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.3.dist-info → scitex-2.11.0.dist-info}/WHEEL +0 -0
  362. {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/entry_points.txt +0 -0
  363. {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,538 +0,0 @@
1
- #!/usr/bin/env python3
2
- # File: ./src/scitex/vis/backend/render.py
3
- """Render figure models to matplotlib figures using scitex.plt."""
4
-
5
- from typing import Any, Dict
6
-
7
- import numpy as np
8
-
9
- import scitex.logging as logging
10
-
11
- from .._models import AnnotationModel, AxesModel, FigureModel, GuideModel, PlotModel
12
- from ._parser import parse_figure_json
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
-
17
- def render_figure(fig_model: FigureModel):
18
- """
19
- Render FigureModel to matplotlib figure using scitex.plt.
20
-
21
- Parameters
22
- ----------
23
- fig_model : FigureModel
24
- Figure model to render
25
-
26
- Returns
27
- -------
28
- tuple
29
- (fig, axes) where fig is FigWrapper and axes is list of AxisWrapper
30
-
31
- Examples
32
- --------
33
- >>> fig_model = FigureModel(width_mm=180, height_mm=120)
34
- >>> fig, axes = render_figure(fig_model)
35
- """
36
- import scitex as stx
37
-
38
- # Validate before rendering
39
- fig_model.validate()
40
-
41
- # Convert mm to inches for matplotlib
42
- MM_TO_INCH = 1 / 25.4
43
- figsize_inch = (
44
- fig_model.width_mm * MM_TO_INCH,
45
- fig_model.height_mm * MM_TO_INCH,
46
- )
47
-
48
- # Create figure with mm dimensions
49
- fig, axes = stx.plt.subplots(
50
- nrows=fig_model.nrows,
51
- ncols=fig_model.ncols,
52
- figsize=figsize_inch,
53
- dpi=fig_model.dpi,
54
- facecolor=fig_model.facecolor,
55
- edgecolor=fig_model.edgecolor,
56
- )
57
-
58
- # Ensure axes is always a list
59
- if not isinstance(axes, (list, np.ndarray)):
60
- axes = [axes]
61
- elif isinstance(axes, np.ndarray):
62
- axes = axes.flatten().tolist()
63
-
64
- # TODO: Apply mm-based spacing (left_mm, right_mm, etc.)
65
- # Currently, matplotlib subplots_adjust uses figure coordinates (0-1), not mm
66
- # Future: Pass margin_left_mm, margin_right_mm etc. to stx.plt.subplots()
67
- # to leverage scitex.plt's mm-control system
68
-
69
- # Add suptitle if specified
70
- if fig_model.suptitle:
71
- suptitle_kwargs = {"t": fig_model.suptitle}
72
- if fig_model.suptitle_fontsize is not None:
73
- suptitle_kwargs["fontsize"] = fig_model.suptitle_fontsize
74
- if fig_model.suptitle_fontweight is not None:
75
- suptitle_kwargs["fontweight"] = fig_model.suptitle_fontweight
76
- if fig_model.suptitle_y is not None:
77
- suptitle_kwargs["y"] = fig_model.suptitle_y
78
- fig.suptitle(**suptitle_kwargs)
79
-
80
- # Render each axes
81
- for i, axes_config in enumerate(fig_model.axes):
82
- if i < len(axes):
83
- axes_model = AxesModel.from_dict(axes_config)
84
- render_axes(axes[i], axes_model)
85
-
86
- return fig, axes
87
-
88
-
89
- def render_axes(ax, axes_model: AxesModel):
90
- """
91
- Render AxesModel onto a matplotlib axis.
92
-
93
- Parameters
94
- ----------
95
- ax : AxisWrapper or matplotlib Axes
96
- Target axis
97
- axes_model : AxesModel
98
- Axes model to render
99
- """
100
- # Validate
101
- axes_model.validate()
102
-
103
- # Render plots first (background layer)
104
- for plot_config in axes_model.plots:
105
- plot_model = PlotModel.from_dict(plot_config)
106
- render_plot(ax, plot_model)
107
-
108
- # Render guides (middle layer - reference lines/spans over plots)
109
- # Note: Use zorder in guide config to control layering if needed
110
- for guide_config in axes_model.guides:
111
- guide_model = GuideModel.from_dict(guide_config)
112
- render_guide(ax, guide_model)
113
-
114
- # Render annotations last (foreground layer)
115
- for annotation_config in axes_model.annotations:
116
- annotation_model = AnnotationModel.from_dict(annotation_config)
117
- render_annotation(ax, annotation_model)
118
-
119
- # Apply axis properties
120
- if axes_model.xlabel:
121
- ax.set_xlabel(axes_model.xlabel)
122
-
123
- if axes_model.ylabel:
124
- ax.set_ylabel(axes_model.ylabel)
125
-
126
- if axes_model.title:
127
- ax.set_title(axes_model.title)
128
-
129
- # Set axis limits
130
- if axes_model.xlim:
131
- ax.set_xlim(axes_model.xlim)
132
-
133
- if axes_model.ylim:
134
- ax.set_ylim(axes_model.ylim)
135
-
136
- # Set axis scales
137
- ax.set_xscale(axes_model.xscale)
138
- ax.set_yscale(axes_model.yscale)
139
-
140
- # Ticks
141
- if axes_model.xticks is not None:
142
- ax.set_xticks(axes_model.xticks)
143
-
144
- if axes_model.yticks is not None:
145
- ax.set_yticks(axes_model.yticks)
146
-
147
- if axes_model.xticklabels is not None:
148
- ax.set_xticklabels(axes_model.xticklabels)
149
-
150
- if axes_model.yticklabels is not None:
151
- ax.set_yticklabels(axes_model.yticklabels)
152
-
153
- # Apply style properties
154
- style = axes_model.style
155
-
156
- # Grid
157
- if style.grid:
158
- ax.grid(
159
- alpha=style.grid_alpha,
160
- linestyle=style.grid_linestyle,
161
- linewidth=style.grid_linewidth,
162
- )
163
-
164
- # Spines
165
- for spine, visible in style.spines_visible.items():
166
- if hasattr(ax, "spines") and spine in ax.spines:
167
- ax.spines[spine].set_visible(visible)
168
-
169
- # Tick label size
170
- if style.tick_fontsize is not None:
171
- ax.tick_params(labelsize=style.tick_fontsize)
172
-
173
- # Legend
174
- if style.legend:
175
- legend_kwargs = {
176
- "loc": style.legend_loc,
177
- "frameon": style.legend_frameon,
178
- }
179
- if style.legend_fontsize is not None:
180
- legend_kwargs["fontsize"] = style.legend_fontsize
181
- ax.legend(**legend_kwargs)
182
-
183
- # Aspect
184
- if style.aspect:
185
- ax.set_aspect(style.aspect)
186
-
187
- # Background color
188
- if style.facecolor:
189
- ax.set_facecolor(style.facecolor)
190
-
191
-
192
- def render_plot(ax, plot_model: PlotModel):
193
- """
194
- Render PlotModel onto an axis.
195
-
196
- Parameters
197
- ----------
198
- ax : AxisWrapper or matplotlib Axes
199
- Target axis
200
- plot_model : PlotModel
201
- Plot model to render
202
- """
203
- # Validate
204
- plot_model.validate()
205
-
206
- data = plot_model.data
207
-
208
- # Build kwargs from style (clean separation of concerns)
209
- # Only include relevant kwargs for each plot type
210
- style_dict = plot_model.style.to_dict()
211
-
212
- # Common kwargs for all plot types
213
- common_keys = {"color", "alpha", "zorder"}
214
-
215
- # Define relevant keys for each plot type
216
- plot_type_keys = {
217
- "line": {"linewidth", "linestyle", "marker", "markersize"},
218
- "scatter": {"marker", "markersize"},
219
- "errorbar": {"linewidth", "linestyle", "marker", "xerr", "yerr", "capsize"},
220
- "bar": {"width"},
221
- "barh": {"width"}, # Will be renamed to height
222
- "hist": {"bins", "density", "cumulative"},
223
- "fill_between": {"linewidth", "fill_color", "fill_alpha"},
224
- "heatmap": {"cmap", "vmin", "vmax", "interpolation"},
225
- "imshow": {"cmap", "vmin", "vmax", "interpolation"},
226
- "contour": {"cmap", "vmin", "vmax"},
227
- "contourf": {"cmap", "vmin", "vmax"},
228
- }
229
-
230
- # Get relevant keys for this plot type
231
- relevant_keys = common_keys | plot_type_keys.get(plot_model.plot_type, set())
232
-
233
- # Filter kwargs to only include relevant ones
234
- kwargs = {k: v for k, v in style_dict.items() if k in relevant_keys}
235
-
236
- # Add label if present
237
- if plot_model.label:
238
- kwargs["label"] = plot_model.label
239
-
240
- # Merge extra kwargs
241
- kwargs.update(plot_model.extra_kwargs)
242
-
243
- # Render based on plot type
244
- if plot_model.plot_type == "line":
245
- ax.plot(data["x"], data["y"], **kwargs)
246
-
247
- elif plot_model.plot_type == "scatter":
248
- # Rename markersize -> s for scatter
249
- if "markersize" in kwargs:
250
- kwargs["s"] = kwargs.pop("markersize")
251
- ax.scatter(data["x"], data["y"], **kwargs)
252
-
253
- elif plot_model.plot_type == "errorbar":
254
- ax.errorbar(data["x"], data["y"], **kwargs)
255
-
256
- elif plot_model.plot_type == "bar":
257
- height = data.get("height", data.get("y"))
258
- ax.bar(data["x"], height, **kwargs)
259
-
260
- elif plot_model.plot_type == "barh":
261
- # Rename width -> height for horizontal bars
262
- if "width" in kwargs:
263
- kwargs["height"] = kwargs.pop("width")
264
- width = data.get("width", data.get("x"))
265
- ax.barh(data["y"], width, **kwargs)
266
-
267
- elif plot_model.plot_type == "hist":
268
- ax.hist(data["x"], **kwargs)
269
-
270
- elif plot_model.plot_type == "fill_between":
271
- # Use fill_alpha and fill_color if present
272
- if "fill_alpha" in kwargs:
273
- kwargs["alpha"] = kwargs.pop("fill_alpha")
274
- if "fill_color" in kwargs:
275
- kwargs["color"] = kwargs.pop("fill_color")
276
- ax.fill_between(data["x"], data["y1"], data["y2"], **kwargs)
277
-
278
- elif plot_model.plot_type in ["heatmap", "imshow"]:
279
- img_data = data.get("z", data.get("img"))
280
- ax.imshow(img_data, **kwargs)
281
-
282
- elif plot_model.plot_type == "contour":
283
- ax.contour(data["x"], data["y"], data["z"], **kwargs)
284
-
285
- elif plot_model.plot_type == "contourf":
286
- ax.contourf(data["x"], data["y"], data["z"], **kwargs)
287
-
288
- else:
289
- raise ValueError(f"Unsupported plot type: {plot_model.plot_type}")
290
-
291
-
292
- def render_guide(ax, guide_model: GuideModel):
293
- """
294
- Render GuideModel onto an axis.
295
-
296
- Parameters
297
- ----------
298
- ax : AxisWrapper or matplotlib Axes
299
- Target axis
300
- guide_model : GuideModel
301
- Guide model to render
302
- """
303
- # Validate
304
- guide_model.validate()
305
-
306
- # Build kwargs from style
307
- kwargs = guide_model.style.to_dict()
308
-
309
- # Add label if present
310
- if guide_model.label:
311
- kwargs["label"] = guide_model.label
312
-
313
- # Render based on guide type
314
- if guide_model.guide_type == "axhline":
315
- ax.axhline(guide_model.y, **kwargs)
316
-
317
- elif guide_model.guide_type == "axvline":
318
- ax.axvline(guide_model.x, **kwargs)
319
-
320
- elif guide_model.guide_type == "axhspan":
321
- ax.axhspan(guide_model.ymin, guide_model.ymax, **kwargs)
322
-
323
- elif guide_model.guide_type == "axvspan":
324
- ax.axvspan(guide_model.xmin, guide_model.xmax, **kwargs)
325
-
326
-
327
- def render_annotation(ax, annotation_model: AnnotationModel):
328
- """
329
- Render AnnotationModel onto an axis.
330
-
331
- Parameters
332
- ----------
333
- ax : AxisWrapper or matplotlib Axes
334
- Target axis
335
- annotation_model : AnnotationModel
336
- Annotation model to render
337
- """
338
- # Validate
339
- annotation_model.validate()
340
-
341
- # Build kwargs from style
342
- kwargs = annotation_model.style.to_dict()
343
-
344
- # Render based on annotation type
345
- if annotation_model.annotation_type == "text":
346
- ax.text(
347
- annotation_model.x,
348
- annotation_model.y,
349
- annotation_model.text,
350
- **kwargs,
351
- )
352
-
353
- elif annotation_model.annotation_type == "annotate":
354
- ax.annotate(
355
- annotation_model.text,
356
- xy=(annotation_model.x, annotation_model.y),
357
- xytext=annotation_model.xytext,
358
- **kwargs,
359
- )
360
-
361
-
362
- def build_figure_from_json(fig_json: Dict[str, Any]):
363
- """
364
- Build matplotlib figure from figure JSON.
365
-
366
- This is the main entry point for rendering.
367
-
368
- Parameters
369
- ----------
370
- fig_json : Dict[str, Any]
371
- Figure JSON specification
372
-
373
- Returns
374
- -------
375
- tuple
376
- (fig, axes) where fig is FigWrapper and axes is list of AxisWrapper
377
-
378
- Examples
379
- --------
380
- >>> fig_json = {...}
381
- >>> fig, axes = build_figure_from_json(fig_json)
382
- >>> import scitex as stx
383
- >>> stx.io.save(fig, "output.png")
384
- """
385
- fig_model = parse_figure_json(fig_json)
386
- return render_figure(fig_model)
387
-
388
-
389
- def _find_column(data, col_name):
390
- """Find a column in data, supporting prefixed column names.
391
-
392
- Parameters
393
- ----------
394
- data : pd.DataFrame
395
- Data to search
396
- col_name : str
397
- Column name to find (can be simple like "x" or prefixed)
398
-
399
- Returns
400
- -------
401
- str or None
402
- Actual column name in data, or None if not found
403
- """
404
- if col_name in data.columns:
405
- return col_name
406
-
407
- # Try to find a column that ends with the variable name
408
- # e.g., "ax-row-0-col-0_trace-id-plot-0_variable-x" matches "x"
409
- suffix = f"_variable-{col_name}"
410
- for col in data.columns:
411
- if col.endswith(suffix):
412
- return col
413
-
414
- # Try partial match at the end
415
- for col in data.columns:
416
- if col.endswith(f"-{col_name}"):
417
- return col
418
-
419
- return None
420
-
421
-
422
- def _is_special_trace(trace_id):
423
- """Check if trace is a special type that doesn't require x/y encoding.
424
-
425
- Parameters
426
- ----------
427
- trace_id : str
428
- Trace identifier
429
-
430
- Returns
431
- -------
432
- bool
433
- True if this is a special trace type
434
- """
435
- special_patterns = [
436
- "fill-between",
437
- "fill_between",
438
- "axhline",
439
- "axvline",
440
- "axhspan",
441
- "axvspan",
442
- "text",
443
- "annotation",
444
- ]
445
- trace_lower = trace_id.lower()
446
- return any(pattern in trace_lower for pattern in special_patterns)
447
-
448
-
449
- def render_traces(ax, trace, data, theme=None):
450
- """
451
- Render a TraceEncoding onto an axis.
452
-
453
- Parameters
454
- ----------
455
- ax : matplotlib Axes
456
- Target axis
457
- trace : TraceEncoding
458
- Trace encoding specification
459
- data : pd.DataFrame or None
460
- Data to plot
461
- theme : Theme, optional
462
- Theme for styling
463
-
464
- Raises
465
- ------
466
- ValueError
467
- If data is None or required columns are missing (for standard traces)
468
- """
469
- # Skip special traces that don't require standard x/y encoding
470
- if _is_special_trace(trace.trace_id):
471
- logger.debug(f"Skipping special trace '{trace.trace_id}' (no x/y rendering)")
472
- return
473
-
474
- if data is None:
475
- logger.warning(f"No data provided for trace '{trace.trace_id}', skipping")
476
- return
477
-
478
- # Get style from theme
479
- color = None
480
- linewidth = 1.0
481
- alpha = 1.0
482
-
483
- if theme:
484
- # Check for trace-specific theme
485
- if hasattr(theme, "traces") and theme.traces:
486
- for t in theme.traces:
487
- if t.trace_id == trace.trace_id:
488
- color = t.color
489
- if t.line_width_pt:
490
- linewidth = t.line_width_pt
491
- if t.alpha:
492
- alpha = t.alpha
493
- break
494
-
495
- # Fall back to default colors
496
- if not color and hasattr(theme, "colors"):
497
- palette = theme.colors.palette
498
- if palette:
499
- color = palette[0]
500
-
501
- if hasattr(theme, "lines"):
502
- linewidth = theme.lines.width_pt
503
-
504
- # Default color if none set
505
- if not color:
506
- color = "#1f77b4"
507
-
508
- # Get column names from encoding
509
- x_col_name = trace.x.column if trace.x else None
510
- y_col_name = trace.y.column if trace.y else None
511
-
512
- if not x_col_name or not y_col_name:
513
- logger.warning(f"Trace '{trace.trace_id}' missing x or y encoding, skipping")
514
- return
515
-
516
- # Find actual columns in data (handles prefixed names)
517
- x_col = _find_column(data, x_col_name)
518
- y_col = _find_column(data, y_col_name)
519
-
520
- if x_col is None:
521
- logger.warning(f"Column '{x_col_name}' not found in data for trace '{trace.trace_id}'. Available: {list(data.columns)[:5]}...")
522
- return
523
- if y_col is None:
524
- logger.warning(f"Column '{y_col_name}' not found in data for trace '{trace.trace_id}'. Available: {list(data.columns)[:5]}...")
525
- return
526
-
527
- # Plot the data
528
- ax.plot(
529
- data[x_col],
530
- data[y_col],
531
- color=color,
532
- linewidth=linewidth,
533
- alpha=alpha,
534
- label=trace.trace_id,
535
- )
536
-
537
-
538
- # EOF
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env python3
2
- # Timestamp: 2025-12-20
3
- # File: /home/ywatanabe/proj/scitex-code/src/scitex/fsb/_dataclasses/ChannelEncoding.py
4
-
5
- """ChannelEncoding - Single channel encoding."""
6
-
7
- from dataclasses import dataclass
8
- from typing import Any, Dict, Optional
9
-
10
-
11
- @dataclass
12
- class ChannelEncoding:
13
- """Encoding for a single visual channel (x, y, color, size, etc.)."""
14
-
15
- column: Optional[str] = None
16
- scale: str = "linear" # linear, log, categorical, ordinal, time
17
- domain: Optional[tuple] = None # Min/max or category list
18
- range: Optional[tuple] = None # Output range for mapping
19
-
20
- def to_dict(self) -> Dict[str, Any]:
21
- result = {}
22
- if self.column:
23
- result["column"] = self.column
24
- if self.scale != "linear":
25
- result["scale"] = self.scale
26
- if self.domain:
27
- result["domain"] = list(self.domain)
28
- if self.range:
29
- result["range"] = list(self.range)
30
- return result
31
-
32
- @classmethod
33
- def from_dict(cls, data: Dict[str, Any]) -> "ChannelEncoding":
34
- domain = data.get("domain")
35
- range_ = data.get("range")
36
- return cls(
37
- column=data.get("column"),
38
- scale=data.get("scale", "linear"),
39
- domain=tuple(domain) if domain else None,
40
- range=tuple(range_) if range_ else None,
41
- )
42
-
43
-
44
- __all__ = ["ChannelEncoding"]
45
-
46
- # EOF
@@ -1,82 +0,0 @@
1
- #!/usr/bin/env python3
2
- # Timestamp: 2025-12-20
3
- # File: /home/ywatanabe/proj/scitex-code/src/scitex/fsb/_dataclasses/Encoding.py
4
-
5
- """Encoding - Complete encoding specification for a bundle."""
6
-
7
- import json
8
- from dataclasses import dataclass, field
9
- from typing import Any, Dict, List
10
-
11
- from ._TraceEncoding import TraceEncoding
12
-
13
- ENCODING_VERSION = "1.0.0"
14
-
15
-
16
- @dataclass
17
- class AxesConfig:
18
- """Axis configuration for encoding."""
19
-
20
- title: str = ""
21
- type: str = "quantitative"
22
-
23
- def to_dict(self) -> Dict[str, Any]:
24
- result = {}
25
- if self.title:
26
- result["title"] = self.title
27
- if self.type != "quantitative":
28
- result["type"] = self.type
29
- return result
30
-
31
- @classmethod
32
- def from_dict(cls, data: Dict[str, Any]) -> "AxesConfig":
33
- return cls(
34
- title=data.get("title", ""),
35
- type=data.get("type", "quantitative"),
36
- )
37
-
38
-
39
- @dataclass
40
- class Encoding:
41
- """Complete encoding specification for a bundle.
42
-
43
- Stored in encoding.json at bundle root.
44
- """
45
-
46
- traces: List[TraceEncoding] = field(default_factory=list)
47
- axes: Dict[str, AxesConfig] = field(default_factory=dict) # {"x": AxesConfig, "y": AxesConfig}
48
-
49
- # Schema metadata
50
- schema_name: str = "fsb.encoding"
51
- schema_version: str = ENCODING_VERSION
52
-
53
- def to_dict(self) -> Dict[str, Any]:
54
- result = {
55
- "traces": [t.to_dict() for t in self.traces],
56
- }
57
- if self.axes:
58
- result["axes"] = {k: v.to_dict() for k, v in self.axes.items()}
59
- return result
60
-
61
- def to_json(self, indent: int = 2) -> str:
62
- return json.dumps(self.to_dict(), indent=indent)
63
-
64
- @classmethod
65
- def from_dict(cls, data: Dict[str, Any]) -> "Encoding":
66
- axes = {}
67
- axes_data = data.get("axes", {})
68
- for key, val in axes_data.items():
69
- axes[key] = AxesConfig.from_dict(val) if isinstance(val, dict) else AxesConfig()
70
- return cls(
71
- traces=[TraceEncoding.from_dict(t) for t in data.get("traces", [])],
72
- axes=axes,
73
- )
74
-
75
- @classmethod
76
- def from_json(cls, json_str: str) -> "Encoding":
77
- return cls.from_dict(json.loads(json_str))
78
-
79
-
80
- __all__ = ["ENCODING_VERSION", "AxesConfig", "Encoding"]
81
-
82
- # EOF