scitex 2.8.1__py3-none-any.whl → 2.10.2__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.2.dist-info}/METADATA +368 -183
  409. {scitex-2.8.1.dist-info → scitex-2.10.2.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.2.dist-info}/WHEEL +0 -0
  414. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/entry_points.txt +0 -0
  415. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,522 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-12-21 13:43:59 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/dev/plt/mpl/get_signatures_details.py
5
+
6
+
7
+ """Extract signatures with *args/**kwargs flattened from matplotlib plotting functions."""
8
+
9
+ import inspect
10
+ import json
11
+ import re
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ import matplotlib.pyplot as plt
16
+ import yaml
17
+
18
+ import scitex as stx
19
+
20
+
21
+ def parse_parameter_types(docstring: str | None) -> dict[str, str]:
22
+ """Extract parameter types from NumPy-style docstring Parameters section."""
23
+ if not docstring:
24
+ return {}
25
+
26
+ types = {}
27
+
28
+ # Find Parameters section
29
+ params_match = re.search(
30
+ r'Parameters\s*[-]+\s*(.*?)(?:\n\s*Returns|\n\s*See Also|\n\s*Notes|\n\s*Examples|\n\s*Other Parameters|\Z)',
31
+ docstring,
32
+ re.DOTALL
33
+ )
34
+ if not params_match:
35
+ return {}
36
+
37
+ params_text = params_match.group(1)
38
+
39
+ # Parse lines like "x, y : array-like or float" or "fmt : str, optional"
40
+ for match in re.finditer(r'^(\w+(?:\s*,\s*\w+)*)\s*:\s*(.+?)(?=\n\s*\n|\n\w+\s*:|\Z)', params_text, re.MULTILINE | re.DOTALL):
41
+ names_str = match.group(1)
42
+ type_str = match.group(2).split('\n')[0].strip() # First line only
43
+
44
+ # Clean up type string
45
+ type_str = re.sub(r',?\s*optional\s*$', '', type_str).strip()
46
+ type_str = re.sub(r',?\s*default[^,]*$', '', type_str, flags=re.IGNORECASE).strip()
47
+
48
+ # Handle multiple names like "x, y"
49
+ for name in re.split(r'\s*,\s*', names_str):
50
+ name = name.strip()
51
+ if name:
52
+ types[name.lower()] = type_str
53
+
54
+ return types
55
+
56
+
57
+ def parse_args_pattern(args_str: str, param_types: dict[str, str]) -> list[dict[str, Any]]:
58
+ """Parse args pattern like '[x], y, [fmt]' into list of arg dicts."""
59
+ if not args_str:
60
+ return []
61
+
62
+ args = []
63
+ # Split by comma, handling brackets
64
+ parts = re.split(r',\s*', args_str)
65
+
66
+ for part in parts:
67
+ part = part.strip()
68
+ if not part or part == '/': # Skip empty or positional-only marker
69
+ continue
70
+
71
+ # Check if optional (wrapped in [])
72
+ optional = part.startswith('[') and part.endswith(']')
73
+ if optional:
74
+ name = part[1:-1].strip()
75
+ else:
76
+ # Handle cases like "[X, Y,] Z" where Z is required
77
+ name = part.strip('[]').strip()
78
+
79
+ if name and name not in ('...', '*'):
80
+ # Look up type from parsed parameters
81
+ type_str = param_types.get(name.lower())
82
+ args.append({
83
+ "name": name,
84
+ "type": type_str,
85
+ "optional": optional,
86
+ })
87
+
88
+ return args
89
+
90
+
91
+ # Manual *args patterns for functions without parseable call signatures
92
+ MANUAL_ARGS_PATTERNS = {
93
+ "fill": "[x], y, [color]",
94
+ "stackplot": "x, *ys",
95
+ "legend": "[handles], [labels]",
96
+ "stem": "[locs], heads",
97
+ "tricontour": "[triangulation], x, y, z, [levels]",
98
+ "tricontourf": "[triangulation], x, y, z, [levels]",
99
+ "triplot": "[triangulation], x, y, [triangles]",
100
+ "loglog": "[x], y, [fmt]",
101
+ "semilogx": "[x], y, [fmt]",
102
+ "semilogy": "[x], y, [fmt]",
103
+ "barbs": "[X], [Y], U, V, [C]",
104
+ "quiver": "[X], [Y], U, V, [C]",
105
+ "pcolor": "[X], [Y], C",
106
+ "pcolormesh": "[X], [Y], C",
107
+ "pcolorfast": "[X], [Y], C",
108
+ "acorr": "x",
109
+ "xcorr": "x, y",
110
+ }
111
+
112
+
113
+ def extract_args_from_docstring(docstring: str | None, func_name: str = "") -> list[dict[str, Any]]:
114
+ """Extract *args as flattened list from docstring call signature."""
115
+ if not docstring:
116
+ return []
117
+
118
+ # First, parse parameter types
119
+ param_types = parse_parameter_types(docstring)
120
+
121
+ # Check for manual pattern first
122
+ if func_name in MANUAL_ARGS_PATTERNS:
123
+ return parse_args_pattern(MANUAL_ARGS_PATTERNS[func_name], param_types)
124
+
125
+ # Look for "Call signature:" patterns
126
+ patterns = [
127
+ r'Call signatures?::\s*\n\s*(.*?)(?:\n\n|\n[A-Z])',
128
+ r'^\s*(\w+\([^)]+\))\s*$',
129
+ ]
130
+
131
+ for pattern in patterns:
132
+ match = re.search(pattern, docstring, re.MULTILINE | re.DOTALL)
133
+ if match:
134
+ sig_text = match.group(1).strip()
135
+ # Extract first signature line
136
+ first_line = sig_text.split('\n')[0].strip()
137
+ # Parse the args from signature like "plot([x], y, [fmt], *, ...)"
138
+ inner_match = re.search(r'\(([^*]+?)(?:,\s*\*|,\s*data|\))', first_line)
139
+ if inner_match:
140
+ args_str = inner_match.group(1).strip().rstrip(',')
141
+ return parse_args_pattern(args_str, param_types)
142
+ return []
143
+
144
+ def get_setter_type(obj, prop_name: str) -> str | None:
145
+ """Get type from set_* method docstring."""
146
+ setter_name = f"set_{prop_name}"
147
+ if not hasattr(obj, setter_name):
148
+ return None
149
+
150
+ method = getattr(obj, setter_name)
151
+ if not method.__doc__:
152
+ return None
153
+
154
+ # Parse Parameters section
155
+ match = re.search(
156
+ r'Parameters\s*[-]+\s*\n\s*(\w+)\s*:\s*(.+?)(?:\n\s*\n|\Z)',
157
+ method.__doc__,
158
+ re.DOTALL
159
+ )
160
+ if match:
161
+ type_str = match.group(2).split('\n')[0].strip()
162
+ return type_str
163
+ return None
164
+
165
+
166
+ def build_kwargs_with_types():
167
+ """Build kwargs lists with types from matplotlib classes."""
168
+ from matplotlib.lines import Line2D
169
+ from matplotlib.patches import Patch
170
+ from matplotlib.text import Text
171
+ from matplotlib.artist import Artist
172
+
173
+ # Create instances for introspection
174
+ line = Line2D([0], [0])
175
+ patch = Patch()
176
+ text = Text()
177
+ artist = Artist()
178
+
179
+ def get_type(obj, name):
180
+ return get_setter_type(obj, name)
181
+
182
+ ARTIST_KWARGS = [
183
+ {"name": "agg_filter", "type": get_type(artist, "agg_filter"), "default": None},
184
+ {"name": "alpha", "type": get_type(artist, "alpha"), "default": None},
185
+ {"name": "animated", "type": get_type(artist, "animated"), "default": False},
186
+ {"name": "clip_box", "type": get_type(artist, "clip_box"), "default": None},
187
+ {"name": "clip_on", "type": get_type(artist, "clip_on"), "default": True},
188
+ {"name": "clip_path", "type": get_type(artist, "clip_path"), "default": None},
189
+ {"name": "gid", "type": get_type(artist, "gid"), "default": None},
190
+ {"name": "label", "type": get_type(artist, "label"), "default": ""},
191
+ {"name": "path_effects", "type": get_type(artist, "path_effects"), "default": None},
192
+ {"name": "picker", "type": get_type(artist, "picker"), "default": None},
193
+ {"name": "rasterized", "type": get_type(artist, "rasterized"), "default": None},
194
+ {"name": "sketch_params", "type": get_type(artist, "sketch_params"), "default": None},
195
+ {"name": "snap", "type": get_type(artist, "snap"), "default": None},
196
+ {"name": "transform", "type": get_type(artist, "transform"), "default": None},
197
+ {"name": "url", "type": get_type(artist, "url"), "default": None},
198
+ {"name": "visible", "type": get_type(artist, "visible"), "default": True},
199
+ {"name": "zorder", "type": get_type(artist, "zorder"), "default": None},
200
+ ]
201
+
202
+ LINE2D_KWARGS = [
203
+ {"name": "color", "type": get_type(line, "color"), "default": None},
204
+ {"name": "linestyle", "type": get_type(line, "linestyle"), "default": "-"},
205
+ {"name": "linewidth", "type": get_type(line, "linewidth"), "default": None},
206
+ {"name": "marker", "type": get_type(line, "marker"), "default": ""},
207
+ {"name": "markeredgecolor", "type": get_type(line, "markeredgecolor"), "default": None},
208
+ {"name": "markeredgewidth", "type": get_type(line, "markeredgewidth"), "default": None},
209
+ {"name": "markerfacecolor", "type": get_type(line, "markerfacecolor"), "default": None},
210
+ {"name": "markersize", "type": get_type(line, "markersize"), "default": None},
211
+ {"name": "antialiased", "type": get_type(line, "antialiased"), "default": True},
212
+ {"name": "dash_capstyle", "type": get_type(line, "dash_capstyle"), "default": "butt"},
213
+ {"name": "dash_joinstyle", "type": get_type(line, "dash_joinstyle"), "default": "round"},
214
+ {"name": "solid_capstyle", "type": get_type(line, "solid_capstyle"), "default": "projecting"},
215
+ {"name": "solid_joinstyle", "type": get_type(line, "solid_joinstyle"), "default": "round"},
216
+ {"name": "drawstyle", "type": get_type(line, "drawstyle"), "default": "default"},
217
+ {"name": "fillstyle", "type": get_type(line, "fillstyle"), "default": "full"},
218
+ ]
219
+
220
+ PATCH_KWARGS = [
221
+ {"name": "color", "type": get_type(patch, "color"), "default": None},
222
+ {"name": "edgecolor", "type": get_type(patch, "edgecolor"), "default": None},
223
+ {"name": "facecolor", "type": get_type(patch, "facecolor"), "default": None},
224
+ {"name": "fill", "type": get_type(patch, "fill"), "default": True},
225
+ {"name": "hatch", "type": get_type(patch, "hatch"), "default": None},
226
+ {"name": "linestyle", "type": get_type(patch, "linestyle"), "default": "-"},
227
+ {"name": "linewidth", "type": get_type(patch, "linewidth"), "default": None},
228
+ {"name": "antialiased", "type": get_type(patch, "antialiased"), "default": None},
229
+ {"name": "capstyle", "type": get_type(patch, "capstyle"), "default": "butt"},
230
+ {"name": "joinstyle", "type": get_type(patch, "joinstyle"), "default": "miter"},
231
+ ]
232
+
233
+ TEXT_KWARGS = [
234
+ {"name": "color", "type": get_type(text, "color"), "default": "black"},
235
+ {"name": "fontfamily", "type": get_type(text, "fontfamily"), "default": None},
236
+ {"name": "fontsize", "type": get_type(text, "fontsize"), "default": None},
237
+ {"name": "fontstretch", "type": get_type(text, "fontstretch"), "default": None},
238
+ {"name": "fontstyle", "type": get_type(text, "fontstyle"), "default": "normal"},
239
+ {"name": "fontvariant", "type": get_type(text, "fontvariant"), "default": "normal"},
240
+ {"name": "fontweight", "type": get_type(text, "fontweight"), "default": "normal"},
241
+ {"name": "horizontalalignment", "type": get_type(text, "horizontalalignment"), "default": "center"},
242
+ {"name": "verticalalignment", "type": get_type(text, "verticalalignment"), "default": "center"},
243
+ {"name": "rotation", "type": get_type(text, "rotation"), "default": None},
244
+ {"name": "linespacing", "type": get_type(text, "linespacing"), "default": None},
245
+ {"name": "multialignment", "type": get_type(text, "multialignment"), "default": None},
246
+ {"name": "wrap", "type": get_type(text, "wrap"), "default": False},
247
+ ]
248
+
249
+ return ARTIST_KWARGS, LINE2D_KWARGS, PATCH_KWARGS, TEXT_KWARGS
250
+
251
+
252
+ # Build kwargs with types at module load
253
+ ARTIST_KWARGS, LINE2D_KWARGS, PATCH_KWARGS, TEXT_KWARGS = build_kwargs_with_types()
254
+
255
+ # Mapping of functions to their **kwargs type
256
+ KWARGS_MAPPING = {
257
+ "plot": LINE2D_KWARGS + ARTIST_KWARGS,
258
+ "scatter": ARTIST_KWARGS,
259
+ "bar": PATCH_KWARGS + ARTIST_KWARGS,
260
+ "barh": PATCH_KWARGS + ARTIST_KWARGS,
261
+ "fill": PATCH_KWARGS + ARTIST_KWARGS,
262
+ "fill_between": PATCH_KWARGS + ARTIST_KWARGS,
263
+ "fill_betweenx": PATCH_KWARGS + ARTIST_KWARGS,
264
+ "step": LINE2D_KWARGS + ARTIST_KWARGS,
265
+ "errorbar": LINE2D_KWARGS + ARTIST_KWARGS,
266
+ "hist": PATCH_KWARGS + ARTIST_KWARGS,
267
+ "hist2d": ARTIST_KWARGS,
268
+ "imshow": ARTIST_KWARGS,
269
+ "pcolor": ARTIST_KWARGS,
270
+ "pcolormesh": ARTIST_KWARGS,
271
+ "pcolorfast": ARTIST_KWARGS,
272
+ "contour": ARTIST_KWARGS,
273
+ "contourf": ARTIST_KWARGS,
274
+ "hexbin": ARTIST_KWARGS,
275
+ "quiver": ARTIST_KWARGS,
276
+ "barbs": ARTIST_KWARGS,
277
+ "specgram": ARTIST_KWARGS,
278
+ "psd": LINE2D_KWARGS + ARTIST_KWARGS,
279
+ "csd": LINE2D_KWARGS + ARTIST_KWARGS,
280
+ "cohere": LINE2D_KWARGS + ARTIST_KWARGS,
281
+ "acorr": LINE2D_KWARGS + ARTIST_KWARGS,
282
+ "xcorr": LINE2D_KWARGS + ARTIST_KWARGS,
283
+ "angle_spectrum": LINE2D_KWARGS + ARTIST_KWARGS,
284
+ "magnitude_spectrum": LINE2D_KWARGS + ARTIST_KWARGS,
285
+ "phase_spectrum": LINE2D_KWARGS + ARTIST_KWARGS,
286
+ "stackplot": PATCH_KWARGS + ARTIST_KWARGS,
287
+ "stairs": PATCH_KWARGS + ARTIST_KWARGS,
288
+ "eventplot": ARTIST_KWARGS,
289
+ "broken_barh": PATCH_KWARGS + ARTIST_KWARGS,
290
+ "loglog": LINE2D_KWARGS + ARTIST_KWARGS,
291
+ "semilogx": LINE2D_KWARGS + ARTIST_KWARGS,
292
+ "semilogy": LINE2D_KWARGS + ARTIST_KWARGS,
293
+ "annotate": TEXT_KWARGS + ARTIST_KWARGS,
294
+ "text": TEXT_KWARGS + ARTIST_KWARGS,
295
+ "arrow": PATCH_KWARGS + ARTIST_KWARGS,
296
+ "axhline": LINE2D_KWARGS + ARTIST_KWARGS,
297
+ "axvline": LINE2D_KWARGS + ARTIST_KWARGS,
298
+ "hlines": ARTIST_KWARGS,
299
+ "vlines": ARTIST_KWARGS,
300
+ "axhspan": PATCH_KWARGS + ARTIST_KWARGS,
301
+ "axvspan": PATCH_KWARGS + ARTIST_KWARGS,
302
+ "axline": LINE2D_KWARGS + ARTIST_KWARGS,
303
+ "legend": ARTIST_KWARGS,
304
+ "grid": LINE2D_KWARGS + ARTIST_KWARGS,
305
+ "table": ARTIST_KWARGS,
306
+ "clabel": TEXT_KWARGS + ARTIST_KWARGS,
307
+ "bar_label": TEXT_KWARGS + ARTIST_KWARGS,
308
+ "quiverkey": ARTIST_KWARGS,
309
+ "ecdf": LINE2D_KWARGS + ARTIST_KWARGS,
310
+ "tricontour": ARTIST_KWARGS,
311
+ "tricontourf": ARTIST_KWARGS,
312
+ "tripcolor": ARTIST_KWARGS,
313
+ "triplot": LINE2D_KWARGS + ARTIST_KWARGS,
314
+ "matshow": ARTIST_KWARGS,
315
+ "spy": ARTIST_KWARGS + LINE2D_KWARGS,
316
+ }
317
+
318
+
319
+ def get_typehint_str(annotation) -> str | None:
320
+ """Convert annotation to string representation."""
321
+ if annotation is inspect.Parameter.empty:
322
+ return None
323
+ if hasattr(annotation, "__name__"):
324
+ return annotation.__name__
325
+ return str(annotation)
326
+
327
+
328
+ def get_default_value(default) -> Any:
329
+ """Convert default value to serializable form."""
330
+ if default is inspect.Parameter.empty:
331
+ return None
332
+ if callable(default):
333
+ return f"<{type(default).__name__}>"
334
+ if isinstance(default, type):
335
+ return f"<class {default.__name__}>"
336
+ try:
337
+ json.dumps(default)
338
+ return default
339
+ except (TypeError, ValueError):
340
+ return repr(default)
341
+
342
+
343
+ def inspect_function_flattened(func, func_name: str) -> dict[str, list[dict[str, Any]]]:
344
+ """Inspect function and flatten *args/**kwargs into args/kwargs structure."""
345
+ try:
346
+ sig = inspect.signature(func)
347
+ except (ValueError, TypeError):
348
+ return {"error": "Cannot inspect signature"}
349
+
350
+ # Parse parameter types from docstring
351
+ param_types = parse_parameter_types(func.__doc__)
352
+
353
+ args = []
354
+ kwargs = []
355
+ has_var_positional = False
356
+ has_var_keyword = False
357
+
358
+ for name, param in sig.parameters.items():
359
+ if name == "self":
360
+ continue
361
+
362
+ if param.kind == inspect.Parameter.VAR_POSITIONAL:
363
+ has_var_positional = True
364
+ elif param.kind == inspect.Parameter.VAR_KEYWORD:
365
+ has_var_keyword = True
366
+ else:
367
+ # Try annotation first, then docstring
368
+ typehint = get_typehint_str(param.annotation)
369
+ if not typehint:
370
+ typehint = param_types.get(name.lower())
371
+
372
+ info = {
373
+ "name": name,
374
+ "type": typehint,
375
+ }
376
+
377
+ if param.default is not inspect.Parameter.empty:
378
+ info["default"] = get_default_value(param.default)
379
+ kwargs.append(info)
380
+ else:
381
+ args.append(info)
382
+
383
+ # Try to extract *args info from docstring and flatten
384
+ if has_var_positional:
385
+ docstring_args = extract_args_from_docstring(func.__doc__, func_name)
386
+ if docstring_args:
387
+ # Insert flattened args at the beginning
388
+ for i, arg in enumerate(docstring_args):
389
+ args.insert(i, arg)
390
+ else:
391
+ # No docstring info, keep generic *args
392
+ args.insert(0, {"name": "*args", "type": None})
393
+
394
+ # Expand **kwargs based on function type
395
+ if has_var_keyword and func_name in KWARGS_MAPPING:
396
+ expanded_kwargs = KWARGS_MAPPING[func_name]
397
+ existing_names = {p["name"] for p in args + kwargs}
398
+ for kwarg in expanded_kwargs:
399
+ if kwarg["name"] not in existing_names:
400
+ kwargs.append(
401
+ {
402
+ "name": kwarg["name"],
403
+ "type": kwarg["type"],
404
+ "default": kwarg["default"],
405
+ }
406
+ )
407
+ elif has_var_keyword:
408
+ kwargs.append(
409
+ {
410
+ "name": "**kwargs",
411
+ "type": None,
412
+ }
413
+ )
414
+
415
+ return {"args": args, "kwargs": kwargs}
416
+
417
+
418
+ def inspect_mpl_plotting_functions_flattened(
419
+ yaml_path: str | Path | None = None,
420
+ ) -> dict[str, dict]:
421
+ """Inspect matplotlib plotting functions with flattened *args/**kwargs."""
422
+ if yaml_path is None:
423
+ yaml_path = "./data/dev/plt/mpl/PLOTTING_FUNCTIONS.yaml"
424
+
425
+ with open(yaml_path) as f:
426
+ categories = yaml.safe_load(f)
427
+
428
+ _, ax = plt.subplots()
429
+ plt.close()
430
+
431
+ results = {}
432
+
433
+ for category, functions in categories.items():
434
+ if not isinstance(functions, list):
435
+ continue
436
+
437
+ results[category] = {}
438
+
439
+ for func_name in functions:
440
+ if isinstance(func_name, str):
441
+ func_name = func_name.split("#")[0].strip()
442
+
443
+ if hasattr(ax, func_name):
444
+ func = getattr(ax, func_name)
445
+ results[category][func_name] = inspect_function_flattened(
446
+ func, func_name
447
+ )
448
+ else:
449
+ results[category][func_name] = {
450
+ "error": "Function not found"
451
+ }
452
+
453
+ return results
454
+
455
+
456
+ def format_signature(func_name: str, info: dict) -> str:
457
+ """Format function signature as a readable string."""
458
+ if "error" in info:
459
+ return f"{func_name}(): {info['error']}"
460
+
461
+ parts = []
462
+
463
+ # Process args
464
+ for p in info.get("args", []):
465
+ name = p["name"]
466
+ ptype = p.get("type")
467
+ if ptype == "*args":
468
+ parts.append(name)
469
+ else:
470
+ parts.append(name)
471
+
472
+ # Process kwargs
473
+ for p in info.get("kwargs", []):
474
+ name = p["name"]
475
+ ptype = p.get("type")
476
+ if ptype == "**kwargs":
477
+ parts.append(name)
478
+ elif "default" in p:
479
+ default = p["default"]
480
+ if isinstance(default, str) and not default.startswith("<"):
481
+ parts.append(f'{name}="{default}"')
482
+ else:
483
+ parts.append(f"{name}={default}")
484
+ else:
485
+ parts.append(name)
486
+
487
+ return f"{func_name}({', '.join(parts)})"
488
+
489
+
490
+ @stx.session
491
+ def main(
492
+ CONFIG=stx.INJECTED,
493
+ plt=stx.INJECTED,
494
+ COLORS=stx.INJECTED,
495
+ rng_manager=stx.INJECTED,
496
+ logger=stx.INJECTED,
497
+ ):
498
+ """Extract signatures with flattened *args/**kwargs."""
499
+ results = inspect_mpl_plotting_functions_flattened()
500
+
501
+ stx.io.save(
502
+ results,
503
+ "./PLOTTING_SIGNATURES_DETAILED.yaml",
504
+ symlink_to="./data/dev/plt/mpl",
505
+ )
506
+
507
+ print("MATPLOTLIB PLOTTING FUNCTION SIGNATURES (DETAILED)")
508
+ print("=" * 60)
509
+
510
+ for category, functions in results.items():
511
+ print(f"\n## {category.upper()}")
512
+ print("-" * 40)
513
+ for func_name, info in functions.items():
514
+ print(f" {format_signature(func_name, info)}")
515
+
516
+ return 0
517
+
518
+
519
+ if __name__ == "__main__":
520
+ main()
521
+
522
+ # EOF
scitex/dict/_pop_keys.py CHANGED
@@ -1,11 +1,7 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # Timestamp: "2025-11-10 22:40:16 (ywatanabe)"
4
3
 
