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,445 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/fsb/_tables/_latex/_validator.py
4
+
5
+ """LaTeX validation for error detection and suggestions."""
6
+
7
+ import re
8
+ import subprocess
9
+ import tempfile
10
+ from dataclasses import dataclass, field
11
+ from enum import Enum
12
+ from pathlib import Path
13
+ from typing import List, Optional, Tuple
14
+
15
+
16
+ class ErrorSeverity(Enum):
17
+ """Error severity levels."""
18
+
19
+ ERROR = "error"
20
+ WARNING = "warning"
21
+ INFO = "info"
22
+
23
+
24
+ @dataclass
25
+ class LaTeXError:
26
+ """A LaTeX validation error.
27
+
28
+ Attributes:
29
+ line: Line number (1-indexed)
30
+ column: Column number (1-indexed)
31
+ message: Error description
32
+ severity: Error severity
33
+ code: Error code (e.g., E001, W001)
34
+ suggestion: Fix suggestion
35
+ context: Line content for context
36
+ """
37
+
38
+ line: int
39
+ column: int
40
+ message: str
41
+ severity: ErrorSeverity
42
+ code: str
43
+ suggestion: Optional[str] = None
44
+ context: Optional[str] = None
45
+
46
+
47
+ @dataclass
48
+ class ValidationResult:
49
+ """Result of LaTeX validation.
50
+
51
+ Attributes:
52
+ is_valid: Whether the LaTeX is valid (no errors)
53
+ errors: List of errors
54
+ warnings: List of warnings
55
+ info: List of info messages
56
+ """
57
+
58
+ is_valid: bool = True
59
+ errors: List[LaTeXError] = field(default_factory=list)
60
+ warnings: List[LaTeXError] = field(default_factory=list)
61
+ info: List[LaTeXError] = field(default_factory=list)
62
+
63
+ def add_error(self, error: LaTeXError) -> None:
64
+ """Add an error to the appropriate list."""
65
+ if error.severity == ErrorSeverity.ERROR:
66
+ self.errors.append(error)
67
+ self.is_valid = False
68
+ elif error.severity == ErrorSeverity.WARNING:
69
+ self.warnings.append(error)
70
+ else:
71
+ self.info.append(error)
72
+
73
+ @property
74
+ def all_issues(self) -> List[LaTeXError]:
75
+ """Get all issues sorted by line number."""
76
+ return sorted(
77
+ self.errors + self.warnings + self.info,
78
+ key=lambda e: (e.line, e.column),
79
+ )
80
+
81
+
82
+ def validate_latex(
83
+ latex_code: str,
84
+ level: str = "syntax",
85
+ ) -> ValidationResult:
86
+ """Validate LaTeX code.
87
+
88
+ Args:
89
+ latex_code: LaTeX source code
90
+ level: Validation level ("syntax", "semantic", "compile")
91
+
92
+ Returns:
93
+ ValidationResult with errors and warnings
94
+ """
95
+ result = ValidationResult()
96
+ lines = latex_code.split("\n")
97
+
98
+ # Always do syntax validation
99
+ _validate_syntax(lines, result)
100
+
101
+ # Semantic validation
102
+ if level in ("semantic", "compile"):
103
+ _validate_semantic(lines, result)
104
+
105
+ # Compilation validation (optional, requires pdflatex)
106
+ if level == "compile":
107
+ _validate_compilation(latex_code, result)
108
+
109
+ return result
110
+
111
+
112
+ def _validate_syntax(lines: List[str], result: ValidationResult) -> None:
113
+ """Check for syntax errors.
114
+
115
+ Args:
116
+ lines: Source lines
117
+ result: ValidationResult to populate
118
+ """
119
+ # Track brace balance
120
+ brace_stack = [] # List of (line, col, char)
121
+ env_stack = [] # List of (line, env_name)
122
+
123
+ for line_num, line in enumerate(lines, 1):
124
+ # Skip comments
125
+ line_no_comment = line.split("%")[0] if "%" in line and "\\%" not in line.split("%")[0] else line
126
+
127
+ # Check brace balance
128
+ for col, char in enumerate(line_no_comment, 1):
129
+ if char == "{":
130
+ # Check if escaped
131
+ if col > 1 and line_no_comment[col - 2] == "\\":
132
+ continue
133
+ brace_stack.append((line_num, col, char))
134
+ elif char == "}":
135
+ if col > 1 and line_no_comment[col - 2] == "\\":
136
+ continue
137
+ if brace_stack:
138
+ brace_stack.pop()
139
+ else:
140
+ result.add_error(
141
+ LaTeXError(
142
+ line=line_num,
143
+ column=col,
144
+ message="Unmatched closing brace '}'",
145
+ severity=ErrorSeverity.ERROR,
146
+ code="E001",
147
+ suggestion="Remove the extra '}' or add a matching '{'",
148
+ context=line,
149
+ )
150
+ )
151
+
152
+ # Check environment matching
153
+ begin_match = re.search(r"\\begin\{(\w+)\}", line_no_comment)
154
+ if begin_match:
155
+ env_name = begin_match.group(1)
156
+ env_stack.append((line_num, env_name))
157
+
158
+ end_match = re.search(r"\\end\{(\w+)\}", line_no_comment)
159
+ if end_match:
160
+ env_name = end_match.group(1)
161
+ if env_stack:
162
+ _, expected_env = env_stack[-1]
163
+ if env_name == expected_env:
164
+ env_stack.pop()
165
+ else:
166
+ result.add_error(
167
+ LaTeXError(
168
+ line=line_num,
169
+ column=end_match.start() + 1,
170
+ message=f"Environment mismatch: expected \\end{{{expected_env}}}, got \\end{{{env_name}}}",
171
+ severity=ErrorSeverity.ERROR,
172
+ code="E002",
173
+ suggestion=f"Change to \\end{{{expected_env}}} or fix the \\begin command",
174
+ context=line,
175
+ )
176
+ )
177
+ else:
178
+ result.add_error(
179
+ LaTeXError(
180
+ line=line_num,
181
+ column=end_match.start() + 1,
182
+ message=f"\\end{{{env_name}}} without matching \\begin{{{env_name}}}",
183
+ severity=ErrorSeverity.ERROR,
184
+ code="E003",
185
+ suggestion=f"Add \\begin{{{env_name}}} before this or remove the \\end command",
186
+ context=line,
187
+ )
188
+ )
189
+
190
+ # Check for common typos
191
+ _check_common_typos(line_num, line, result)
192
+
193
+ # Report unclosed braces
194
+ for line_num, col, _ in brace_stack:
195
+ result.add_error(
196
+ LaTeXError(
197
+ line=line_num,
198
+ column=col,
199
+ message="Unclosed brace '{'",
200
+ severity=ErrorSeverity.ERROR,
201
+ code="E004",
202
+ suggestion="Add a matching '}'",
203
+ context=lines[line_num - 1] if line_num <= len(lines) else "",
204
+ )
205
+ )
206
+
207
+ # Report unclosed environments
208
+ for line_num, env_name in env_stack:
209
+ result.add_error(
210
+ LaTeXError(
211
+ line=line_num,
212
+ column=1,
213
+ message=f"Unclosed environment: \\begin{{{env_name}}} without \\end{{{env_name}}}",
214
+ severity=ErrorSeverity.ERROR,
215
+ code="E005",
216
+ suggestion=f"Add \\end{{{env_name}}} at the end",
217
+ context=lines[line_num - 1] if line_num <= len(lines) else "",
218
+ )
219
+ )
220
+
221
+
222
+ def _check_common_typos(line_num: int, line: str, result: ValidationResult) -> None:
223
+ """Check for common LaTeX typos.
224
+
225
+ Args:
226
+ line_num: Line number
227
+ line: Line content
228
+ result: ValidationResult to populate
229
+ """
230
+ typos = [
231
+ (r"\\beign\{", "\\begin{", "W001"),
232
+ (r"\\beigin\{", "\\begin{", "W001"),
233
+ (r"\\ened\{", "\\end{", "W002"),
234
+ (r"\\ceneter", "\\centering", "W003"),
235
+ (r"\\includegraphcis", "\\includegraphics", "W004"),
236
+ (r"\\captoin", "\\caption", "W005"),
237
+ (r"\\lable\{", "\\label{", "W006"),
238
+ (r"\\toperule", "\\toprule", "W007"),
239
+ (r"\\bottomrul", "\\bottomrule", "W008"),
240
+ (r"\\midruel", "\\midrule", "W009"),
241
+ ]
242
+
243
+ for pattern, correct, code in typos:
244
+ match = re.search(pattern, line, re.IGNORECASE)
245
+ if match:
246
+ result.add_error(
247
+ LaTeXError(
248
+ line=line_num,
249
+ column=match.start() + 1,
250
+ message=f"Possible typo: '{match.group()}' should be '{correct}'",
251
+ severity=ErrorSeverity.WARNING,
252
+ code=code,
253
+ suggestion=f"Replace with '{correct}'",
254
+ context=line,
255
+ )
256
+ )
257
+
258
+
259
+ def _validate_semantic(lines: List[str], result: ValidationResult) -> None:
260
+ """Check for semantic issues.
261
+
262
+ Args:
263
+ lines: Source lines
264
+ result: ValidationResult to populate
265
+ """
266
+ labels = set()
267
+ refs = set()
268
+ has_caption = False
269
+ in_float = False
270
+
271
+ for line_num, line in enumerate(lines, 1):
272
+ # Track float environments
273
+ if re.search(r"\\begin\{(figure|table)\}", line):
274
+ in_float = True
275
+ has_caption = False
276
+
277
+ if re.search(r"\\end\{(figure|table)\}", line):
278
+ if in_float and not has_caption:
279
+ result.add_error(
280
+ LaTeXError(
281
+ line=line_num,
282
+ column=1,
283
+ message="Float environment without caption",
284
+ severity=ErrorSeverity.WARNING,
285
+ code="W010",
286
+ suggestion="Add \\caption{...} to the figure/table",
287
+ context=line,
288
+ )
289
+ )
290
+ in_float = False
291
+
292
+ # Track captions
293
+ if "\\caption" in line:
294
+ has_caption = True
295
+
296
+ # Collect labels
297
+ label_match = re.search(r"\\label\{([^}]+)\}", line)
298
+ if label_match:
299
+ label = label_match.group(1)
300
+ if label in labels:
301
+ result.add_error(
302
+ LaTeXError(
303
+ line=line_num,
304
+ column=label_match.start() + 1,
305
+ message=f"Duplicate label: '{label}'",
306
+ severity=ErrorSeverity.WARNING,
307
+ code="W011",
308
+ suggestion="Use a unique label",
309
+ context=line,
310
+ )
311
+ )
312
+ labels.add(label)
313
+
314
+ # Collect refs
315
+ for ref_match in re.finditer(r"\\ref\{([^}]+)\}", line):
316
+ refs.add(ref_match.group(1))
317
+
318
+ # Check for undefined refs (only warning since refs might be in other files)
319
+ # for ref in refs - labels:
320
+ # result.add_error(...)
321
+
322
+
323
+ def _validate_compilation(latex_code: str, result: ValidationResult) -> None:
324
+ """Attempt to compile LaTeX and capture errors.
325
+
326
+ Args:
327
+ latex_code: LaTeX source code
328
+ result: ValidationResult to populate
329
+ """
330
+ # Create a minimal document if needed
331
+ if "\\documentclass" not in latex_code:
332
+ latex_code = _wrap_in_document(latex_code)
333
+
334
+ try:
335
+ with tempfile.TemporaryDirectory() as tmpdir:
336
+ tex_path = Path(tmpdir) / "test.tex"
337
+ tex_path.write_text(latex_code, encoding="utf-8")
338
+
339
+ proc = subprocess.run(
340
+ ["pdflatex", "-interaction=nonstopmode", "-halt-on-error", str(tex_path)],
341
+ cwd=tmpdir,
342
+ capture_output=True,
343
+ text=True,
344
+ timeout=30,
345
+ )
346
+
347
+ if proc.returncode != 0:
348
+ # Parse pdflatex output for errors
349
+ _parse_pdflatex_output(proc.stdout, result)
350
+
351
+ except FileNotFoundError:
352
+ result.add_error(
353
+ LaTeXError(
354
+ line=0,
355
+ column=0,
356
+ message="pdflatex not found - compilation check skipped",
357
+ severity=ErrorSeverity.INFO,
358
+ code="I001",
359
+ suggestion="Install TeX Live or MiKTeX for compilation validation",
360
+ )
361
+ )
362
+ except subprocess.TimeoutExpired:
363
+ result.add_error(
364
+ LaTeXError(
365
+ line=0,
366
+ column=0,
367
+ message="Compilation timed out",
368
+ severity=ErrorSeverity.WARNING,
369
+ code="W012",
370
+ suggestion="Check for infinite loops in macros",
371
+ )
372
+ )
373
+ except Exception as e:
374
+ result.add_error(
375
+ LaTeXError(
376
+ line=0,
377
+ column=0,
378
+ message=f"Compilation error: {str(e)}",
379
+ severity=ErrorSeverity.INFO,
380
+ code="I002",
381
+ )
382
+ )
383
+
384
+
385
+ def _wrap_in_document(content: str) -> str:
386
+ """Wrap content in a minimal LaTeX document.
387
+
388
+ Args:
389
+ content: LaTeX content
390
+
391
+ Returns:
392
+ Complete document string
393
+ """
394
+ return f"""\\documentclass{{article}}
395
+ \\usepackage{{graphicx}}
396
+ \\usepackage{{booktabs}}
397
+ \\usepackage{{amsmath}}
398
+ \\begin{{document}}
399
+ {content}
400
+ \\end{{document}}
401
+ """
402
+
403
+
404
+ def _parse_pdflatex_output(output: str, result: ValidationResult) -> None:
405
+ """Parse pdflatex output for errors.
406
+
407
+ Args:
408
+ output: pdflatex stdout
409
+ result: ValidationResult to populate
410
+ """
411
+ # Look for error lines
412
+ error_pattern = re.compile(r"^! (.+)$", re.MULTILINE)
413
+ line_pattern = re.compile(r"^l\.(\d+) (.*)$", re.MULTILINE)
414
+
415
+ for match in error_pattern.finditer(output):
416
+ error_msg = match.group(1)
417
+
418
+ # Try to find line number
419
+ line_num = 0
420
+ context = ""
421
+ line_match = line_pattern.search(output, match.end())
422
+ if line_match:
423
+ line_num = int(line_match.group(1))
424
+ context = line_match.group(2)
425
+
426
+ result.add_error(
427
+ LaTeXError(
428
+ line=line_num,
429
+ column=1,
430
+ message=error_msg,
431
+ severity=ErrorSeverity.ERROR,
432
+ code="C001",
433
+ context=context,
434
+ )
435
+ )
436
+
437
+
438
+ __all__ = [
439
+ "ErrorSeverity",
440
+ "LaTeXError",
441
+ "ValidationResult",
442
+ "validate_latex",
443
+ ]
444
+
445
+ # EOF
scitex/gen/__init__.py CHANGED
@@ -1,15 +1,32 @@
1
1
  #!/usr/bin/env python3
