scitex 2.7.3__py3-none-any.whl → 2.10.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 (563) hide show
  1. scitex/__init__.py +15 -7
  2. scitex/__version__.py +1 -2
  3. scitex/_install_guide.py +250 -0
  4. scitex/_optional_deps.py +206 -39
  5. scitex/ai/_gen_ai/_Groq.py +2 -4
  6. scitex/ai/_gen_ai/_OpenAI.py +5 -2
  7. scitex/ai/_gen_ai/_Perplexity.py +20 -6
  8. scitex/audio/__init__.py +24 -15
  9. scitex/audio/_cross_process_lock.py +139 -0
  10. scitex/audio/_mcp_handlers.py +256 -0
  11. scitex/audio/_mcp_tool_schemas.py +203 -0
  12. scitex/audio/engines/elevenlabs_engine.py +5 -2
  13. scitex/audio/mcp_server.py +98 -457
  14. scitex/bridge/__init__.py +30 -19
  15. scitex/bridge/_figrecipe.py +245 -0
  16. scitex/bridge/_helpers.py +2 -1
  17. scitex/bridge/_plt_vis.py +23 -10
  18. scitex/bridge/_stats_plt.py +18 -5
  19. scitex/bridge/_stats_vis.py +16 -2
  20. scitex/browser/__init__.py +84 -44
  21. scitex/browser/automation/__init__.py +5 -1
  22. scitex/browser/core/BrowserMixin.py +17 -4
  23. scitex/browser/core/__init__.py +11 -2
  24. scitex/browser/remote/CaptchaHandler.py +1 -1
  25. scitex/browser/remote/ZenRowsAPIClient.py +1 -1
  26. scitex/capture/grid.py +487 -0
  27. scitex/capture/mcp_handlers.py +401 -0
  28. scitex/capture/mcp_tool_defs.py +192 -0
  29. scitex/capture/mcp_tools.py +241 -0
  30. scitex/capture/mcp_utils.py +30 -0
  31. scitex/cli/convert.py +421 -0
  32. scitex/cli/main.py +6 -4
  33. scitex/datetime/__init__.py +46 -0
  34. scitex/datetime/_linspace.py +100 -0
  35. scitex/datetime/_normalize_timestamp.py +306 -0
  36. scitex/db/_delete_duplicates.py +4 -4
  37. scitex/db/_sqlite3/_delete_duplicates.py +11 -2
  38. scitex/dev/plt/__init__.py +61 -62
  39. scitex/dev/plt/demo_plotters/__init__.py +0 -0
  40. scitex/dev/plt/demo_plotters/plot_mpl_axhline.py +28 -0
  41. scitex/dev/plt/demo_plotters/plot_mpl_axhspan.py +28 -0
  42. scitex/dev/plt/demo_plotters/plot_mpl_axvline.py +28 -0
  43. scitex/dev/plt/demo_plotters/plot_mpl_axvspan.py +28 -0
  44. scitex/dev/plt/demo_plotters/plot_mpl_bar.py +29 -0
  45. scitex/dev/plt/demo_plotters/plot_mpl_barh.py +29 -0
  46. scitex/dev/plt/demo_plotters/plot_mpl_boxplot.py +28 -0
  47. scitex/dev/plt/demo_plotters/plot_mpl_contour.py +31 -0
  48. scitex/dev/plt/demo_plotters/plot_mpl_contourf.py +31 -0
  49. scitex/dev/plt/demo_plotters/plot_mpl_errorbar.py +30 -0
  50. scitex/dev/plt/demo_plotters/plot_mpl_eventplot.py +28 -0
  51. scitex/dev/plt/demo_plotters/plot_mpl_fill.py +30 -0
  52. scitex/dev/plt/demo_plotters/plot_mpl_fill_between.py +31 -0
  53. scitex/dev/plt/demo_plotters/plot_mpl_hexbin.py +28 -0
  54. scitex/dev/plt/demo_plotters/plot_mpl_hist.py +28 -0
  55. scitex/dev/plt/demo_plotters/plot_mpl_hist2d.py +28 -0
  56. scitex/dev/plt/demo_plotters/plot_mpl_imshow.py +29 -0
  57. scitex/dev/plt/demo_plotters/plot_mpl_pcolormesh.py +31 -0
  58. scitex/dev/plt/demo_plotters/plot_mpl_pie.py +29 -0
  59. scitex/dev/plt/demo_plotters/plot_mpl_plot.py +29 -0
  60. scitex/dev/plt/demo_plotters/plot_mpl_quiver.py +31 -0
  61. scitex/dev/plt/demo_plotters/plot_mpl_scatter.py +28 -0
  62. scitex/dev/plt/demo_plotters/plot_mpl_stackplot.py +31 -0
  63. scitex/dev/plt/demo_plotters/plot_mpl_stem.py +29 -0
  64. scitex/dev/plt/demo_plotters/plot_mpl_step.py +29 -0
  65. scitex/dev/plt/demo_plotters/plot_mpl_violinplot.py +28 -0
  66. scitex/dev/plt/demo_plotters/plot_sns_barplot.py +29 -0
  67. scitex/dev/plt/demo_plotters/plot_sns_boxplot.py +29 -0
  68. scitex/dev/plt/demo_plotters/plot_sns_heatmap.py +28 -0
  69. scitex/dev/plt/demo_plotters/plot_sns_histplot.py +29 -0
  70. scitex/dev/plt/demo_plotters/plot_sns_kdeplot.py +29 -0
  71. scitex/dev/plt/demo_plotters/plot_sns_lineplot.py +31 -0
  72. scitex/dev/plt/demo_plotters/plot_sns_scatterplot.py +29 -0
  73. scitex/dev/plt/demo_plotters/plot_sns_stripplot.py +29 -0
  74. scitex/dev/plt/demo_plotters/plot_sns_swarmplot.py +29 -0
  75. scitex/dev/plt/demo_plotters/plot_sns_violinplot.py +29 -0
  76. scitex/dev/plt/demo_plotters/plot_stx_bar.py +29 -0
  77. scitex/dev/plt/demo_plotters/plot_stx_barh.py +29 -0
  78. scitex/dev/plt/demo_plotters/plot_stx_box.py +28 -0
  79. scitex/dev/plt/demo_plotters/plot_stx_boxplot.py +28 -0
  80. scitex/dev/plt/demo_plotters/plot_stx_conf_mat.py +28 -0
  81. scitex/dev/plt/demo_plotters/plot_stx_contour.py +31 -0
  82. scitex/dev/plt/demo_plotters/plot_stx_ecdf.py +28 -0
  83. scitex/dev/plt/demo_plotters/plot_stx_errorbar.py +30 -0
  84. scitex/dev/plt/demo_plotters/plot_stx_fill_between.py +31 -0
  85. scitex/dev/plt/demo_plotters/plot_stx_fillv.py +28 -0
  86. scitex/dev/plt/demo_plotters/plot_stx_heatmap.py +28 -0
  87. scitex/dev/plt/demo_plotters/plot_stx_image.py +28 -0
  88. scitex/dev/plt/demo_plotters/plot_stx_imshow.py +28 -0
  89. scitex/dev/plt/demo_plotters/plot_stx_joyplot.py +28 -0
  90. scitex/dev/plt/demo_plotters/plot_stx_kde.py +28 -0
  91. scitex/dev/plt/demo_plotters/plot_stx_line.py +28 -0
  92. scitex/dev/plt/demo_plotters/plot_stx_mean_ci.py +28 -0
  93. scitex/dev/plt/demo_plotters/plot_stx_mean_std.py +28 -0
  94. scitex/dev/plt/demo_plotters/plot_stx_median_iqr.py +28 -0
  95. scitex/dev/plt/demo_plotters/plot_stx_raster.py +28 -0
  96. scitex/dev/plt/demo_plotters/plot_stx_rectangle.py +28 -0
  97. scitex/dev/plt/demo_plotters/plot_stx_scatter.py +29 -0
  98. scitex/dev/plt/demo_plotters/plot_stx_shaded_line.py +29 -0
  99. scitex/dev/plt/demo_plotters/plot_stx_violin.py +28 -0
  100. scitex/dev/plt/demo_plotters/plot_stx_violinplot.py +28 -0
  101. scitex/dev/plt/mpl/get_dir_ax.py +46 -0
  102. scitex/dev/plt/mpl/get_signatures.py +176 -0
  103. scitex/dev/plt/mpl/get_signatures_details.py +522 -0
  104. scitex/dev/plt/plot_mpl_axhline.py +0 -0
  105. scitex/dev/plt/plot_mpl_axhspan.py +0 -0
  106. scitex/dev/plt/plot_mpl_axvline.py +0 -0
  107. scitex/dev/plt/plot_mpl_axvspan.py +0 -0
  108. scitex/dev/plt/plot_mpl_bar.py +0 -0
  109. scitex/dev/plt/plot_mpl_barh.py +0 -0
  110. scitex/dev/plt/plot_mpl_boxplot.py +0 -0
  111. scitex/dev/plt/plot_mpl_contour.py +0 -0
  112. scitex/dev/plt/plot_mpl_contourf.py +0 -0
  113. scitex/dev/plt/plot_mpl_errorbar.py +0 -0
  114. scitex/dev/plt/plot_mpl_eventplot.py +0 -0
  115. scitex/dev/plt/plot_mpl_fill.py +0 -0
  116. scitex/dev/plt/plot_mpl_fill_between.py +0 -0
  117. scitex/dev/plt/plot_mpl_hexbin.py +0 -0
  118. scitex/dev/plt/plot_mpl_hist.py +0 -0
  119. scitex/dev/plt/plot_mpl_hist2d.py +0 -0
  120. scitex/dev/plt/plot_mpl_imshow.py +0 -0
  121. scitex/dev/plt/plot_mpl_pcolormesh.py +0 -0
  122. scitex/dev/plt/plot_mpl_pie.py +0 -0
  123. scitex/dev/plt/plot_mpl_plot.py +0 -0
  124. scitex/dev/plt/plot_mpl_quiver.py +0 -0
  125. scitex/dev/plt/plot_mpl_scatter.py +0 -0
  126. scitex/dev/plt/plot_mpl_stackplot.py +0 -0
  127. scitex/dev/plt/plot_mpl_stem.py +0 -0
  128. scitex/dev/plt/plot_mpl_step.py +0 -0
  129. scitex/dev/plt/plot_mpl_violinplot.py +0 -0
  130. scitex/dev/plt/plot_sns_barplot.py +0 -0
  131. scitex/dev/plt/plot_sns_boxplot.py +0 -0
  132. scitex/dev/plt/plot_sns_heatmap.py +0 -0
  133. scitex/dev/plt/plot_sns_histplot.py +0 -0
  134. scitex/dev/plt/plot_sns_kdeplot.py +0 -0
  135. scitex/dev/plt/plot_sns_lineplot.py +0 -0
  136. scitex/dev/plt/plot_sns_scatterplot.py +0 -0
  137. scitex/dev/plt/plot_sns_stripplot.py +0 -0
  138. scitex/dev/plt/plot_sns_swarmplot.py +0 -0
  139. scitex/dev/plt/plot_sns_violinplot.py +0 -0
  140. scitex/dev/plt/plot_stx_bar.py +0 -0
  141. scitex/dev/plt/plot_stx_barh.py +0 -0
  142. scitex/dev/plt/plot_stx_box.py +0 -0
  143. scitex/dev/plt/plot_stx_boxplot.py +0 -0
  144. scitex/dev/plt/plot_stx_conf_mat.py +0 -0
  145. scitex/dev/plt/plot_stx_contour.py +0 -0
  146. scitex/dev/plt/plot_stx_ecdf.py +0 -0
  147. scitex/dev/plt/plot_stx_errorbar.py +0 -0
  148. scitex/dev/plt/plot_stx_fill_between.py +0 -0
  149. scitex/dev/plt/plot_stx_fillv.py +0 -0
  150. scitex/dev/plt/plot_stx_heatmap.py +0 -0
  151. scitex/dev/plt/plot_stx_image.py +0 -0
  152. scitex/dev/plt/plot_stx_imshow.py +0 -0
  153. scitex/dev/plt/plot_stx_joyplot.py +0 -0
  154. scitex/dev/plt/plot_stx_kde.py +0 -0
  155. scitex/dev/plt/plot_stx_line.py +0 -0
  156. scitex/dev/plt/plot_stx_mean_ci.py +0 -0
  157. scitex/dev/plt/plot_stx_mean_std.py +0 -0
  158. scitex/dev/plt/plot_stx_median_iqr.py +0 -0
  159. scitex/dev/plt/plot_stx_raster.py +0 -0
  160. scitex/dev/plt/plot_stx_rectangle.py +0 -0
  161. scitex/dev/plt/plot_stx_scatter.py +0 -0
  162. scitex/dev/plt/plot_stx_shaded_line.py +0 -0
  163. scitex/dev/plt/plot_stx_violin.py +0 -0
  164. scitex/dev/plt/plot_stx_violinplot.py +0 -0
  165. scitex/diagram/README.md +197 -0
  166. scitex/diagram/__init__.py +48 -0
  167. scitex/diagram/_compile.py +312 -0
  168. scitex/diagram/_diagram.py +355 -0
  169. scitex/diagram/_presets.py +173 -0
  170. scitex/diagram/_schema.py +182 -0
  171. scitex/diagram/_split.py +278 -0
  172. scitex/dict/_pop_keys.py +1 -7
  173. scitex/dsp/__init__.py +15 -10
  174. scitex/dsp/add_noise.py +5 -2
  175. scitex/dsp/example.py +35 -22
  176. scitex/dsp/filt.py +8 -3
  177. scitex/dsp/reference.py +3 -2
  178. scitex/dsp/utils/__init__.py +2 -1
  179. scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
  180. scitex/dt/__init__.py +39 -2
  181. scitex/errors.py +82 -521
  182. scitex/fig/__init__.py +4 -4
  183. scitex/fig/editor/__init__.py +5 -2
  184. scitex/fig/editor/_dearpygui_editor.py +1 -1
  185. scitex/fig/editor/_mpl_editor.py +1 -1
  186. scitex/fig/editor/_qt_editor.py +1 -1
  187. scitex/fig/editor/_tkinter_editor.py +1 -1
  188. scitex/fig/editor/edit/__init__.py +50 -0
  189. scitex/fig/editor/edit/backend_detector.py +109 -0
  190. scitex/fig/editor/edit/bundle_resolver.py +240 -0
  191. scitex/fig/editor/edit/editor_launcher.py +239 -0
  192. scitex/fig/editor/edit/manual_handler.py +53 -0
  193. scitex/fig/editor/edit/panel_loader.py +232 -0
  194. scitex/fig/editor/edit/path_resolver.py +67 -0
  195. scitex/fig/editor/flask_editor/_bbox.py +23 -0
  196. scitex/fig/editor/flask_editor/_core.py +908 -103
  197. scitex/fig/editor/flask_editor/_renderer.py +74 -0
  198. scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
  199. scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
  200. scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
  201. scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
  202. scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
  203. scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
  204. scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
  205. scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
  206. scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
  207. scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
  208. scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
  209. scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
  210. scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
  211. scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
  212. scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
  213. scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
  214. scitex/fig/editor/flask_editor/static/css/index.css +31 -0
  215. scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
  216. scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
  217. scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
  218. scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
  219. scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
  220. scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
  221. scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
  222. scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
  223. scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
  224. scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
  225. scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
  226. scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
  227. scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
  228. scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
  229. scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
  230. scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
  231. scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
  232. scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
  233. scitex/fig/editor/flask_editor/static/js/main.js +426 -0
  234. scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
  235. scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
  236. scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
  237. scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
  238. scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
  239. scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
  240. scitex/fig/editor/flask_editor/templates/__init__.py +95 -5
  241. scitex/fig/editor/flask_editor/templates/_html.py +27 -9
  242. scitex/fig/editor/flask_editor/templates/_scripts.py +1928 -131
  243. scitex/fig/editor/flask_editor/templates/_styles.py +363 -51
  244. scitex/fig/io/_bundle.py +104 -19
  245. scitex/fts/README.md +262 -0
  246. scitex/fts/TODO.md +66 -0
  247. scitex/fts/__init__.py +90 -0
  248. scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
  249. scitex/fts/_bundle/_FTS.py +657 -0
  250. scitex/fts/_bundle/__init__.py +38 -0
  251. scitex/fts/_bundle/_children.py +216 -0
  252. scitex/fts/_bundle/_conversion/__init__.py +15 -0
  253. scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
  254. scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
  255. scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
  256. scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
  257. scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
  258. scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
  259. scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
  260. scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
  261. scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
  262. scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
  263. scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
  264. scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
  265. scitex/fts/_bundle/_extractors/__init__.py +32 -0
  266. scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
  267. scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
  268. scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
  269. scitex/fts/_bundle/_loader.py +134 -0
  270. scitex/fts/_bundle/_mpl_helpers.py +389 -0
  271. scitex/fts/_bundle/_saver.py +269 -0
  272. scitex/fts/_bundle/_storage.py +200 -0
  273. scitex/fts/_bundle/_utils/__init__.py +55 -0
  274. scitex/fts/_bundle/_utils/_const.py +26 -0
  275. scitex/fts/_bundle/_utils/_errors.py +73 -0
  276. scitex/fts/_bundle/_utils/_generate.py +21 -0
  277. scitex/fts/_bundle/_utils/_types.py +76 -0
  278. scitex/fts/_bundle/_validation.py +434 -0
  279. scitex/fts/_bundle/_zipbundle.py +165 -0
  280. scitex/fts/_fig/__init__.py +22 -0
  281. scitex/fts/_fig/_backend/__init__.py +53 -0
  282. scitex/fts/_fig/_backend/_export.py +165 -0
  283. scitex/fts/_fig/_backend/_parser.py +188 -0
  284. scitex/fts/_fig/_backend/_render.py +538 -0
  285. scitex/fts/_fig/_composite.py +345 -0
  286. scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
  287. scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
  288. scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
  289. scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
  290. scitex/fts/_fig/_dataclasses/__init__.py +47 -0
  291. scitex/fts/_fig/_editor/__init__.py +14 -0
  292. scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
  293. scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
  294. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
  295. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
  296. scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
  297. scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
  298. scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
  299. scitex/fts/_fig/_editor/_defaults.py +300 -0
  300. scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
  301. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
  302. scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
  303. scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
  304. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
  305. scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
  306. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
  307. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
  308. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
  309. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
  310. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
  311. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
  312. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
  313. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
  314. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
  315. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
  316. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
  317. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
  318. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
  319. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
  320. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
  321. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
  322. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
  323. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
  324. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
  325. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
  326. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
  327. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
  328. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
  329. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
  330. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
  331. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
  332. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
  333. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
  334. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
  335. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
  336. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
  337. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
  338. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
  339. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
  340. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
  341. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
  342. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
  343. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
  344. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
  345. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
  346. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
  347. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
  348. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
  349. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
  350. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
  351. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
  352. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
  353. scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
  354. scitex/fts/_fig/_models/_Annotations.py +115 -0
  355. scitex/fts/_fig/_models/_Axes.py +152 -0
  356. scitex/fts/_fig/_models/_Figure.py +138 -0
  357. scitex/fts/_fig/_models/_Guides.py +104 -0
  358. scitex/fts/_fig/_models/_Plot.py +123 -0
  359. scitex/fts/_fig/_models/_Styles.py +245 -0
  360. scitex/fts/_fig/_models/__init__.py +80 -0
  361. scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
  362. scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
  363. scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
  364. scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
  365. scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
  366. scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
  367. scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
  368. scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
  369. scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
  370. scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
  371. scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
  372. scitex/fts/_fig/_utils/__init__.py +129 -0
  373. scitex/fts/_fig/_utils/_auto_layout.py +127 -0
  374. scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
  375. scitex/fts/_fig/_utils/_const_sizes.py +48 -0
  376. scitex/fts/_fig/_utils/_convert_coords.py +77 -0
  377. scitex/fts/_fig/_utils/_get_template.py +178 -0
  378. scitex/fts/_fig/_utils/_normalize.py +73 -0
  379. scitex/fts/_fig/_utils/_plot_layout.py +397 -0
  380. scitex/fts/_fig/_utils/_validate.py +197 -0
  381. scitex/fts/_kinds/__init__.py +45 -0
  382. scitex/fts/_kinds/_figure/__init__.py +19 -0
  383. scitex/fts/_kinds/_figure/_composite.py +345 -0
  384. scitex/fts/_kinds/_plot/__init__.py +25 -0
  385. scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
  386. scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
  387. scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
  388. scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
  389. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
  390. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
  391. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
  392. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
  393. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
  394. scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
  395. scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
  396. scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
  397. scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
  398. scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
  399. scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
  400. scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
  401. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
  402. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
  403. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
  404. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
  405. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
  406. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
  407. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
  408. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
  409. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
  410. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
  411. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
  412. scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
  413. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
  414. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
  415. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
  416. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
  417. scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
  418. scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
  419. scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
  420. scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
  421. scitex/fts/_kinds/_shape/__init__.py +141 -0
  422. scitex/fts/_kinds/_stats/__init__.py +56 -0
  423. scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
  424. scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
  425. scitex/fts/_kinds/_table/__init__.py +72 -0
  426. scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
  427. scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
  428. scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
  429. scitex/fts/_kinds/_table/_latex/_export.py +279 -0
  430. scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
  431. scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
  432. scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
  433. scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
  434. scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
  435. scitex/fts/_kinds/_text/__init__.py +77 -0
  436. scitex/fts/_schemas/data_info.schema.json +75 -0
  437. scitex/fts/_schemas/encoding.schema.json +90 -0
  438. scitex/fts/_schemas/node.schema.json +145 -0
  439. scitex/fts/_schemas/render_manifest.schema.json +62 -0
  440. scitex/fts/_schemas/stats.schema.json +132 -0
  441. scitex/fts/_schemas/theme.schema.json +141 -0
  442. scitex/fts/_stats/__init__.py +48 -0
  443. scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
  444. scitex/fts/_stats/_dataclasses/__init__.py +48 -0
  445. scitex/fts/_tables/__init__.py +65 -0
  446. scitex/fts/_tables/_latex/__init__.py +93 -0
  447. scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
  448. scitex/fts/_tables/_latex/_editor/_app.py +725 -0
  449. scitex/fts/_tables/_latex/_export.py +279 -0
  450. scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
  451. scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
  452. scitex/fts/_tables/_latex/_table_exporter.py +362 -0
  453. scitex/fts/_tables/_latex/_utils.py +369 -0
  454. scitex/fts/_tables/_latex/_validator.py +445 -0
  455. scitex/gen/__init__.py +66 -25
  456. scitex/gen/misc.py +28 -0
  457. scitex/io/__init__.py +47 -20
  458. scitex/io/_load.py +87 -36
  459. scitex/io/_load_modules/__init__.py +10 -7
  460. scitex/io/_load_modules/_pandas.py +6 -1
  461. scitex/io/_save.py +299 -1556
  462. scitex/io/_save_modules/__init__.py +76 -19
  463. scitex/io/_save_modules/_figure_utils.py +90 -0
  464. scitex/io/_save_modules/_image_csv.py +497 -0
  465. scitex/io/_save_modules/_legends.py +91 -0
  466. scitex/io/_save_modules/_pltz_bundle.py +356 -0
  467. scitex/io/_save_modules/_pltz_stx.py +536 -0
  468. scitex/io/_save_modules/_stx_bundle.py +104 -0
  469. scitex/io/_save_modules/_symlink.py +96 -0
  470. scitex/io/_save_modules/_yaml.py +1 -1
  471. scitex/io/_save_modules/_zarr.py +64 -18
  472. scitex/io/bundle/README.md +212 -0
  473. scitex/io/bundle/__init__.py +110 -0
  474. scitex/io/{_bundle.py → bundle/_core.py} +219 -89
  475. scitex/io/bundle/_nested.py +713 -0
  476. scitex/io/bundle/_types.py +74 -0
  477. scitex/io/bundle/_zip.py +487 -0
  478. scitex/io/utils/h5_to_zarr.py +1 -1
  479. scitex/logging/__init__.py +108 -13
  480. scitex/logging/_errors.py +508 -0
  481. scitex/logging/_formatters.py +30 -6
  482. scitex/logging/_warnings.py +261 -0
  483. scitex/plt/__init__.py +4 -1
  484. scitex/plt/_figrecipe.py +236 -0
  485. scitex/plt/_subplots/_AxisWrapper.py +6 -0
  486. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +0 -0
  487. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +0 -0
  488. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +0 -0
  489. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +0 -0
  490. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +0 -0
  491. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +0 -0
  492. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +0 -0
  493. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +0 -0
  494. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +0 -0
  495. scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +0 -0
  496. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +0 -0
  497. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +0 -0
  498. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +0 -0
  499. scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
  500. scitex/plt/_subplots/_FigWrapper.py +15 -0
  501. scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
  502. scitex/plt/_subplots/_export_as_csv.py +11 -0
  503. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
  504. scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
  505. scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
  506. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +0 -0
  507. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +0 -0
  508. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +0 -0
  509. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +0 -0
  510. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
  511. scitex/plt/_subplots/_fonts.py +71 -0
  512. scitex/plt/_subplots/_mm_layout.py +282 -0
  513. scitex/plt/gallery/__init__.py +99 -2
  514. scitex/plt/io/_layered_bundle.py +0 -0
  515. scitex/plt/styles/_plot_postprocess.py +3 -1
  516. scitex/plt/utils/_configure_mpl.py +16 -19
  517. scitex/repro/_RandomStateManager.py +13 -8
  518. scitex/resource/__init__.py +19 -1
  519. scitex/resource/_utils/_get_env_info.py +13 -25
  520. scitex/schema/__init__.py +149 -160
  521. scitex/schema/_encoding.py +273 -0
  522. scitex/schema/_figure_elements.py +406 -0
  523. scitex/schema/_plot.py +0 -0
  524. scitex/schema/_theme.py +360 -0
  525. scitex/schema/_validation.py +0 -98
  526. scitex/scholar/__init__.py +56 -14
  527. scitex/scholar/auth/ScholarAuthManager.py +1 -1
  528. scitex/scholar/auth/__init__.py +11 -2
  529. scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
  530. scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
  531. scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
  532. scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
  533. scitex/scholar/config/ScholarConfig.py +1 -1
  534. scitex/scholar/core/Scholar.py +1 -1
  535. scitex/session/_decorator.py +18 -16
  536. scitex/session/_lifecycle.py +9 -11
  537. scitex/session/template.py +9 -8
  538. scitex/sh/test_sh.py +72 -0
  539. scitex/sh/test_sh_simple.py +61 -0
  540. scitex/stats/__init__.py +221 -97
  541. scitex/stats/_schema.py +21 -22
  542. scitex/stats/descriptive/_circular.py +212 -351
  543. scitex/stats/descriptive/_describe.py +81 -132
  544. scitex/stats/descriptive/_nan.py +205 -433
  545. scitex/stats/descriptive/_real.py +127 -141
  546. scitex/str/_format_plot_text.py +5 -5
  547. scitex/str/_latex.py +26 -84
  548. scitex/str/_latex_fallback.py +53 -47
  549. scitex/web/_search_pubmed.py +5 -4
  550. scitex/writer/tests/test_diff_between.py +451 -0
  551. scitex/writer/tests/test_document_section.py +311 -0
  552. scitex/writer/tests/test_document_workflow.py +393 -0
  553. scitex/writer/tests/test_writer.py +361 -0
  554. scitex/writer/tests/test_writer_integration.py +303 -0
  555. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
  556. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/RECORD +479 -108
  557. scitex/fig/editor/_edit.py +0 -751
  558. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
  559. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
  560. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
  561. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
  562. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
  563. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-21
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_kinds/_shape/__init__.py
4
+
5
+ """Shape kind - Shape annotation elements.
6
+
7
+ A shape bundle contains geometric shapes (no payload data).
8
+ Used for arrows, rectangles, circles, lines in figures.
9
+
10
+ Structure:
11
+ - canonical/node.json: Shape geometry and styling
12
+ - No payload (shape definition is in node specification)
13
+ """
14
+
15
+ from typing import Any, Optional, TYPE_CHECKING
16
+
17
+ if TYPE_CHECKING:
18
+ from matplotlib.axes import Axes
19
+ from matplotlib.patches import Patch
20
+
21
+
22
+ def render_shape(
23
+ ax: "Axes",
24
+ shape_type: str,
25
+ x: float,
26
+ y: float,
27
+ width: Optional[float] = None,
28
+ height: Optional[float] = None,
29
+ radius: Optional[float] = None,
30
+ x2: Optional[float] = None,
31
+ y2: Optional[float] = None,
32
+ facecolor: Optional[str] = None,
33
+ edgecolor: Optional[str] = None,
34
+ linewidth: float = 1.0,
35
+ linestyle: str = "-",
36
+ alpha: float = 1.0,
37
+ **kwargs: Any,
38
+ ) -> Optional["Patch"]:
39
+ """Render shape annotation on axes.
40
+
41
+ Parameters
42
+ ----------
43
+ ax : Axes
44
+ Matplotlib axes to render on
45
+ shape_type : str
46
+ Type of shape: rectangle, circle, ellipse, line, arrow
47
+ x, y : float
48
+ Position/start point in axes coordinates
49
+ width, height : float, optional
50
+ Dimensions for rectangle/ellipse
51
+ radius : float, optional
52
+ Radius for circle
53
+ x2, y2 : float, optional
54
+ End point for line/arrow
55
+ facecolor : str, optional
56
+ Fill color
57
+ edgecolor : str, optional
58
+ Edge/line color
59
+ linewidth : float
60
+ Line width in points
61
+ linestyle : str
62
+ Line style (-, --, :, -.)
63
+ alpha : float
64
+ Opacity (0-1)
65
+ **kwargs : Any
66
+ Additional kwargs passed to patch constructor
67
+
68
+ Returns
69
+ -------
70
+ Patch or None
71
+ The created matplotlib patch, or None for lines
72
+ """
73
+ from matplotlib.patches import (
74
+ Rectangle,
75
+ Circle,
76
+ Ellipse,
77
+ FancyArrowPatch,
78
+ )
79
+ from matplotlib.lines import Line2D
80
+
81
+ patch_kwargs = {
82
+ "linewidth": linewidth,
83
+ "linestyle": linestyle,
84
+ "alpha": alpha,
85
+ }
86
+ if facecolor is not None:
87
+ patch_kwargs["facecolor"] = facecolor
88
+ if edgecolor is not None:
89
+ patch_kwargs["edgecolor"] = edgecolor
90
+ patch_kwargs.update(kwargs)
91
+
92
+ patch = None
93
+
94
+ if shape_type == "rectangle":
95
+ w = width or 0.1
96
+ h = height or 0.1
97
+ patch = Rectangle(
98
+ (x, y), w, h, transform=ax.transAxes, **patch_kwargs
99
+ )
100
+ ax.add_patch(patch)
101
+
102
+ elif shape_type == "circle":
103
+ r = radius or 0.05
104
+ patch = Circle((x, y), r, transform=ax.transAxes, **patch_kwargs)
105
+ ax.add_patch(patch)
106
+
107
+ elif shape_type == "ellipse":
108
+ w = width or 0.1
109
+ h = height or 0.05
110
+ patch = Ellipse((x, y), w, h, transform=ax.transAxes, **patch_kwargs)
111
+ ax.add_patch(patch)
112
+
113
+ elif shape_type == "line":
114
+ line = Line2D(
115
+ [x, x2 or x + 0.1],
116
+ [y, y2 or y],
117
+ transform=ax.transAxes,
118
+ color=edgecolor or "black",
119
+ linewidth=linewidth,
120
+ linestyle=linestyle,
121
+ alpha=alpha,
122
+ )
123
+ ax.add_line(line)
124
+
125
+ elif shape_type == "arrow":
126
+ patch = FancyArrowPatch(
127
+ (x, y),
128
+ (x2 or x + 0.1, y2 or y),
129
+ transform=ax.transAxes,
130
+ arrowstyle="->",
131
+ mutation_scale=10,
132
+ **patch_kwargs,
133
+ )
134
+ ax.add_patch(patch)
135
+
136
+ return patch
137
+
138
+
139
+ __all__ = ["render_shape"]
140
+
141
+ # EOF
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-21
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_kinds/_stats/__init__.py
4
+
5
+ """Stats kind - Statistical analysis results.
6
+
7
+ A stats bundle contains statistical test results (payload/stats.json).
8
+ Used for annotations like p-values, effect sizes, confidence intervals.
9
+
10
+ Structure:
11
+ - payload/stats.json: Statistical results
12
+ - analyses: List of statistical tests and their results
13
+ """
14
+
15
+ # Public dataclasses
16
+ from ._dataclasses import (
17
+ STATS_VERSION,
18
+ Stats,
19
+ # Type aliases
20
+ PositionMode,
21
+ UnitType,
22
+ SymbolStyle,
23
+ # GUI classes
24
+ Position,
25
+ StatStyling,
26
+ StatPositioning,
27
+ # Core classes
28
+ DataRef,
29
+ EffectSize,
30
+ StatMethod,
31
+ StatResult,
32
+ StatDisplay,
33
+ Analysis,
34
+ )
35
+
36
+ __all__ = [
37
+ "STATS_VERSION",
38
+ "Stats",
39
+ # Type aliases
40
+ "PositionMode",
41
+ "UnitType",
42
+ "SymbolStyle",
43
+ # GUI classes
44
+ "Position",
45
+ "StatStyling",
46
+ "StatPositioning",
47
+ # Core classes
48
+ "DataRef",
49
+ "EffectSize",
50
+ "StatMethod",
51
+ "StatResult",
52
+ "StatDisplay",
53
+ "Analysis",
54
+ ]
55
+
56
+ # EOF
@@ -0,0 +1,423 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_stats/_dataclasses/_Stats.py
4
+
5
+ """
6
+ Stats - Statistical analysis results with provenance and GUI support.
7
+
8
+ This module provides the single source of truth for statistical result schemas,
9
+ supporting both:
10
+ 1. Bundle storage (data provenance, test results)
11
+ 2. GUI annotation (positioning, styling for interactive editing)
12
+ """
13
+
14
+ import json
15
+ from dataclasses import dataclass, field, asdict
16
+ from datetime import datetime
17
+ from typing import Any, Dict, List, Literal, Optional, Union
18
+
19
+ STATS_VERSION = "1.1.0"
20
+
21
+ # Type aliases for GUI support
22
+ PositionMode = Literal["absolute", "relative_to_plot", "above_whisker", "auto"]
23
+ UnitType = Literal["mm", "px", "inch", "data"]
24
+ SymbolStyle = Literal["asterisk", "text", "bracket", "compact", "detailed", "publication"]
25
+
26
+
27
+ @dataclass
28
+ class DataRef:
29
+ """Reference to data used in analysis."""
30
+
31
+ path: str
32
+ columns: Optional[List[str]] = None
33
+ filter: Optional[str] = None
34
+
35
+ def to_dict(self) -> Dict[str, Any]:
36
+ result = {"path": self.path}
37
+ if self.columns:
38
+ result["columns"] = self.columns
39
+ if self.filter:
40
+ result["filter"] = self.filter
41
+ return result
42
+
43
+ @classmethod
44
+ def from_dict(cls, data: Dict[str, Any]) -> "DataRef":
45
+ return cls(
46
+ path=data.get("path", ""),
47
+ columns=data.get("columns"),
48
+ filter=data.get("filter"),
49
+ )
50
+
51
+
52
+ # =============================================================================
53
+ # GUI Position and Styling Classes (merged from scitex.schema._stats)
54
+ # =============================================================================
55
+
56
+
57
+ @dataclass
58
+ class Position:
59
+ """
60
+ Position specification with unit support for GUI integration.
61
+
62
+ Supports multiple coordinate systems for flexibility across
63
+ matplotlib (mm), Fabric.js (px), and data coordinates.
64
+ """
65
+
66
+ x: float
67
+ y: float
68
+ unit: UnitType = "mm"
69
+ relative_to: Optional[str] = None # Plot ID or "axes"
70
+ offset: Optional[Dict[str, float]] = None # {"dx": 0, "dy": 0}
71
+
72
+ def to_dict(self) -> Dict[str, Any]:
73
+ return {
74
+ "x": self.x,
75
+ "y": self.y,
76
+ "unit": self.unit,
77
+ "relative_to": self.relative_to,
78
+ "offset": self.offset,
79
+ }
80
+
81
+ @classmethod
82
+ def from_dict(cls, data: Dict[str, Any]) -> "Position":
83
+ return cls(**data)
84
+
85
+ def to_mm(self, dpi: float = 300.0) -> "Position":
86
+ """Convert position to mm (for matplotlib)."""
87
+ if self.unit == "mm":
88
+ return self
89
+ elif self.unit == "px":
90
+ mm_per_px = 25.4 / dpi
91
+ return Position(
92
+ x=self.x * mm_per_px,
93
+ y=self.y * mm_per_px,
94
+ unit="mm",
95
+ relative_to=self.relative_to,
96
+ offset=self.offset,
97
+ )
98
+ elif self.unit == "inch":
99
+ return Position(
100
+ x=self.x * 25.4,
101
+ y=self.y * 25.4,
102
+ unit="mm",
103
+ relative_to=self.relative_to,
104
+ offset=self.offset,
105
+ )
106
+ return self
107
+
108
+ def to_px(self, dpi: float = 300.0) -> "Position":
109
+ """Convert position to px (for Fabric.js canvas)."""
110
+ mm_pos = self.to_mm(dpi)
111
+ px_per_mm = dpi / 25.4
112
+ return Position(
113
+ x=mm_pos.x * px_per_mm,
114
+ y=mm_pos.y * px_per_mm,
115
+ unit="px",
116
+ relative_to=self.relative_to,
117
+ offset=self.offset,
118
+ )
119
+
120
+
121
+ @dataclass
122
+ class StatStyling:
123
+ """Styling configuration for statistical annotation display."""
124
+
125
+ font_size_pt: float = 7.0
126
+ font_family: str = "Arial"
127
+ color: str = "#000000"
128
+ symbol_style: SymbolStyle = "asterisk"
129
+ line_width_mm: Optional[float] = None
130
+ bracket_height_mm: Optional[float] = None
131
+ theme: Literal["light", "dark", "auto"] = "auto"
132
+
133
+ def to_dict(self) -> Dict[str, Any]:
134
+ return asdict(self)
135
+
136
+ @classmethod
137
+ def from_dict(cls, data: Dict[str, Any]) -> "StatStyling":
138
+ return cls(**data)
139
+
140
+ def get_theme_color(self, is_dark: bool = False) -> str:
141
+ """Get appropriate color for theme."""
142
+ if self.theme == "auto":
143
+ return "#ffffff" if is_dark else "#000000"
144
+ elif self.theme == "dark":
145
+ return "#ffffff"
146
+ return "#000000"
147
+
148
+
149
+ @dataclass
150
+ class StatPositioning:
151
+ """Position configuration for GUI-ready annotation placement."""
152
+
153
+ mode: PositionMode = "auto"
154
+ position: Optional[Position] = None
155
+ preferred_corner: Optional[str] = None # "top-right", "bottom-left", etc.
156
+ avoid_overlap: bool = True
157
+ min_distance_mm: float = 2.0
158
+ anchor_to: Optional[str] = None # "plot_center", "whisker_top", etc.
159
+
160
+ def to_dict(self) -> Dict[str, Any]:
161
+ return {
162
+ "mode": self.mode,
163
+ "position": self.position.to_dict() if self.position else None,
164
+ "preferred_corner": self.preferred_corner,
165
+ "avoid_overlap": self.avoid_overlap,
166
+ "min_distance_mm": self.min_distance_mm,
167
+ "anchor_to": self.anchor_to,
168
+ }
169
+
170
+ @classmethod
171
+ def from_dict(cls, data: Dict[str, Any]) -> "StatPositioning":
172
+ data_copy = data.copy()
173
+ if data_copy.get("position"):
174
+ data_copy["position"] = Position.from_dict(data_copy["position"])
175
+ return cls(**data_copy)
176
+
177
+
178
+ @dataclass
179
+ class EffectSize:
180
+ """Effect size with confidence interval."""
181
+
182
+ name: str # cohens_d, hedges_g, eta_squared, r_squared, etc.
183
+ value: float
184
+ ci_lower: Optional[float] = None
185
+ ci_upper: Optional[float] = None
186
+ ci_level: float = 0.95
187
+
188
+ def to_dict(self) -> Dict[str, Any]:
189
+ result = {"name": self.name, "value": self.value}
190
+ if self.ci_lower is not None:
191
+ result["ci_lower"] = self.ci_lower
192
+ if self.ci_upper is not None:
193
+ result["ci_upper"] = self.ci_upper
194
+ if self.ci_level != 0.95:
195
+ result["ci_level"] = self.ci_level
196
+ return result
197
+
198
+ @classmethod
199
+ def from_dict(cls, data: Dict[str, Any]) -> "EffectSize":
200
+ return cls(
201
+ name=data.get("name", ""),
202
+ value=data.get("value", 0.0),
203
+ ci_lower=data.get("ci_lower"),
204
+ ci_upper=data.get("ci_upper"),
205
+ ci_level=data.get("ci_level", 0.95),
206
+ )
207
+
208
+
209
+ @dataclass
210
+ class StatMethod:
211
+ """Statistical method specification."""
212
+
213
+ name: str # t-test, anova, chi-squared, correlation, etc.
214
+ variant: Optional[str] = None # independent, paired, one-way, etc.
215
+ parameters: Dict[str, Any] = field(default_factory=dict)
216
+
217
+ def to_dict(self) -> Dict[str, Any]:
218
+ result = {"name": self.name}
219
+ if self.variant:
220
+ result["variant"] = self.variant
221
+ if self.parameters:
222
+ result["parameters"] = self.parameters
223
+ return result
224
+
225
+ @classmethod
226
+ def from_dict(cls, data: Dict[str, Any]) -> "StatMethod":
227
+ return cls(
228
+ name=data.get("name", ""),
229
+ variant=data.get("variant"),
230
+ parameters=data.get("parameters", {}),
231
+ )
232
+
233
+
234
+ @dataclass
235
+ class StatResult:
236
+ """Statistical test result."""
237
+
238
+ statistic: float
239
+ statistic_name: str # t, F, chi2, r, etc.
240
+ p_value: float
241
+ df: Optional[float] = None
242
+ effect_size: Optional[EffectSize] = None
243
+ significant: Optional[bool] = None
244
+ alpha: float = 0.05
245
+
246
+ def to_dict(self) -> Dict[str, Any]:
247
+ result = {
248
+ "statistic": self.statistic,
249
+ "statistic_name": self.statistic_name,
250
+ "p_value": self.p_value,
251
+ }
252
+ if self.df is not None:
253
+ result["df"] = self.df
254
+ if self.effect_size:
255
+ result["effect_size"] = self.effect_size.to_dict()
256
+ if self.significant is not None:
257
+ result["significant"] = self.significant
258
+ if self.alpha != 0.05:
259
+ result["alpha"] = self.alpha
260
+ return result
261
+
262
+ @classmethod
263
+ def from_dict(cls, data: Dict[str, Any]) -> "StatResult":
264
+ effect_size = None
265
+ if "effect_size" in data:
266
+ effect_size = EffectSize.from_dict(data["effect_size"])
267
+ return cls(
268
+ statistic=data.get("statistic", 0.0),
269
+ statistic_name=data.get("statistic_name", ""),
270
+ p_value=data.get("p_value", 1.0),
271
+ df=data.get("df"),
272
+ effect_size=effect_size,
273
+ significant=data.get("significant"),
274
+ alpha=data.get("alpha", 0.05),
275
+ )
276
+
277
+
278
+ @dataclass
279
+ class StatDisplay:
280
+ """How to display the statistical result (with GUI support)."""
281
+
282
+ show_stars: bool = True
283
+ show_p_value: bool = True
284
+ show_effect_size: bool = False
285
+ bracket_groups: Optional[List[str]] = None
286
+ # Enhanced GUI support
287
+ positioning: Optional[StatPositioning] = None
288
+ styling: Optional[StatStyling] = None
289
+ plot_id: Optional[str] = None # Associated plot in TrackingMixin
290
+
291
+ def to_dict(self) -> Dict[str, Any]:
292
+ result = {
293
+ "show_stars": self.show_stars,
294
+ "show_p_value": self.show_p_value,
295
+ "show_effect_size": self.show_effect_size,
296
+ }
297
+ if self.bracket_groups:
298
+ result["bracket_groups"] = self.bracket_groups
299
+ if self.positioning:
300
+ result["positioning"] = self.positioning.to_dict()
301
+ if self.styling:
302
+ result["styling"] = self.styling.to_dict()
303
+ if self.plot_id:
304
+ result["plot_id"] = self.plot_id
305
+ return result
306
+
307
+ @classmethod
308
+ def from_dict(cls, data: Dict[str, Any]) -> "StatDisplay":
309
+ positioning = None
310
+ if "positioning" in data and data["positioning"]:
311
+ positioning = StatPositioning.from_dict(data["positioning"])
312
+ styling = None
313
+ if "styling" in data and data["styling"]:
314
+ styling = StatStyling.from_dict(data["styling"])
315
+ return cls(
316
+ show_stars=data.get("show_stars", True),
317
+ show_p_value=data.get("show_p_value", True),
318
+ show_effect_size=data.get("show_effect_size", False),
319
+ bracket_groups=data.get("bracket_groups"),
320
+ positioning=positioning,
321
+ styling=styling,
322
+ plot_id=data.get("plot_id"),
323
+ )
324
+
325
+
326
+ @dataclass
327
+ class Analysis:
328
+ """Complete analysis record with provenance."""
329
+
330
+ result_id: str
331
+ method: StatMethod
332
+ results: StatResult
333
+ data_refs: List[DataRef] = field(default_factory=list)
334
+ inputs: Dict[str, Any] = field(default_factory=dict)
335
+ display: Optional[StatDisplay] = None
336
+
337
+ def to_dict(self) -> Dict[str, Any]:
338
+ result = {
339
+ "result_id": self.result_id,
340
+ "method": self.method.to_dict(),
341
+ "results": self.results.to_dict(),
342
+ }
343
+ if self.data_refs:
344
+ result["data_refs"] = [d.to_dict() for d in self.data_refs]
345
+ if self.inputs:
346
+ result["inputs"] = self.inputs
347
+ if self.display:
348
+ result["display"] = self.display.to_dict()
349
+ return result
350
+
351
+ @classmethod
352
+ def from_dict(cls, data: Dict[str, Any]) -> "Analysis":
353
+ display = None
354
+ if "display" in data:
355
+ display = StatDisplay.from_dict(data["display"])
356
+ return cls(
357
+ result_id=data.get("result_id", ""),
358
+ method=StatMethod.from_dict(data.get("method", {})),
359
+ results=StatResult.from_dict(data.get("results", {})),
360
+ data_refs=[DataRef.from_dict(d) for d in data.get("data_refs", [])],
361
+ inputs=data.get("inputs", {}),
362
+ display=display,
363
+ )
364
+
365
+
366
+ @dataclass
367
+ class Stats:
368
+ """Complete statistics specification for a bundle.
369
+
370
+ Stored in stats/stats.json.
371
+ """
372
+
373
+ analyses: List[Analysis] = field(default_factory=list)
374
+ software: Dict[str, str] = field(default_factory=dict)
375
+
376
+ # Schema metadata
377
+ schema_name: str = "fsb.stats"
378
+ schema_version: str = STATS_VERSION
379
+
380
+ def to_dict(self) -> Dict[str, Any]:
381
+ result = {"analyses": [a.to_dict() for a in self.analyses]}
382
+ if self.software:
383
+ result["software"] = self.software
384
+ return result
385
+
386
+ def to_json(self, indent: int = 2) -> str:
387
+ return json.dumps(self.to_dict(), indent=indent)
388
+
389
+ @classmethod
390
+ def from_dict(cls, data: Dict[str, Any]) -> "Stats":
391
+ return cls(
392
+ analyses=[Analysis.from_dict(a) for a in data.get("analyses", [])],
393
+ software=data.get("software", {}),
394
+ )
395
+
396
+ @classmethod
397
+ def from_json(cls, json_str: str) -> "Stats":
398
+ return cls.from_dict(json.loads(json_str))
399
+
400
+
401
+ __all__ = [
402
+ # Version
403
+ "STATS_VERSION",
404
+ # Type aliases
405
+ "PositionMode",
406
+ "UnitType",
407
+ "SymbolStyle",
408
+ # Data reference
409
+ "DataRef",
410
+ # GUI classes (merged from scitex.schema._stats)
411
+ "Position",
412
+ "StatStyling",
413
+ "StatPositioning",
414
+ # Core stats classes
415
+ "EffectSize",
416
+ "StatMethod",
417
+ "StatResult",
418
+ "StatDisplay",
419
+ "Analysis",
420
+ "Stats",
421
+ ]
422
+
423
+ # EOF
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/fts/_stats/_dataclasses/__init__.py
4
+
5
+ """Statistics-specific dataclasses for FTS with GUI support."""
6
+
7
+ from ._Stats import (
8
+ STATS_VERSION,
9
+ # Type aliases
10
+ PositionMode,
11
+ UnitType,
12
+ SymbolStyle,
13
+ # GUI classes
14
+ Position,
15
+ StatStyling,
16
+ StatPositioning,
17
+ # Core classes
18
+ Analysis,
19
+ DataRef,
20
+ EffectSize,
21
+ StatDisplay,
22
+ StatMethod,
23
+ StatResult,
24
+ Stats,
25
+ )
26
+
27
+ __all__ = [
28
+ # Version
29
+ "STATS_VERSION",
30
+ # Type aliases
31
+ "PositionMode",
32
+ "UnitType",
33
+ "SymbolStyle",
34
+ # GUI classes
35
+ "Position",
36
+ "StatStyling",
37
+ "StatPositioning",
38
+ # Core classes
39
+ "DataRef",
40
+ "EffectSize",
41
+ "StatMethod",
42
+ "StatResult",
43
+ "StatDisplay",
44
+ "Analysis",
45
+ "Stats",
46
+ ]
47
+
48
+ # EOF