5
4
 
6
- import numpy as np
7
-
8
-
9
5
  def pop_keys(keys_list, keys_to_pop):
10
6
  """Remove specified keys from a list of keys.
11
7
 
@@ -28,9 +24,7 @@ def pop_keys(keys_list, keys_to_pop):
28
24
  >>> pop_keys(keys_list, keys_to_pop)
29
25
  ['a', 'c', 'e', 'bde']
30
26
  """
31
- indi_to_remain = [k not in keys_to_pop for k in keys_list]
32
- keys_remainded_list = list(np.array(keys_list)[list(indi_to_remain)])
33
- return keys_remainded_list
27
+ return [k for k in keys_list if k not in keys_to_pop]
34
28
 
35
29
 
36
30
  # EOF
scitex/dsp/__init__.py CHANGED
@@ -3,20 +3,23 @@
3
3
 
4
4
  import warnings
5
5
 
6
+ # Import example, params, norm, reference, filt, and add_noise modules as submodules
7
+ from . import add_noise, example, filt, norm, params, reference
8
+
6
9
  # Core imports that should always work
7
10
  from ._crop import crop
8
11
  from ._demo_sig import demo_sig
9
12
  from ._detect_ripples import (
10
- detect_ripples,
11
- _preprocess,
12
- _find_events,
13
- _drop_ripples_at_edges,
14
13
  _calc_relative_peak_position,
14
+ _drop_ripples_at_edges,
15
+ _find_events,
16
+ _preprocess,
15
17
  _sort_columns,
18
+ detect_ripples,
16
19
  )