2
2
  """Scitex gen module."""
3
3
 
4
- from ._DimHandler import DimHandler
5
- from ._TimeStamper import TimeStamper
4
+ # Optional: DimHandler requires torch
5
+ try:
6
+ from ._DimHandler import DimHandler
7
+ except ImportError:
8
+ DimHandler = None
6
9
  from ._alternate_kwarg import alternate_kwarg
7
10
  from ._cache import cache
8
11
  from ._check_host import check_host, is_host, verify_host
9
12
  from ._ci import ci
13
+ from ._deprecated_close import (
14
+ close as _deprecated_close,
15
+ )
16
+ from ._deprecated_close import (
17
+ running2finished as _deprecated_running2finished,
18
+ )
19
+
20
+ # _start.py moved to old/ directory - functionality now in scitex.session
21
+ # BACKWARD COMPATIBILITY: Import deprecated wrappers
22
+ from ._deprecated_start import start as _deprecated_start
10
23
 
11
24
  # _close.py moved to old/ directory - functionality now in scitex.session
12
- from ._embed import embed
25
+ # Optional: _embed requires torch
26
+ try:
27
+ from ._embed import embed
28
+ except ImportError:
29
+ embed = None
13
30
  from ._inspect_module import inspect_module
14
31
  from ._is_ipython import is_ipython, is_script
