scitex 2.8.1__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 (415) 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/dict/_pop_keys.py +1 -7
  105. scitex/dsp/__init__.py +15 -10
  106. scitex/dsp/add_noise.py +5 -2
  107. scitex/dsp/example.py +35 -22
  108. scitex/dsp/filt.py +8 -3
  109. scitex/dsp/reference.py +3 -2
  110. scitex/dsp/utils/__init__.py +2 -1
  111. scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
  112. scitex/dt/__init__.py +39 -2
  113. scitex/errors.py +82 -521
  114. scitex/fig/__init__.py +4 -4
  115. scitex/fig/editor/edit/panel_loader.py +1 -1
  116. scitex/fig/io/_bundle.py +7 -7
  117. scitex/fts/README.md +262 -0
  118. scitex/fts/TODO.md +66 -0
  119. scitex/fts/__init__.py +90 -0
  120. scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
  121. scitex/fts/_bundle/_FTS.py +657 -0
  122. scitex/fts/_bundle/__init__.py +38 -0
  123. scitex/fts/_bundle/_children.py +216 -0
  124. scitex/fts/_bundle/_conversion/__init__.py +15 -0
  125. scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
  126. scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
  127. scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
  128. scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
  129. scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
  130. scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
  131. scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
  132. scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
  133. scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
  134. scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
  135. scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
  136. scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
  137. scitex/fts/_bundle/_extractors/__init__.py +32 -0
  138. scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
  139. scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
  140. scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
  141. scitex/fts/_bundle/_loader.py +134 -0
  142. scitex/fts/_bundle/_mpl_helpers.py +389 -0
  143. scitex/fts/_bundle/_saver.py +269 -0
  144. scitex/fts/_bundle/_storage.py +200 -0
  145. scitex/fts/_bundle/_utils/__init__.py +55 -0
  146. scitex/fts/_bundle/_utils/_const.py +26 -0
  147. scitex/fts/_bundle/_utils/_errors.py +73 -0
  148. scitex/fts/_bundle/_utils/_generate.py +21 -0
  149. scitex/fts/_bundle/_utils/_types.py +76 -0
  150. scitex/fts/_bundle/_validation.py +434 -0
  151. scitex/fts/_bundle/_zipbundle.py +165 -0
  152. scitex/fts/_fig/__init__.py +22 -0
  153. scitex/fts/_fig/_backend/__init__.py +53 -0
  154. scitex/fts/_fig/_backend/_export.py +165 -0
  155. scitex/fts/_fig/_backend/_parser.py +188 -0
  156. scitex/fts/_fig/_backend/_render.py +538 -0
  157. scitex/fts/_fig/_composite.py +345 -0
  158. scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
  159. scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
  160. scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
  161. scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
  162. scitex/fts/_fig/_dataclasses/__init__.py +47 -0
  163. scitex/fts/_fig/_editor/__init__.py +14 -0
  164. scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
  165. scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
  166. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
  167. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
  168. scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
  169. scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
  170. scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
  171. scitex/fts/_fig/_editor/_defaults.py +300 -0
  172. scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
  173. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
  174. scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
  175. scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
  176. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
  177. scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
  178. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
  179. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
  180. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
  181. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
  182. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
  183. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
  184. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
  185. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
  186. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
  187. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
  188. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
  189. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
  190. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
  191. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
  192. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
  193. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
  194. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
  195. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
  196. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
  197. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
  198. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
  199. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
  200. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
  201. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
  202. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
  203. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
  204. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
  205. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
  206. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
  207. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
  208. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
  209. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
  210. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
  211. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
  212. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
  213. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
  214. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
  215. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
  216. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
  217. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
  218. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
  219. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
  220. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
  221. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
  222. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
  223. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
  224. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
  225. scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
  226. scitex/fts/_fig/_models/_Annotations.py +115 -0
  227. scitex/fts/_fig/_models/_Axes.py +152 -0
  228. scitex/fts/_fig/_models/_Figure.py +138 -0
  229. scitex/fts/_fig/_models/_Guides.py +104 -0
  230. scitex/fts/_fig/_models/_Plot.py +123 -0
  231. scitex/fts/_fig/_models/_Styles.py +245 -0
  232. scitex/fts/_fig/_models/__init__.py +80 -0
  233. scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
  234. scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
  235. scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
  236. scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
  237. scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
  238. scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
  239. scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
  240. scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
  241. scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
  242. scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
  243. scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
  244. scitex/fts/_fig/_utils/__init__.py +129 -0
  245. scitex/fts/_fig/_utils/_auto_layout.py +127 -0
  246. scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
  247. scitex/fts/_fig/_utils/_const_sizes.py +48 -0
  248. scitex/fts/_fig/_utils/_convert_coords.py +77 -0
  249. scitex/fts/_fig/_utils/_get_template.py +178 -0
  250. scitex/fts/_fig/_utils/_normalize.py +73 -0
  251. scitex/fts/_fig/_utils/_plot_layout.py +397 -0
  252. scitex/fts/_fig/_utils/_validate.py +197 -0
  253. scitex/fts/_kinds/__init__.py +45 -0
  254. scitex/fts/_kinds/_figure/__init__.py +19 -0
  255. scitex/fts/_kinds/_figure/_composite.py +345 -0
  256. scitex/fts/_kinds/_plot/__init__.py +25 -0
  257. scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
  258. scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
  259. scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
  260. scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
  261. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
  262. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
  263. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
  264. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
  265. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
  266. scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
  267. scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
  268. scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
  269. scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
  270. scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
  271. scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
  272. scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
  273. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
  274. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
  275. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
  276. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
  277. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
  278. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
  279. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
  280. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
  281. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
  282. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
  283. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
  284. scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
  285. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
  286. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
  287. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
  288. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
  289. scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
  290. scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
  291. scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
  292. scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
  293. scitex/fts/_kinds/_shape/__init__.py +141 -0
  294. scitex/fts/_kinds/_stats/__init__.py +56 -0
  295. scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
  296. scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
  297. scitex/fts/_kinds/_table/__init__.py +72 -0
  298. scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
  299. scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
  300. scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
  301. scitex/fts/_kinds/_table/_latex/_export.py +279 -0
  302. scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
  303. scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
  304. scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
  305. scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
  306. scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
  307. scitex/fts/_kinds/_text/__init__.py +77 -0
  308. scitex/fts/_schemas/data_info.schema.json +75 -0
  309. scitex/fts/_schemas/encoding.schema.json +90 -0
  310. scitex/fts/_schemas/node.schema.json +145 -0
  311. scitex/fts/_schemas/render_manifest.schema.json +62 -0
  312. scitex/fts/_schemas/stats.schema.json +132 -0
  313. scitex/fts/_schemas/theme.schema.json +141 -0
  314. scitex/fts/_stats/__init__.py +48 -0
  315. scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
  316. scitex/fts/_stats/_dataclasses/__init__.py +48 -0
  317. scitex/fts/_tables/__init__.py +65 -0
  318. scitex/fts/_tables/_latex/__init__.py +93 -0
  319. scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
  320. scitex/fts/_tables/_latex/_editor/_app.py +725 -0
  321. scitex/fts/_tables/_latex/_export.py +279 -0
  322. scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
  323. scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
  324. scitex/fts/_tables/_latex/_table_exporter.py +362 -0
  325. scitex/fts/_tables/_latex/_utils.py +369 -0
  326. scitex/fts/_tables/_latex/_validator.py +445 -0
  327. scitex/gen/__init__.py +66 -25
  328. scitex/gen/misc.py +28 -0
  329. scitex/io/__init__.py +47 -32
  330. scitex/io/_load.py +87 -36
  331. scitex/io/_load_modules/__init__.py +10 -7
  332. scitex/io/_load_modules/_pandas.py +6 -1
  333. scitex/io/_save.py +299 -1556
  334. scitex/io/_save_modules/__init__.py +76 -19
  335. scitex/io/_save_modules/_figure_utils.py +90 -0
  336. scitex/io/_save_modules/_image_csv.py +497 -0
  337. scitex/io/_save_modules/_legends.py +91 -0
  338. scitex/io/_save_modules/_pltz_bundle.py +356 -0
  339. scitex/io/_save_modules/_pltz_stx.py +536 -0
  340. scitex/io/_save_modules/_stx_bundle.py +104 -0
  341. scitex/io/_save_modules/_symlink.py +96 -0
  342. scitex/io/_save_modules/_yaml.py +1 -1
  343. scitex/io/_save_modules/_zarr.py +64 -18
  344. scitex/io/bundle/README.md +212 -0
  345. scitex/io/bundle/__init__.py +110 -0
  346. scitex/io/{_bundle.py → bundle/_core.py} +168 -97
  347. scitex/io/bundle/_nested.py +713 -0
  348. scitex/io/bundle/_types.py +74 -0
  349. scitex/io/{_zip_bundle.py → bundle/_zip.py} +93 -45
  350. scitex/io/utils/h5_to_zarr.py +1 -1
  351. scitex/logging/__init__.py +108 -13
  352. scitex/logging/_errors.py +508 -0
  353. scitex/logging/_formatters.py +30 -6
  354. scitex/logging/_warnings.py +261 -0
  355. scitex/plt/__init__.py +4 -1
  356. scitex/plt/_figrecipe.py +236 -0
  357. scitex/plt/_subplots/_AxisWrapper.py +6 -0
  358. scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
  359. scitex/plt/_subplots/_FigWrapper.py +15 -0
  360. scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
  361. scitex/plt/_subplots/_export_as_csv.py +11 -0
  362. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
  363. scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
  364. scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
  365. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
  366. scitex/plt/_subplots/_fonts.py +71 -0
  367. scitex/plt/_subplots/_mm_layout.py +282 -0
  368. scitex/plt/gallery/__init__.py +99 -2
  369. scitex/plt/styles/_plot_postprocess.py +3 -1
  370. scitex/plt/utils/_configure_mpl.py +16 -19
  371. scitex/repro/_RandomStateManager.py +13 -8
  372. scitex/resource/__init__.py +19 -1
  373. scitex/resource/_utils/_get_env_info.py +13 -25
  374. scitex/schema/__init__.py +149 -160
  375. scitex/schema/_encoding.py +273 -0
  376. scitex/schema/_figure_elements.py +406 -0
  377. scitex/schema/_theme.py +360 -0
  378. scitex/schema/_validation.py +0 -98
  379. scitex/scholar/__init__.py +56 -14
  380. scitex/scholar/auth/ScholarAuthManager.py +1 -1
  381. scitex/scholar/auth/__init__.py +11 -2
  382. scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
  383. scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
  384. scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
  385. scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
  386. scitex/scholar/config/ScholarConfig.py +1 -1
  387. scitex/scholar/core/Scholar.py +1 -1
  388. scitex/session/_decorator.py +18 -16
  389. scitex/session/_lifecycle.py +9 -11
  390. scitex/session/template.py +9 -8
  391. scitex/sh/test_sh.py +72 -0
  392. scitex/sh/test_sh_simple.py +61 -0
  393. scitex/stats/__init__.py +221 -97
  394. scitex/stats/_schema.py +21 -22
  395. scitex/stats/descriptive/_circular.py +212 -351
  396. scitex/stats/descriptive/_describe.py +81 -132
  397. scitex/stats/descriptive/_nan.py +205 -433
  398. scitex/stats/descriptive/_real.py +127 -141
  399. scitex/str/_format_plot_text.py +5 -5
  400. scitex/str/_latex.py +26 -84
  401. scitex/str/_latex_fallback.py +53 -47
  402. scitex/web/_search_pubmed.py +5 -4
  403. scitex/writer/tests/test_diff_between.py +451 -0
  404. scitex/writer/tests/test_document_section.py +311 -0
  405. scitex/writer/tests/test_document_workflow.py +393 -0
  406. scitex/writer/tests/test_writer.py +361 -0
  407. scitex/writer/tests/test_writer_integration.py +303 -0
  408. {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
  409. {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/RECORD +412 -97
  410. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
  411. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
  412. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
  413. {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
  414. {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
  415. {scitex-2.8.1.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env python3
2
+ """Millimeter-based layout control for matplotlib figures."""
3
+
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+
7
+ from ._AxesWrapper import AxesWrapper
8
+ from ._AxisWrapper import AxisWrapper
9
+ from ._FigWrapper import FigWrapper
10
+
11
+
12
+ def create_with_mm_control(
13
+ *args,
14
+ track=True,
15
+ sharex=False,
16
+ sharey=False,
17
+ axes_width_mm=None,
18
+ axes_height_mm=None,
19
+ margin_left_mm=None,
20
+ margin_right_mm=None,
21
+ margin_bottom_mm=None,
22
+ margin_top_mm=None,
23
+ space_w_mm=None,
24
+ space_h_mm=None,
25
+ axes_thickness_mm=None,
26
+ tick_length_mm=None,
27
+ tick_thickness_mm=None,
28
+ trace_thickness_mm=None,
29
+ marker_size_mm=None,
30
+ axis_font_size_pt=None,
31
+ tick_font_size_pt=None,
32
+ title_font_size_pt=None,
33
+ legend_font_size_pt=None,
34
+ suptitle_font_size_pt=None,
35
+ label_pad_pt=None,
36
+ tick_pad_pt=None,
37
+ title_pad_pt=None,
38
+ font_family=None,
39
+ n_ticks=None,
40
+ mode=None,
41
+ dpi=None,
42
+ styles=None,
43
+ transparent=None,
44
+ theme=None,
45
+ **kwargs,
46
+ ):
47
+ """Create figure with mm-based control over axes dimensions.
48
+
49
+ Returns
50
+ -------
51
+ tuple
52
+ (FigWrapper, AxisWrapper or AxesWrapper)
53
+ """
54
+ from scitex.plt.utils import apply_style_mm, mm_to_inch
55
+
56
+ # Parse nrows, ncols from args or kwargs
57
+ nrows, ncols = 1, 1
58
+ if len(args) >= 1:
59
+ nrows = args[0]
60
+ elif "nrows" in kwargs:
61
+ nrows = kwargs.pop("nrows")
62
+ if len(args) >= 2:
63
+ ncols = args[1]
64
+ elif "ncols" in kwargs:
65
+ ncols = kwargs.pop("ncols")
66
+
67
+ n_axes = nrows * ncols
68
+
69
+ # Apply mode-specific defaults
70
+ if mode == "display":
71
+ scale_factor = 3.0
72
+ dpi = dpi or 100
73
+ else:
74
+ scale_factor = 1.0
75
+ dpi = dpi or 300
76
+
77
+ # Set defaults with scaling
78
+ if axes_width_mm is None:
79
+ axes_width_mm = 30.0 * scale_factor
80
+ elif mode == "display":
81
+ axes_width_mm = axes_width_mm * scale_factor
82
+
83
+ if axes_height_mm is None:
84
+ axes_height_mm = 21.0 * scale_factor
85
+ elif mode == "display":
86
+ axes_height_mm = axes_height_mm * scale_factor
87
+
88
+ margin_left_mm = (
89
+ margin_left_mm if margin_left_mm is not None else (5.0 * scale_factor)
90
+ )
91
+ margin_right_mm = (
92
+ margin_right_mm if margin_right_mm is not None else (2.0 * scale_factor)
93
+ )
94
+ margin_bottom_mm = (
95
+ margin_bottom_mm if margin_bottom_mm is not None else (5.0 * scale_factor)
96
+ )
97
+ margin_top_mm = margin_top_mm if margin_top_mm is not None else (2.0 * scale_factor)
98
+ space_w_mm = space_w_mm if space_w_mm is not None else (3.0 * scale_factor)
99
+ space_h_mm = space_h_mm if space_h_mm is not None else (3.0 * scale_factor)
100
+
101
+ # Handle list vs scalar for axes dimensions
102
+ if isinstance(axes_width_mm, (list, tuple)):
103
+ ax_widths_mm = list(axes_width_mm)
104
+ if len(ax_widths_mm) != n_axes:
105
+ raise ValueError(
106
+ f"axes_width_mm list length ({len(ax_widths_mm)}) "
107
+ f"must match nrows*ncols ({n_axes})"
108
+ )
109
+ else:
110
+ ax_widths_mm = [axes_width_mm] * n_axes
111
+
112
+ if isinstance(axes_height_mm, (list, tuple)):
113
+ ax_heights_mm = list(axes_height_mm)
114
+ if len(ax_heights_mm) != n_axes:
115
+ raise ValueError(
116
+ f"axes_height_mm list length ({len(ax_heights_mm)}) "
117
+ f"must match nrows*ncols ({n_axes})"
118
+ )
119
+ else:
120
+ ax_heights_mm = [axes_height_mm] * n_axes
121
+
122
+ # Calculate figure size from axes grid
123
+ ax_widths_2d = np.array(ax_widths_mm).reshape(nrows, ncols)
124
+ ax_heights_2d = np.array(ax_heights_mm).reshape(nrows, ncols)
125
+
126
+ max_widths_per_col = ax_widths_2d.max(axis=0)
127
+ max_heights_per_row = ax_heights_2d.max(axis=1)
128
+
129
+ total_width_mm = (
130
+ margin_left_mm
131
+ + max_widths_per_col.sum()
132
+ + (ncols - 1) * space_w_mm
133
+ + margin_right_mm
134
+ )
135
+ total_height_mm = (
136
+ margin_bottom_mm
137
+ + max_heights_per_row.sum()
138
+ + (nrows - 1) * space_h_mm
139
+ + margin_top_mm
140
+ )
141
+
142
+ # Create figure
143
+ figsize_inch = (mm_to_inch(total_width_mm), mm_to_inch(total_height_mm))
144
+ if transparent:
145
+ fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi, facecolor="none")
146
+ else:
147
+ fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi)
148
+
149
+ # Store theme on figure
150
+ if theme is not None:
151
+ fig_mpl._scitex_theme = theme
152
+
153
+ # Create axes array and position each one manually
154
+ axes_mpl_list = []
155
+ ax_idx = 0
156
+
157
+ for row in range(nrows):
158
+ for col in range(ncols):
159
+ # Calculate position
160
+ left_mm = margin_left_mm + max_widths_per_col[:col].sum() + col * space_w_mm
161
+ rows_below = nrows - row - 1
162
+ bottom_mm = (
163
+ margin_bottom_mm
164
+ + max_heights_per_row[row + 1 :].sum()
165
+ + rows_below * space_h_mm
166
+ )
167
+
168
+ # Convert to figure coordinates [0-1]
169
+ left = left_mm / total_width_mm
170
+ bottom = bottom_mm / total_height_mm
171
+ width = ax_widths_mm[ax_idx] / total_width_mm
172
+ height = ax_heights_mm[ax_idx] / total_height_mm
173
+
174
+ # Create axes
175
+ ax_mpl = fig_mpl.add_axes([left, bottom, width, height])
176
+ if transparent:
177
+ ax_mpl.patch.set_alpha(0.0)
178
+ axes_mpl_list.append(ax_mpl)
179
+
180
+ # Tag with metadata
181
+ ax_mpl._scitex_metadata = {
182
+ "created_with": "scitex.plt.subplots",
183
+ "mode": mode or "publication",
184
+ "axes_size_mm": (ax_widths_mm[ax_idx], ax_heights_mm[ax_idx]),
185
+ "position_in_grid": (row, col),
186
+ }
187
+ ax_idx += 1
188
+
189
+ # Apply styling to each axes
190
+ suptitle_font_size_pt_value = None
191
+ for i, ax_mpl in enumerate(axes_mpl_list):
192
+ # Determine which style dict to use
193
+ if styles is not None:
194
+ if isinstance(styles, list):
195
+ if len(styles) != n_axes:
196
+ raise ValueError(
197
+ f"styles list length ({len(styles)}) "
198
+ f"must match nrows*ncols ({n_axes})"
199
+ )
200
+ style_dict = styles[i]
201
+ else:
202
+ style_dict = styles
203
+ else:
204
+ # Build style dict from individual parameters
205
+ style_dict = {}
206
+ if axes_thickness_mm is not None:
207
+ style_dict["axis_thickness_mm"] = axes_thickness_mm
208
+ if tick_length_mm is not None:
209
+ style_dict["tick_length_mm"] = tick_length_mm
210
+ if tick_thickness_mm is not None:
211
+ style_dict["tick_thickness_mm"] = tick_thickness_mm
212
+ if trace_thickness_mm is not None:
213
+ style_dict["trace_thickness_mm"] = trace_thickness_mm
214
+ if marker_size_mm is not None:
215
+ style_dict["marker_size_mm"] = marker_size_mm
216
+ if axis_font_size_pt is not None:
217
+ style_dict["axis_font_size_pt"] = axis_font_size_pt
218
+ if tick_font_size_pt is not None:
219
+ style_dict["tick_font_size_pt"] = tick_font_size_pt
220
+ if title_font_size_pt is not None:
221
+ style_dict["title_font_size_pt"] = title_font_size_pt
222
+ if legend_font_size_pt is not None:
223
+ style_dict["legend_font_size_pt"] = legend_font_size_pt
224
+ if suptitle_font_size_pt is not None:
225
+ style_dict["suptitle_font_size_pt"] = suptitle_font_size_pt
226
+ if label_pad_pt is not None:
227
+ style_dict["label_pad_pt"] = label_pad_pt
228
+ if tick_pad_pt is not None:
229
+ style_dict["tick_pad_pt"] = tick_pad_pt
230
+ if title_pad_pt is not None:
231
+ style_dict["title_pad_pt"] = title_pad_pt
232
+ if font_family is not None:
233
+ style_dict["font_family"] = font_family
234
+ if n_ticks is not None:
235
+ style_dict["n_ticks"] = n_ticks
236
+
237
+ # Always add theme to style_dict
238
+ if theme is not None:
239
+ style_dict["theme"] = theme
240
+
241
+ # Extract suptitle font size if available
242
+ if "suptitle_font_size_pt" in style_dict:
243
+ suptitle_font_size_pt_value = style_dict["suptitle_font_size_pt"]
244
+
245
+ # Apply style if not empty
246
+ if style_dict:
247
+ apply_style_mm(ax_mpl, style_dict)
248
+ ax_mpl._scitex_metadata["style_mm"] = style_dict
249
+
250
+ # Store suptitle font size in figure metadata
251
+ if suptitle_font_size_pt_value is not None:
252
+ fig_mpl._scitex_suptitle_font_size_pt = suptitle_font_size_pt_value
253
+
254
+ # Wrap the figure
255
+ fig_scitex = FigWrapper(fig_mpl)
256
+
257
+ # Reshape axes list
258
+ axes_array_mpl = np.array(axes_mpl_list).reshape(nrows, ncols)
259
+
260
+ # Handle single axis case
261
+ if n_axes == 1:
262
+ ax_mpl_scalar = axes_array_mpl.item()
263
+ axis_scitex = AxisWrapper(fig_scitex, ax_mpl_scalar, track)
264
+ fig_scitex.axes = [axis_scitex]
265
+ ax_mpl_scalar._scitex_wrapper = axis_scitex
266
+ return fig_scitex, axis_scitex
267
+
268
+ # Handle multiple axes case
269
+ axes_flat_scitex_list = []
270
+ for ax_mpl in axes_mpl_list:
271
+ ax_scitex = AxisWrapper(fig_scitex, ax_mpl, track)
272
+ ax_mpl._scitex_wrapper = ax_scitex
273
+ axes_flat_scitex_list.append(ax_scitex)
274
+
275
+ axes_array_scitex = np.array(axes_flat_scitex_list).reshape(nrows, ncols)
276
+ axes_scitex = AxesWrapper(fig_scitex, axes_array_scitex)
277
+ fig_scitex.axes = axes_scitex
278
+
279
+ return fig_scitex, axes_scitex
280
+
281
+
282
+ # EOF
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
- # Timestamp: "2025-12-08 23:30:00 (ywatanabe)"
3
+ # Timestamp: "2025-12-18 (ywatanabe)"
4
4
  # File: /home/ywatanabe/proj/scitex-code/src/scitex/plt/gallery/__init__.py
5
5
 
6
6
  """
@@ -19,11 +19,108 @@ Usage:
19
19
 
20
20
  # List available plots
21
21
  stx.plt.gallery.list()
22
+
23
+ # Get plot spec and data for bundle creation
24
+ spec = stx.plt.gallery.get_plot_spec("line", "plot")
25
+ data = stx.plt.gallery.get_plot_data("line", "plot")
22
26
  """
23
27
 
24
28
  from ._generate import generate
25
29
  from ._registry import CATEGORIES, list_plots
30
+ from ._plots import PLOT_FUNCTIONS
31
+
32
+
33
+ def get_plot_spec(category: str, plot_name: str) -> dict:
34
+ """Get spec dictionary for a gallery plot.
35
+
36
+ Parameters
37
+ ----------
38
+ category : str
39
+ Plot category (e.g., "line", "scatter", "categorical")
40
+ plot_name : str
41
+ Plot name within the category (e.g., "plot", "scatter", "bar")
42
+
43
+ Returns
44
+ -------
45
+ dict
46
+ Spec dictionary for the plot type.
47
+ """
48
+ if category not in CATEGORIES:
49
+ raise ValueError(f"Unknown category: {category}. Available: {list(CATEGORIES.keys())}")
50
+
51
+ if plot_name not in CATEGORIES[category]["plots"]:
52
+ raise ValueError(f"Unknown plot: {plot_name} in category {category}")
53
+
54
+ # Build a minimal spec for this plot type
55
+ return {
56
+ "schema": {"name": "scitex.plt.plot", "version": "1.0.0"},
57
+ "plot_type": plot_name,
58
+ "category": category,
59
+ "axes": {"xlabel": "", "ylabel": ""},
60
+ }
61
+
62
+
63
+ def get_plot_data(category: str, plot_name: str):
64
+ """Get sample data for a gallery plot as DataFrame.
65
+
66
+ Parameters
67
+ ----------
68
+ category : str
69
+ Plot category (e.g., "line", "scatter", "categorical")
70
+ plot_name : str
71
+ Plot name within the category (e.g., "plot", "scatter", "bar")
72
+
73
+ Returns
74
+ -------
75
+ pandas.DataFrame or None
76
+ Sample data for the plot, or None if plot doesn't use CSV data.
77
+ """
78
+ import io
79
+ import tempfile
80
+ from pathlib import Path
81
+
82
+ if category not in CATEGORIES:
83
+ raise ValueError(f"Unknown category: {category}. Available: {list(CATEGORIES.keys())}")
84
+
85
+ if plot_name not in CATEGORIES[category]["plots"]:
86
+ raise ValueError(f"Unknown plot: {plot_name} in category {category}")
87
+
88
+ if plot_name not in PLOT_FUNCTIONS:
89
+ return None
90
+
91
+ try:
92
+ import scitex as stx
93
+ from scitex.plt.styles.presets import SCITEX_STYLE
94
+
95
+ # Create a temporary figure
96
+ style = SCITEX_STYLE.copy()
97
+ style["figsize"] = (4, 3)
98
+ fig, ax = stx.plt.subplots(**style)
99
+
100
+ # Generate plot
101
+ plot_func = PLOT_FUNCTIONS[plot_name]
102
+ fig, ax = plot_func(fig, ax, stx)
103
+
104
+ # Export to CSV and parse
105
+ csv_buffer = io.StringIO()
106
+ ax.export_as_csv(csv_buffer)
107
+ csv_buffer.seek(0)
108
+
109
+ import pandas as pd
110
+ df = pd.read_csv(csv_buffer)
111
+
112
+ # Close figure
113
+ stx.plt.close(fig._fig_mpl if hasattr(fig, "_fig_mpl") else fig)
114
+
115
+ return df
116
+
117
+ except Exception as e:
118
+ # Some plots may not have exportable CSV data
119
+ import warnings
120
+ warnings.warn(f"Could not get data for {category}/{plot_name}: {e}")
121
+ return None
122
+
26
123
 
27
- __all__ = ["generate", "list_plots", "CATEGORIES"]
124
+ __all__ = ["generate", "list_plots", "CATEGORIES", "get_plot_spec", "get_plot_data"]
28
125
 
29
126
  # EOF
@@ -119,7 +119,9 @@ def _apply_tick_locator(ax):
119
119
  try:
120
120
 
121
121
  def is_categorical_axis(axis):
122
- if isinstance(axis.converter, StrCategoryConverter):
122
+ # Use get_converter() for matplotlib 3.10+ compatibility
123
+ converter = getattr(axis, 'get_converter', lambda: axis.converter)()
124
+ if isinstance(converter, StrCategoryConverter):
123
125
  return True
124
126
  if hasattr(axis, "units") and isinstance(axis.units, UnitData):
125
127
  return True
@@ -9,11 +9,14 @@ from typing import Dict
9
9
  from typing import Optional
10
10
  from typing import Tuple
11
11
 
12
+ import logging
12
13
  import matplotlib.pyplot as plt
13
14
  import numpy as np
14
15
  import scitex
15
16
  from scitex.dict import DotDict
16
17
 
18
+ logger = logging.getLogger(__name__)
19
+
17
20
 
18
21
  def configure_mpl(
19
22
  plt,
@@ -343,28 +346,22 @@ def configure_mpl(
343
346
  plt.rcParams.update(mpl_config)
344
347
 
345
348
  if verbose:
346
- print("\n" + "-" * 40)
347
- print("Matplotlib has been configured as follows:\n")
348
- print(f"Figure DPI (Display): {dpi_display} DPI")
349
- print(f"Figure DPI (Save): {dpi_save} DPI")
350
- print(
349
+ colors_str = "\n".join(f" {color_str}: {rgba}" for color_str, rgba in RGBA.items())
350
+ config_msg = (
351
+ f"\n{'-' * 40}\n"
352
+ f"Matplotlib has been configured as follows:\n\n"
353
+ f"Figure DPI (Display): {dpi_display} DPI\n"
354
+ f"Figure DPI (Save): {dpi_save} DPI\n"
351
355
  f"Figure Size (Not the Axis Size): "
352
356
  f"{fig_size_mm[0] * fig_scale:.1f} x "
353
- f"{fig_size_mm[1] * fig_scale:.1f} mm (width x height)"
357
+ f"{fig_size_mm[1] * fig_scale:.1f} mm (width x height)\n"
358
+ f"\nHide Top and Right Axes: {hide_top_right_spines}\n"
359
+ f"Line Width: {line_width}\n"
360
+ f"\nCustom Colors (RGBA):\n"
361
+ f"{colors_str}\n"
362
+ f"{'-' * 40}"
354
363
  )
355
- # print("\nFont Sizes:")
356
- # print(f" Base Size: {base_size:.1f}pt")
357
- # print(f" Title: {title_size:.1f}pt (125% of base, min 10pt)")
358
- # print(f" Axis Labels: {label_size:.1f}pt (100% of base, min 9pt)")
359
- # print(f" Tick Labels: {small_size:.1f}pt (85% of base, min 8pt)")
360
- # print(f" Legend: {small_size:.1f}pt (85% of base, min 8pt)")
361
- print(f"\nHide Top and Right Axes: {hide_top_right_spines}")
362
- print(f"Line Width: {line_width}")
363
- # print(f"Number of Ticks: {n_ticks}")
364
- print(f"\nCustom Colors (RGBA):")
365
- for color_str, rgba in RGBA.items():
366
- print(f" {color_str}: {rgba}")
367
- print("-" * 40)
364
+ logger.info(config_msg)
368
365
 
369
366
  # Store n_ticks for later use
370
367
  plt._n_ticks = n_ticks
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # Timestamp: "2025-12-09 (ywatanabe)"
4
3
  # File: /home/ywatanabe/proj/scitex-code/src/scitex/repro/_RandomStateManager.py
5
4
  # ----------------------------------------
6
5
  from __future__ import annotations
6
+
7
7
  import os
8
8
 
9
9
  __FILE__ = __file__
@@ -21,6 +21,7 @@ Main API:
21
21
 
22
22
  import hashlib
23
23
  import json
24
+ import logging
24
25
  import pickle
25
26
  from contextlib import contextmanager
26
27
  from pathlib import Path
@@ -28,6 +29,8 @@ from typing import Any
28
29
 
29
30
  from scitex.config import get_paths
30
31
 
32
+ logger = logging.getLogger(__name__)
33
+
31
34
  # Global singleton instance
32
35
  _GLOBAL_INSTANCE = None
33
36
 
@@ -62,7 +65,7 @@ class RandomStateManager:
62
65
  self._jax_key = None # Initialize to None, will be set if jax is available
63
66
 
64
67
  if verbose:
65
- print(f"RandomStateManager initialized with seed {seed}")
68
+ logger.info(f"RandomStateManager initialized with seed {seed}")
66
69
 
67
70
  # Auto-fix all available seeds
68
71
  self._auto_fix_seeds(verbose=verbose)
@@ -138,7 +141,7 @@ class RandomStateManager:
138
141
  pass
139
142
 
140
143
  if verbose and fixed_modules:
141
- print(f"Fixed random seeds for: {', '.join(fixed_modules)}")
144
+ logger.info(f"Fixed random seeds for: {', '.join(fixed_modules)}")
142
145
 
143
146
  def get_np_generator(self, name: str):
144
147
  """
@@ -225,7 +228,6 @@ class RandomStateManager:
225
228
  >>> # Next run:
226
229
  >>> rng.verify(data, "train_data") # Verifies match
227
230
  """
228
- import numpy as np
229
231
 
230
232
  # Auto-generate name if needed
231
233
  if name is None:
@@ -249,7 +251,7 @@ class RandomStateManager:
249
251
 
250
252
  # Check cache
251
253
  if cache_file.exists():
252
- with open(cache_file, "r") as f:
254
+ with open(cache_file) as f:
253
255
  cached = json.load(f)
254
256
 
255
257
  matches = cached["hash"] == obj_hash
@@ -315,7 +317,10 @@ class RandomStateManager:
315
317
  if isinstance(obj, jnp.ndarray):
316
318
  obj_np = np.array(obj)
317
319
  return hashlib.sha256(obj_np.tobytes()).hexdigest()[:32]
318
- except ImportError:
320
+ except (ImportError, AttributeError, RuntimeError):
321
+ # ImportError: jax not installed
322
+ # AttributeError: circular import in jax._src.clusters
323
+ # RuntimeError: other jax initialization errors
319
324
  pass
320
325
 
321
326
  # Pandas DataFrame/Series
@@ -504,7 +509,6 @@ class RandomStateManager:
504
509
  >>> rng.clear_cache(["test1", "test2"]) # Clear multiple
505
510
  >>> rng.clear_cache("experiment_*") # Clear pattern
506
511
  """
507
- import glob
508
512
 
509
513
  if not self._cache_dir.exists():
510
514
  return 0
@@ -614,7 +618,6 @@ def main(args):
614
618
  - Reproducible random generation
615
619
  - Verification of reproducibility
616
620
  """
617
- import numpy as np
618
621
 
619
622
  # Create RandomStateManager (already created by session.start)
620
623
  print(f"\n{'=' * 60}")
@@ -650,7 +653,9 @@ def main(args):
650
653
 
651
654
  if __name__ == "__main__":
652
655
  import sys
656
+
653
657
  import matplotlib.pyplot as plt
658
+
654
659
  import scitex as stx
655
660
 
656
661
  args = parse_args()
@@ -2,7 +2,17 @@
2
2
  """Scitex resource module."""
3
3
 
4
4
  from ._get_processor_usages import get_processor_usages
5
- from ._get_specs import get_specs
5
+ from ._get_specs import (
6
+ _cpu_info,
7
+ _disk_info,
8
+ _memory_info,
9
+ _network_info,
10
+ _supple_nvidia_info,
11
+ _supple_os_info,
12
+ _supple_python_info,
13
+ _system_info,
14
+ get_specs,
15
+ )
6
16
  from ._log_processor_usages import log_processor_usages, main
7
17
 
8
18
  __all__ = [
@@ -10,4 +20,12 @@ __all__ = [
10
20
  "get_specs",
11
21
  "log_processor_usages",
12
22
  "main",
23
+ "_cpu_info",
24
+ "_disk_info",
25
+ "_memory_info",
26
+ "_network_info",
27
+ "_supple_nvidia_info",
28
+ "_supple_os_info",
29
+ "_supple_python_info",
30
+ "_system_info",
13
31
  ]