17
20
  from ._ensure_3d import ensure_3d
18
21
  from ._hilbert import hilbert
19
- from ._modulation_index import modulation_index, _reshape
22
+ from ._modulation_index import _reshape, modulation_index
20
23
  from ._pac import pac
21
24
  from ._psd import band_powers, psd
22
25
  from ._resample import resample
@@ -24,16 +27,12 @@ from ._time import time
24
27
  from ._transform import to_segments, to_sktime_df
25
28
  from ._wavelet import wavelet
26
29
 
27
- # Import example and params modules as submodules
28
- from . import example
29
- from . import params
30
-
31
30
  # Try to import audio-related functions that require PortAudio
32
31
  try:
33
32
  from ._listen import list_and_select_device
34
33
 
35
34
  _audio_available = True
36
- except (ImportError, OSError) as e:
35
+ except (ImportError, OSError):
37
36
  warnings.warn(
38
37
  "Audio functionality unavailable: PortAudio library not found. "
39
38
  "Install PortAudio to use audio features (e.g., sudo apt-get install portaudio19-dev)",
@@ -62,17 +61,23 @@ __all__ = [
62
61
  "_preprocess",
63
62
  "_reshape",
64
63
  "_sort_columns",
64
+ "add_noise",
65
65
  "band_powers",
66
66
  "crop",
67
67
  "demo_sig",
68
68
  "detect_ripples",
69
69
  "ensure_3d",
70
+ "example",
71
+ "filt",
70
72
  "get_eeg_pos",
71
73
  "hilbert",
72
74
  "list_and_select_device",
73
75
  "modulation_index",
76
+ "norm",
74
77
  "pac",
78
+ "params",
75
79
  "psd",
80
+ "reference",
76
81
  "resample",
77
82
  "time",
78
83
  "to_segments",
scitex/dsp/add_noise.py CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # Time-stamp: "ywatanabe (2024-11-02 23:09:49)"
4
3
  # File: ./scitex_repo/src/scitex/dsp/add_noise.py
5
4
 
6
5
  import torch
6
+
7
7
  from scitex.decorators import signal_fn
8
8
 
9
9
 
@@ -50,9 +50,11 @@ def pink(x, amp=1.0, dim=-1):
50
50
 
51
51
  @signal_fn
52
52
  def brown(x, amp=1.0, dim=-1):
53
+ from scitex.dsp import norm
54
+
53
55
  noise = _uniform(x.shape, amp=amp)
54
56
  noise = torch.cumsum(noise, dim=dim)
55
- noise = scitex.dsp.norm.minmax(noise, amp=amp, dim=dim)
57
+ noise = norm.minmax(noise, amp=amp, dim=dim)
56
58
  return x + noise.to(x.device)
57
59
 
58
60
 
@@ -60,6 +62,7 @@ if __name__ == "__main__":
60
62
  import sys
61
63
 
62
64
  import matplotlib.pyplot as plt
65
+
63
66
  import scitex
64
67
 
65
68
  # Start