15
32
  from ._less import less
@@ -23,47 +40,69 @@ from ._mat2py import (
23
40
  public_keys,
24
41
  save_npa,
25
42
  )
26
- from ._norm import clip_perc, to_01, to_nan01, to_nanz, to_z, unbias
43
+
44
+ # Optional: _norm requires torch
45
+ try:
46
+ from ._norm import clip_perc, to_01, to_nan01, to_nanz, to_z, unbias
47
+ except ImportError:
48
+ clip_perc = None
49
+ to_01 = None
50
+ to_nan01 = None
51
+ to_nanz = None
52
+ to_z = None
53
+ unbias = None
27
54
  from ._paste import paste
28
55
  from ._print_config import print_config, print_config_main
29
56
  from ._shell import run_shellcommand, run_shellscript
30
57
  from ._src import src
31
- # _start.py moved to old/ directory - functionality now in scitex.session
32
-
33
- # BACKWARD COMPATIBILITY: Import deprecated wrappers
34
- from ._deprecated_start import start as _deprecated_start
35
- from ._deprecated_close import (
36
- close as _deprecated_close,
37
- running2finished as _deprecated_running2finished,
38
- )
58
+ from ._TimeStamper import TimeStamper
39
59
 
40
60
  # Override the imported functions with deprecated wrappers
41
61
  start = _deprecated_start
42
62
  close = _deprecated_close
43
63
  running2finished = _deprecated_running2finished
44
64
 
65
+ from ._detect_environment import (
66
+ detect_environment,
67
+ get_output_directory,
68
+ is_notebook,
69
+ )
70
+ from ._get_notebook_path import (
71
+ get_notebook_directory,
72
+ get_notebook_name,
73
+ get_notebook_path,
74
+ )
45
75
  from ._symlink import symlink
46
76
  from ._symlog import symlog
47
77
  from ._title2path import title2path
48
78
  from ._title_case import main, title_case
49
79
  from ._to_even import to_even
50
80
  from ._to_odd import to_odd
51
- from ._to_rank import to_rank
81
+
82
+ # Optional: _to_rank requires torch
83
+ try:
84
+ from ._to_rank import to_rank
85
+ except ImportError:
86
+ to_rank = None
52
87
  from ._transpose import transpose
53
- from ._type import ArrayLike, var_info
54
- from ._var_info import ArrayLike, var_info
88
+
89
+ # Optional: _type and _var_info require torch
90
+ try:
91
+ from ._type import ArrayLike, var_info
92
+ except ImportError:
93
+ ArrayLike = None
94
+ var_info = None
95
+
96
+ try:
97
+ from ._var_info import ArrayLike, var_info
98
+ except ImportError:
99
+ pass # Already set to None above
55
100
  from ._wrap import wrap
56
101
  from ._xml2dict import XmlDictConfig, XmlListConfig, xml2dict
57
- from ._detect_environment import (
58
- detect_environment,
59
- get_output_directory,
60
- is_notebook,
61
- )
62
- from ._get_notebook_path import (
63
- get_notebook_path,
64
- get_notebook_name,
65
- get_notebook_directory,
66
- )
102
+ from .misc import float_linspace
103
+
104
+ # Import from misc module
105
+ from .misc import connect_nums
67
106
 
68
107
  __all__ = [
69
108
  "ArrayLike",
@@ -79,8 +118,10 @@ __all__ = [
79
118
  "ci",
80
119
  "clip_perc",
81
120
  "close",
121
+ "connect_nums",
82
122
  "dir2npy",
83
123
  "embed",
124
+ "float_linspace",
84
125
  "inspect_module",
85
126
  "is_host",
86
127
  "is_ipython",
scitex/gen/misc.py CHANGED
@@ -423,6 +423,34 @@ def partial_at(func, index, value):
423
423
  return result
424
424
 
425
425
 
426
+ def connect_nums(nums):
427
+ """Connect multiple numbers/values with hyphens.
428
+
429
+ This function takes an iterable of numbers or values and joins them
430
+ with hyphens to create a single string representation.
431
+
432
+ Parameters
433
+ ----------
434
+ nums : iterable
435
+ An iterable of numbers or values to be connected.
436
+
437
+ Returns
438
+ -------
439
+ str
440
+ A string with the values joined by hyphens.
441
+
442
+ Example
443
+ -------
444
+ >>> connect_nums((0, 0))
445
+ '0-0'
446
+ >>> connect_nums((1, 2, 3))
447
+ '1-2-3'
448
+ >>> connect_nums(('a', 'b'))
449
+ 'a-b'
450
+ """
451
+ return "-".join(str(num) for num in nums)
452
+
453
+
426
454
  # def describe(df, method="mean", round_factor=1, axis=0):
427
455
  # assert method in ["mean_std", "mean_ci", "median_iqr"]
428
456
  # df = pd.DataFrame(df)