scitex 2.7.3__py3-none-any.whl → 2.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (563) hide show
  1. scitex/__init__.py +15 -7
  2. scitex/__version__.py +1 -2
  3. scitex/_install_guide.py +250 -0
  4. scitex/_optional_deps.py +206 -39
  5. scitex/ai/_gen_ai/_Groq.py +2 -4
  6. scitex/ai/_gen_ai/_OpenAI.py +5 -2
  7. scitex/ai/_gen_ai/_Perplexity.py +20 -6
  8. scitex/audio/__init__.py +24 -15
  9. scitex/audio/_cross_process_lock.py +139 -0
  10. scitex/audio/_mcp_handlers.py +256 -0
  11. scitex/audio/_mcp_tool_schemas.py +203 -0
  12. scitex/audio/engines/elevenlabs_engine.py +5 -2
  13. scitex/audio/mcp_server.py +98 -457
  14. scitex/bridge/__init__.py +30 -19
  15. scitex/bridge/_figrecipe.py +245 -0
  16. scitex/bridge/_helpers.py +2 -1
  17. scitex/bridge/_plt_vis.py +23 -10
  18. scitex/bridge/_stats_plt.py +18 -5
  19. scitex/bridge/_stats_vis.py +16 -2
  20. scitex/browser/__init__.py +84 -44
  21. scitex/browser/automation/__init__.py +5 -1
  22. scitex/browser/core/BrowserMixin.py +17 -4
  23. scitex/browser/core/__init__.py +11 -2
  24. scitex/browser/remote/CaptchaHandler.py +1 -1
  25. scitex/browser/remote/ZenRowsAPIClient.py +1 -1
  26. scitex/capture/grid.py +487 -0
  27. scitex/capture/mcp_handlers.py +401 -0
  28. scitex/capture/mcp_tool_defs.py +192 -0
  29. scitex/capture/mcp_tools.py +241 -0
  30. scitex/capture/mcp_utils.py +30 -0
  31. scitex/cli/convert.py +421 -0
  32. scitex/cli/main.py +6 -4
  33. scitex/datetime/__init__.py +46 -0
  34. scitex/datetime/_linspace.py +100 -0
  35. scitex/datetime/_normalize_timestamp.py +306 -0
  36. scitex/db/_delete_duplicates.py +4 -4
  37. scitex/db/_sqlite3/_delete_duplicates.py +11 -2
  38. scitex/dev/plt/__init__.py +61 -62
  39. scitex/dev/plt/demo_plotters/__init__.py +0 -0
  40. scitex/dev/plt/demo_plotters/plot_mpl_axhline.py +28 -0
  41. scitex/dev/plt/demo_plotters/plot_mpl_axhspan.py +28 -0
  42. scitex/dev/plt/demo_plotters/plot_mpl_axvline.py +28 -0
  43. scitex/dev/plt/demo_plotters/plot_mpl_axvspan.py +28 -0
  44. scitex/dev/plt/demo_plotters/plot_mpl_bar.py +29 -0
  45. scitex/dev/plt/demo_plotters/plot_mpl_barh.py +29 -0
  46. scitex/dev/plt/demo_plotters/plot_mpl_boxplot.py +28 -0
  47. scitex/dev/plt/demo_plotters/plot_mpl_contour.py +31 -0
  48. scitex/dev/plt/demo_plotters/plot_mpl_contourf.py +31 -0
  49. scitex/dev/plt/demo_plotters/plot_mpl_errorbar.py +30 -0
  50. scitex/dev/plt/demo_plotters/plot_mpl_eventplot.py +28 -0
  51. scitex/dev/plt/demo_plotters/plot_mpl_fill.py +30 -0
  52. scitex/dev/plt/demo_plotters/plot_mpl_fill_between.py +31 -0
  53. scitex/dev/plt/demo_plotters/plot_mpl_hexbin.py +28 -0
  54. scitex/dev/plt/demo_plotters/plot_mpl_hist.py +28 -0
  55. scitex/dev/plt/demo_plotters/plot_mpl_hist2d.py +28 -0
  56. scitex/dev/plt/demo_plotters/plot_mpl_imshow.py +29 -0
  57. scitex/dev/plt/demo_plotters/plot_mpl_pcolormesh.py +31 -0
  58. scitex/dev/plt/demo_plotters/plot_mpl_pie.py +29 -0
  59. scitex/dev/plt/demo_plotters/plot_mpl_plot.py +29 -0
  60. scitex/dev/plt/demo_plotters/plot_mpl_quiver.py +31 -0
  61. scitex/dev/plt/demo_plotters/plot_mpl_scatter.py +28 -0
  62. scitex/dev/plt/demo_plotters/plot_mpl_stackplot.py +31 -0
  63. scitex/dev/plt/demo_plotters/plot_mpl_stem.py +29 -0
  64. scitex/dev/plt/demo_plotters/plot_mpl_step.py +29 -0
  65. scitex/dev/plt/demo_plotters/plot_mpl_violinplot.py +28 -0
  66. scitex/dev/plt/demo_plotters/plot_sns_barplot.py +29 -0
  67. scitex/dev/plt/demo_plotters/plot_sns_boxplot.py +29 -0
  68. scitex/dev/plt/demo_plotters/plot_sns_heatmap.py +28 -0
  69. scitex/dev/plt/demo_plotters/plot_sns_histplot.py +29 -0
  70. scitex/dev/plt/demo_plotters/plot_sns_kdeplot.py +29 -0
  71. scitex/dev/plt/demo_plotters/plot_sns_lineplot.py +31 -0
  72. scitex/dev/plt/demo_plotters/plot_sns_scatterplot.py +29 -0
  73. scitex/dev/plt/demo_plotters/plot_sns_stripplot.py +29 -0
  74. scitex/dev/plt/demo_plotters/plot_sns_swarmplot.py +29 -0
  75. scitex/dev/plt/demo_plotters/plot_sns_violinplot.py +29 -0
  76. scitex/dev/plt/demo_plotters/plot_stx_bar.py +29 -0
  77. scitex/dev/plt/demo_plotters/plot_stx_barh.py +29 -0
  78. scitex/dev/plt/demo_plotters/plot_stx_box.py +28 -0
  79. scitex/dev/plt/demo_plotters/plot_stx_boxplot.py +28 -0
  80. scitex/dev/plt/demo_plotters/plot_stx_conf_mat.py +28 -0
  81. scitex/dev/plt/demo_plotters/plot_stx_contour.py +31 -0
  82. scitex/dev/plt/demo_plotters/plot_stx_ecdf.py +28 -0
  83. scitex/dev/plt/demo_plotters/plot_stx_errorbar.py +30 -0
  84. scitex/dev/plt/demo_plotters/plot_stx_fill_between.py +31 -0
  85. scitex/dev/plt/demo_plotters/plot_stx_fillv.py +28 -0
  86. scitex/dev/plt/demo_plotters/plot_stx_heatmap.py +28 -0
  87. scitex/dev/plt/demo_plotters/plot_stx_image.py +28 -0
  88. scitex/dev/plt/demo_plotters/plot_stx_imshow.py +28 -0
  89. scitex/dev/plt/demo_plotters/plot_stx_joyplot.py +28 -0
  90. scitex/dev/plt/demo_plotters/plot_stx_kde.py +28 -0
  91. scitex/dev/plt/demo_plotters/plot_stx_line.py +28 -0
  92. scitex/dev/plt/demo_plotters/plot_stx_mean_ci.py +28 -0
  93. scitex/dev/plt/demo_plotters/plot_stx_mean_std.py +28 -0
  94. scitex/dev/plt/demo_plotters/plot_stx_median_iqr.py +28 -0
  95. scitex/dev/plt/demo_plotters/plot_stx_raster.py +28 -0
  96. scitex/dev/plt/demo_plotters/plot_stx_rectangle.py +28 -0
  97. scitex/dev/plt/demo_plotters/plot_stx_scatter.py +29 -0
  98. scitex/dev/plt/demo_plotters/plot_stx_shaded_line.py +29 -0
  99. scitex/dev/plt/demo_plotters/plot_stx_violin.py +28 -0
  100. scitex/dev/plt/demo_plotters/plot_stx_violinplot.py +28 -0
  101. scitex/dev/plt/mpl/get_dir_ax.py +46 -0
  102. scitex/dev/plt/mpl/get_signatures.py +176 -0
  103. scitex/dev/plt/mpl/get_signatures_details.py +522 -0
  104. scitex/dev/plt/plot_mpl_axhline.py +0 -0
  105. scitex/dev/plt/plot_mpl_axhspan.py +0 -0
  106. scitex/dev/plt/plot_mpl_axvline.py +0 -0
  107. scitex/dev/plt/plot_mpl_axvspan.py +0 -0
  108. scitex/dev/plt/plot_mpl_bar.py +0 -0
  109. scitex/dev/plt/plot_mpl_barh.py +0 -0
  110. scitex/dev/plt/plot_mpl_boxplot.py +0 -0
  111. scitex/dev/plt/plot_mpl_contour.py +0 -0
  112. scitex/dev/plt/plot_mpl_contourf.py +0 -0
  113. scitex/dev/plt/plot_mpl_errorbar.py +0 -0
  114. scitex/dev/plt/plot_mpl_eventplot.py +0 -0
  115. scitex/dev/plt/plot_mpl_fill.py +0 -0
  116. scitex/dev/plt/plot_mpl_fill_between.py +0 -0
  117. scitex/dev/plt/plot_mpl_hexbin.py +0 -0
  118. scitex/dev/plt/plot_mpl_hist.py +0 -0
  119. scitex/dev/plt/plot_mpl_hist2d.py +0 -0
  120. scitex/dev/plt/plot_mpl_imshow.py +0 -0
  121. scitex/dev/plt/plot_mpl_pcolormesh.py +0 -0
  122. scitex/dev/plt/plot_mpl_pie.py +0 -0
  123. scitex/dev/plt/plot_mpl_plot.py +0 -0
  124. scitex/dev/plt/plot_mpl_quiver.py +0 -0
  125. scitex/dev/plt/plot_mpl_scatter.py +0 -0
  126. scitex/dev/plt/plot_mpl_stackplot.py +0 -0
  127. scitex/dev/plt/plot_mpl_stem.py +0 -0
  128. scitex/dev/plt/plot_mpl_step.py +0 -0
  129. scitex/dev/plt/plot_mpl_violinplot.py +0 -0
  130. scitex/dev/plt/plot_sns_barplot.py +0 -0
  131. scitex/dev/plt/plot_sns_boxplot.py +0 -0
  132. scitex/dev/plt/plot_sns_heatmap.py +0 -0
  133. scitex/dev/plt/plot_sns_histplot.py +0 -0
  134. scitex/dev/plt/plot_sns_kdeplot.py +0 -0
  135. scitex/dev/plt/plot_sns_lineplot.py +0 -0
  136. scitex/dev/plt/plot_sns_scatterplot.py +0 -0
  137. scitex/dev/plt/plot_sns_stripplot.py +0 -0
  138. scitex/dev/plt/plot_sns_swarmplot.py +0 -0
  139. scitex/dev/plt/plot_sns_violinplot.py +0 -0
  140. scitex/dev/plt/plot_stx_bar.py +0 -0
  141. scitex/dev/plt/plot_stx_barh.py +0 -0
  142. scitex/dev/plt/plot_stx_box.py +0 -0
  143. scitex/dev/plt/plot_stx_boxplot.py +0 -0
  144. scitex/dev/plt/plot_stx_conf_mat.py +0 -0
  145. scitex/dev/plt/plot_stx_contour.py +0 -0
  146. scitex/dev/plt/plot_stx_ecdf.py +0 -0
  147. scitex/dev/plt/plot_stx_errorbar.py +0 -0
  148. scitex/dev/plt/plot_stx_fill_between.py +0 -0
  149. scitex/dev/plt/plot_stx_fillv.py +0 -0
  150. scitex/dev/plt/plot_stx_heatmap.py +0 -0
  151. scitex/dev/plt/plot_stx_image.py +0 -0
  152. scitex/dev/plt/plot_stx_imshow.py +0 -0
  153. scitex/dev/plt/plot_stx_joyplot.py +0 -0
  154. scitex/dev/plt/plot_stx_kde.py +0 -0
  155. scitex/dev/plt/plot_stx_line.py +0 -0
  156. scitex/dev/plt/plot_stx_mean_ci.py +0 -0
  157. scitex/dev/plt/plot_stx_mean_std.py +0 -0
  158. scitex/dev/plt/plot_stx_median_iqr.py +0 -0
  159. scitex/dev/plt/plot_stx_raster.py +0 -0
  160. scitex/dev/plt/plot_stx_rectangle.py +0 -0
  161. scitex/dev/plt/plot_stx_scatter.py +0 -0
  162. scitex/dev/plt/plot_stx_shaded_line.py +0 -0
  163. scitex/dev/plt/plot_stx_violin.py +0 -0
  164. scitex/dev/plt/plot_stx_violinplot.py +0 -0
  165. scitex/diagram/README.md +197 -0
  166. scitex/diagram/__init__.py +48 -0
  167. scitex/diagram/_compile.py +312 -0
  168. scitex/diagram/_diagram.py +355 -0
  169. scitex/diagram/_presets.py +173 -0
  170. scitex/diagram/_schema.py +182 -0
  171. scitex/diagram/_split.py +278 -0
  172. scitex/dict/_pop_keys.py +1 -7
  173. scitex/dsp/__init__.py +15 -10
  174. scitex/dsp/add_noise.py +5 -2
  175. scitex/dsp/example.py +35 -22
  176. scitex/dsp/filt.py +8 -3
  177. scitex/dsp/reference.py +3 -2
  178. scitex/dsp/utils/__init__.py +2 -1
  179. scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
  180. scitex/dt/__init__.py +39 -2
  181. scitex/errors.py +82 -521
  182. scitex/fig/__init__.py +4 -4
  183. scitex/fig/editor/__init__.py +5 -2
  184. scitex/fig/editor/_dearpygui_editor.py +1 -1
  185. scitex/fig/editor/_mpl_editor.py +1 -1
  186. scitex/fig/editor/_qt_editor.py +1 -1
  187. scitex/fig/editor/_tkinter_editor.py +1 -1
  188. scitex/fig/editor/edit/__init__.py +50 -0
  189. scitex/fig/editor/edit/backend_detector.py +109 -0
  190. scitex/fig/editor/edit/bundle_resolver.py +240 -0
  191. scitex/fig/editor/edit/editor_launcher.py +239 -0
  192. scitex/fig/editor/edit/manual_handler.py +53 -0
  193. scitex/fig/editor/edit/panel_loader.py +232 -0
  194. scitex/fig/editor/edit/path_resolver.py +67 -0
  195. scitex/fig/editor/flask_editor/_bbox.py +23 -0
  196. scitex/fig/editor/flask_editor/_core.py +908 -103
  197. scitex/fig/editor/flask_editor/_renderer.py +74 -0
  198. scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
  199. scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
  200. scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
  201. scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
  202. scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
  203. scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
  204. scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
  205. scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
  206. scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
  207. scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
  208. scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
  209. scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
  210. scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
  211. scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
  212. scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
  213. scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
  214. scitex/fig/editor/flask_editor/static/css/index.css +31 -0
  215. scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
  216. scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
  217. scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
  218. scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
  219. scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
  220. scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
  221. scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
  222. scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
  223. scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
  224. scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
  225. scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
  226. scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
  227. scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
  228. scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
  229. scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
  230. scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
  231. scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
  232. scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
  233. scitex/fig/editor/flask_editor/static/js/main.js +426 -0
  234. scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
  235. scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
  236. scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
  237. scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
  238. scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
  239. scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
  240. scitex/fig/editor/flask_editor/templates/__init__.py +95 -5
  241. scitex/fig/editor/flask_editor/templates/_html.py +27 -9
  242. scitex/fig/editor/flask_editor/templates/_scripts.py +1928 -131
  243. scitex/fig/editor/flask_editor/templates/_styles.py +363 -51
  244. scitex/fig/io/_bundle.py +104 -19
  245. scitex/fts/README.md +262 -0
  246. scitex/fts/TODO.md +66 -0
  247. scitex/fts/__init__.py +90 -0
  248. scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
  249. scitex/fts/_bundle/_FTS.py +657 -0
  250. scitex/fts/_bundle/__init__.py +38 -0
  251. scitex/fts/_bundle/_children.py +216 -0
  252. scitex/fts/_bundle/_conversion/__init__.py +15 -0
  253. scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
  254. scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
  255. scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
  256. scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
  257. scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
  258. scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
  259. scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
  260. scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
  261. scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
  262. scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
  263. scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
  264. scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
  265. scitex/fts/_bundle/_extractors/__init__.py +32 -0
  266. scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
  267. scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
  268. scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
  269. scitex/fts/_bundle/_loader.py +134 -0
  270. scitex/fts/_bundle/_mpl_helpers.py +389 -0
  271. scitex/fts/_bundle/_saver.py +269 -0
  272. scitex/fts/_bundle/_storage.py +200 -0
  273. scitex/fts/_bundle/_utils/__init__.py +55 -0
  274. scitex/fts/_bundle/_utils/_const.py +26 -0
  275. scitex/fts/_bundle/_utils/_errors.py +73 -0
  276. scitex/fts/_bundle/_utils/_generate.py +21 -0
  277. scitex/fts/_bundle/_utils/_types.py +76 -0
  278. scitex/fts/_bundle/_validation.py +434 -0
  279. scitex/fts/_bundle/_zipbundle.py +165 -0
  280. scitex/fts/_fig/__init__.py +22 -0
  281. scitex/fts/_fig/_backend/__init__.py +53 -0
  282. scitex/fts/_fig/_backend/_export.py +165 -0
  283. scitex/fts/_fig/_backend/_parser.py +188 -0
  284. scitex/fts/_fig/_backend/_render.py +538 -0
  285. scitex/fts/_fig/_composite.py +345 -0
  286. scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
  287. scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
  288. scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
  289. scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
  290. scitex/fts/_fig/_dataclasses/__init__.py +47 -0
  291. scitex/fts/_fig/_editor/__init__.py +14 -0
  292. scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
  293. scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
  294. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
  295. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
  296. scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
  297. scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
  298. scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
  299. scitex/fts/_fig/_editor/_defaults.py +300 -0
  300. scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
  301. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
  302. scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
  303. scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
  304. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
  305. scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
  306. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
  307. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
  308. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
  309. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
  310. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
  311. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
  312. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
  313. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
  314. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
  315. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
  316. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
  317. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
  318. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
  319. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
  320. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
  321. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
  322. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
  323. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
  324. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
  325. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
  326. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
  327. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
  328. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
  329. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
  330. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
  331. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
  332. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
  333. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
  334. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
  335. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
  336. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
  337. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
  338. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
  339. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
  340. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
  341. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
  342. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
  343. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
  344. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
  345. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
  346. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
  347. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
  348. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
  349. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
  350. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
  351. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
  352. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
  353. scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
  354. scitex/fts/_fig/_models/_Annotations.py +115 -0
  355. scitex/fts/_fig/_models/_Axes.py +152 -0
  356. scitex/fts/_fig/_models/_Figure.py +138 -0
  357. scitex/fts/_fig/_models/_Guides.py +104 -0
  358. scitex/fts/_fig/_models/_Plot.py +123 -0
  359. scitex/fts/_fig/_models/_Styles.py +245 -0
  360. scitex/fts/_fig/_models/__init__.py +80 -0
  361. scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
  362. scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
  363. scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
  364. scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
  365. scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
  366. scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
  367. scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
  368. scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
  369. scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
  370. scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
  371. scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
  372. scitex/fts/_fig/_utils/__init__.py +129 -0
  373. scitex/fts/_fig/_utils/_auto_layout.py +127 -0
  374. scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
  375. scitex/fts/_fig/_utils/_const_sizes.py +48 -0
  376. scitex/fts/_fig/_utils/_convert_coords.py +77 -0
  377. scitex/fts/_fig/_utils/_get_template.py +178 -0
  378. scitex/fts/_fig/_utils/_normalize.py +73 -0
  379. scitex/fts/_fig/_utils/_plot_layout.py +397 -0
  380. scitex/fts/_fig/_utils/_validate.py +197 -0
  381. scitex/fts/_kinds/__init__.py +45 -0
  382. scitex/fts/_kinds/_figure/__init__.py +19 -0
  383. scitex/fts/_kinds/_figure/_composite.py +345 -0
  384. scitex/fts/_kinds/_plot/__init__.py +25 -0
  385. scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
  386. scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
  387. scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
  388. scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
  389. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
  390. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
  391. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
  392. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
  393. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
  394. scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
  395. scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
  396. scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
  397. scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
  398. scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
  399. scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
  400. scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
  401. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
  402. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
  403. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
  404. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
  405. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
  406. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
  407. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
  408. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
  409. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
  410. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
  411. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
  412. scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
  413. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
  414. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
  415. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
  416. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
  417. scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
  418. scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
  419. scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
  420. scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
  421. scitex/fts/_kinds/_shape/__init__.py +141 -0
  422. scitex/fts/_kinds/_stats/__init__.py +56 -0
  423. scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
  424. scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
  425. scitex/fts/_kinds/_table/__init__.py +72 -0
  426. scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
  427. scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
  428. scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
  429. scitex/fts/_kinds/_table/_latex/_export.py +279 -0
  430. scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
  431. scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
  432. scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
  433. scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
  434. scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
  435. scitex/fts/_kinds/_text/__init__.py +77 -0
  436. scitex/fts/_schemas/data_info.schema.json +75 -0
  437. scitex/fts/_schemas/encoding.schema.json +90 -0
  438. scitex/fts/_schemas/node.schema.json +145 -0
  439. scitex/fts/_schemas/render_manifest.schema.json +62 -0
  440. scitex/fts/_schemas/stats.schema.json +132 -0
  441. scitex/fts/_schemas/theme.schema.json +141 -0
  442. scitex/fts/_stats/__init__.py +48 -0
  443. scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
  444. scitex/fts/_stats/_dataclasses/__init__.py +48 -0
  445. scitex/fts/_tables/__init__.py +65 -0
  446. scitex/fts/_tables/_latex/__init__.py +93 -0
  447. scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
  448. scitex/fts/_tables/_latex/_editor/_app.py +725 -0
  449. scitex/fts/_tables/_latex/_export.py +279 -0
  450. scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
  451. scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
  452. scitex/fts/_tables/_latex/_table_exporter.py +362 -0
  453. scitex/fts/_tables/_latex/_utils.py +369 -0
  454. scitex/fts/_tables/_latex/_validator.py +445 -0
  455. scitex/gen/__init__.py +66 -25
  456. scitex/gen/misc.py +28 -0
  457. scitex/io/__init__.py +47 -20
  458. scitex/io/_load.py +87 -36
  459. scitex/io/_load_modules/__init__.py +10 -7
  460. scitex/io/_load_modules/_pandas.py +6 -1
  461. scitex/io/_save.py +299 -1556
  462. scitex/io/_save_modules/__init__.py +76 -19
  463. scitex/io/_save_modules/_figure_utils.py +90 -0
  464. scitex/io/_save_modules/_image_csv.py +497 -0
  465. scitex/io/_save_modules/_legends.py +91 -0
  466. scitex/io/_save_modules/_pltz_bundle.py +356 -0
  467. scitex/io/_save_modules/_pltz_stx.py +536 -0
  468. scitex/io/_save_modules/_stx_bundle.py +104 -0
  469. scitex/io/_save_modules/_symlink.py +96 -0
  470. scitex/io/_save_modules/_yaml.py +1 -1
  471. scitex/io/_save_modules/_zarr.py +64 -18
  472. scitex/io/bundle/README.md +212 -0
  473. scitex/io/bundle/__init__.py +110 -0
  474. scitex/io/{_bundle.py → bundle/_core.py} +219 -89
  475. scitex/io/bundle/_nested.py +713 -0
  476. scitex/io/bundle/_types.py +74 -0
  477. scitex/io/bundle/_zip.py +487 -0
  478. scitex/io/utils/h5_to_zarr.py +1 -1
  479. scitex/logging/__init__.py +108 -13
  480. scitex/logging/_errors.py +508 -0
  481. scitex/logging/_formatters.py +30 -6
  482. scitex/logging/_warnings.py +261 -0
  483. scitex/plt/__init__.py +4 -1
  484. scitex/plt/_figrecipe.py +236 -0
  485. scitex/plt/_subplots/_AxisWrapper.py +6 -0
  486. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +0 -0
  487. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +0 -0
  488. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +0 -0
  489. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +0 -0
  490. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +0 -0
  491. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +0 -0
  492. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +0 -0
  493. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +0 -0
  494. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +0 -0
  495. scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +0 -0
  496. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +0 -0
  497. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +0 -0
  498. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +0 -0
  499. scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
  500. scitex/plt/_subplots/_FigWrapper.py +15 -0
  501. scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
  502. scitex/plt/_subplots/_export_as_csv.py +11 -0
  503. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
  504. scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
  505. scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
  506. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +0 -0
  507. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +0 -0
  508. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +0 -0
  509. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +0 -0
  510. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
  511. scitex/plt/_subplots/_fonts.py +71 -0
  512. scitex/plt/_subplots/_mm_layout.py +282 -0
  513. scitex/plt/gallery/__init__.py +99 -2
  514. scitex/plt/io/_layered_bundle.py +0 -0
  515. scitex/plt/styles/_plot_postprocess.py +3 -1
  516. scitex/plt/utils/_configure_mpl.py +16 -19
  517. scitex/repro/_RandomStateManager.py +13 -8
  518. scitex/resource/__init__.py +19 -1
  519. scitex/resource/_utils/_get_env_info.py +13 -25
  520. scitex/schema/__init__.py +149 -160
  521. scitex/schema/_encoding.py +273 -0
  522. scitex/schema/_figure_elements.py +406 -0
  523. scitex/schema/_plot.py +0 -0
  524. scitex/schema/_theme.py +360 -0
  525. scitex/schema/_validation.py +0 -98
  526. scitex/scholar/__init__.py +56 -14
  527. scitex/scholar/auth/ScholarAuthManager.py +1 -1
  528. scitex/scholar/auth/__init__.py +11 -2
  529. scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
  530. scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
  531. scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
  532. scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
  533. scitex/scholar/config/ScholarConfig.py +1 -1
  534. scitex/scholar/core/Scholar.py +1 -1
  535. scitex/session/_decorator.py +18 -16
  536. scitex/session/_lifecycle.py +9 -11
  537. scitex/session/template.py +9 -8
  538. scitex/sh/test_sh.py +72 -0
  539. scitex/sh/test_sh_simple.py +61 -0
  540. scitex/stats/__init__.py +221 -97
  541. scitex/stats/_schema.py +21 -22
  542. scitex/stats/descriptive/_circular.py +212 -351
  543. scitex/stats/descriptive/_describe.py +81 -132
  544. scitex/stats/descriptive/_nan.py +205 -433
  545. scitex/stats/descriptive/_real.py +127 -141
  546. scitex/str/_format_plot_text.py +5 -5
  547. scitex/str/_latex.py +26 -84
  548. scitex/str/_latex_fallback.py +53 -47
  549. scitex/web/_search_pubmed.py +5 -4
  550. scitex/writer/tests/test_diff_between.py +451 -0
  551. scitex/writer/tests/test_document_section.py +311 -0
  552. scitex/writer/tests/test_document_workflow.py +393 -0
  553. scitex/writer/tests/test_writer.py +361 -0
  554. scitex/writer/tests/test_writer_integration.py +303 -0
  555. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
  556. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/RECORD +479 -108
  557. scitex/fig/editor/_edit.py +0 -751
  558. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
  559. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
  560. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
  561. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
  562. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
  563. {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,22 +1,17 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Timestamp: "2025-05-29 03:46:53 (ywatanabe)"
4
- # File: /ssh:ywatanabe@sp:/home/ywatanabe/proj/scitex_repo/src/scitex/plt/_subplots/_SubplotsWrapper.py
5
- # ----------------------------------------
6
- import os
7
-
8
- __FILE__ = "./src/scitex/plt/_subplots/_SubplotsWrapper.py"
9
- __DIR__ = os.path.dirname(__FILE__)
10
- # ----------------------------------------
2
+ """SubplotsWrapper: Monitor data plotted using matplotlib for CSV export."""
11
3
 
4
+ import os
12
5
  from collections import OrderedDict
13
6
 
14
7
  import matplotlib.pyplot as plt
15
- import numpy as np
16
8
 
17
- from ._AxesWrapper import AxesWrapper
18
- from ._AxisWrapper import AxisWrapper
19
- from ._FigWrapper import FigWrapper
9
+ __FILE__ = "./src/scitex/plt/_subplots/_SubplotsWrapper.py"
10
+ __DIR__ = os.path.dirname(__FILE__)
11
+
12
+ # Configure fonts at import
13
+ from ._fonts import _arial_enabled # noqa: F401
14
+ from ._mm_layout import create_with_mm_control
20
15
 
21
16
  # Register Arial fonts at module import
22
17
  import matplotlib.font_manager as fm
@@ -75,12 +70,28 @@ class SubplotsWrapper:
75
70
  """
76
71
  A wrapper class monitors data plotted using the ax methods from matplotlib.pyplot.
77
72
  This data can be converted into a CSV file formatted for SigmaPlot compatibility.
73
+
74
+ Supports optional figrecipe integration for reproducible figures.
75
+ When figrecipe is available and `use_figrecipe=True`, figures are created
76
+ with recipe recording capability for later reproduction.
78
77
  """
79
78
 
80
79
  def __init__(self):
81
80
  self._subplots_wrapper_history = OrderedDict()
82
81
  self._fig_scitex = None
83
82
  self._counter_part = plt.subplots
83
+ self._figrecipe_available = None # Lazy check
84
+
85
+ def _check_figrecipe(self):
86
+ """Check if figrecipe is available (lazy, cached)."""
87
+ if self._figrecipe_available is None:
88
+ try:
89
+ import figrecipe # noqa: F401
90
+
91
+ self._figrecipe_available = True
92
+ except ImportError:
93
+ self._figrecipe_available = False
94
+ return self._figrecipe_available
84
95
 
85
96
  def __call__(
86
97
  self,
@@ -89,6 +100,7 @@ class SubplotsWrapper:
89
100
  sharex=False,
90
101
  sharey=False,
91
102
  constrained_layout=None,
103
+ use_figrecipe=None, # NEW: Enable figrecipe recording
92
104
  # MM-control parameters (unified style system)
93
105
  axes_width_mm=None,
94
106
  axes_height_mm=None,
@@ -111,9 +123,9 @@ class SubplotsWrapper:
111
123
  n_ticks=None,
112
124
  mode=None,
113
125
  dpi=None,
114
- styles=None, # List of style dicts for per-axes control
115
- transparent=None, # Transparent background (default: from SCITEX_STYLE.yaml)
116
- theme=None, # Color theme: "light" or "dark" (default: "light")
126
+ styles=None,
127
+ transparent=None,
128
+ theme=None,
117
129
  **kwargs,
118
130
  ):
119
131
  """
@@ -125,104 +137,33 @@ class SubplotsWrapper:
125
137
  nrows, ncols passed to matplotlib.pyplot.subplots
126
138
  track : bool, optional
127
139
  Track plotting operations for CSV export (default: True)
128
- sharex, sharey : bool, optional
129
- Share axes (default: False)
130
- constrained_layout : dict or None, optional
131
- Layout engine parameters
132
-
133
- MM-Control Parameters (Unified Style System)
134
- ---------------------------------------------
135
- axes_width_mm : float or list, optional
136
- Axes width in mm (single value for all, or list for each)
137
- axes_height_mm : float or list, optional
138
- Axes height in mm (single value for all, or list for each)
139
- margin_left_mm : float, optional
140
- Left margin in mm (default: 5.0)
141
- margin_right_mm : float, optional
142
- Right margin in mm (default: 2.0)
143
- margin_bottom_mm : float, optional
144
- Bottom margin in mm (default: 5.0)
145
- margin_top_mm : float, optional
146
- Top margin in mm (default: 2.0)
147
- space_w_mm : float, optional
148
- Horizontal spacing between axes in mm (default: 3.0)
149
- space_h_mm : float, optional
150
- Vertical spacing between axes in mm (default: 3.0)
151
- axes_thickness_mm : float, optional
152
- Axes spine thickness in mm
153
- tick_length_mm : float, optional
154
- Tick length in mm
155
- tick_thickness_mm : float, optional
156
- Tick thickness in mm
157
- trace_thickness_mm : float, optional
158
- Plot line thickness in mm
159
- axis_font_size_pt : float, optional
160
- Axis label font size in points
161
- tick_font_size_pt : float, optional
162
- Tick label font size in points
163
- mode : str, optional
164
- 'publication' or 'display' (default: None, uses standard matplotlib)
165
- dpi : int, optional
166
- Resolution (default: 300 for publication, 100 for display)
167
- styles : list of dict, optional
168
- Individual style dicts for each axes
169
- transparent : bool, optional
170
- Create figure with transparent background (default: False)
171
- Useful for publication-ready figures that will be cropped
172
- theme : str, optional
173
- Color theme: "light" or "dark" (default: "light")
174
- Dark mode uses eye-friendly colors optimized for dark backgrounds
175
- **kwargs
176
- Additional arguments passed to matplotlib.pyplot.subplots
140
+ use_figrecipe : bool or None, optional
141
+ If True, use figrecipe for recipe recording.
142
+ If None (default), auto-detect figrecipe availability.
143
+ If False, disable figrecipe even if available.
144
+
145
+ MM-Control Parameters
146
+ ---------------------
147
+ axes_width_mm, axes_height_mm : float or list
148
+ Axes dimensions in mm
149
+ margin_*_mm : float
150
+ Figure margins in mm
151
+ space_w_mm, space_h_mm : float
152
+ Spacing between axes in mm
153
+ mode : str
154
+ 'publication' or 'display'
177
155
 
178
156
  Returns
179
157
  -------
180
158
  fig : FigWrapper
181
- Wrapped matplotlib Figure
159
+ Wrapped matplotlib Figure (with optional RecordingFigure)
182
160
  ax or axes : AxisWrapper or AxesWrapper
183
161
  Wrapped matplotlib Axes
184
-
185
- Examples
186
- --------
187
- Single axes with style:
188
-
189
- >>> fig, ax = stx.plt.subplots(
190
- ... axes_width_mm=30,
191
- ... axes_height_mm=21,
192
- ... axes_thickness_mm=0.2,
193
- ... tick_length_mm=0.8,
194
- ... mode='publication'
195
- ... )
196
-
197
- Multiple axes with uniform style:
198
-
199
- >>> fig, axes = stx.plt.subplots(
200
- ... nrows=2, ncols=3,
201
- ... axes_width_mm=30,
202
- ... axes_height_mm=21,
203
- ... space_w_mm=3,
204
- ... space_h_mm=3,
205
- ... mode='publication'
206
- ... )
207
-
208
- Using style preset:
209
-
210
- >>> NATURE_STYLE = {
211
- ... 'axes_width_mm': 30,
212
- ... 'axes_height_mm': 21,
213
- ... 'axes_thickness_mm': 0.2,
214
- ... 'tick_length_mm': 0.8,
215
- ... }
216
- >>> fig, ax = stx.plt.subplots(**NATURE_STYLE)
217
162
  """
163
+ # Resolve style values
164
+ from scitex.plt.styles import SCITEX_STYLE as _S
165
+ from scitex.plt.styles import resolve_style_value as _resolve
218
166
 
219
- # Use resolve_style_value for priority: direct → yaml → env → default
220
- from scitex.plt.styles import (
221
- resolve_style_value as _resolve,
222
- SCITEX_STYLE as _S,
223
- )
224
-
225
- # Resolve all style values with proper priority chain
226
167
  axes_width_mm = _resolve(
227
168
  "axes.width_mm", axes_width_mm, _S.get("axes_width_mm")
228
169
  )
@@ -275,419 +216,114 @@ class SubplotsWrapper:
275
216
  )
276
217
  n_ticks = _resolve("ticks.n_ticks", n_ticks, _S.get("n_ticks"), int)
277
218
  dpi = _resolve("output.dpi", dpi, _S.get("dpi"), int)
278
- # Resolve transparent from YAML (default: True in SCITEX_STYLE.yaml)
219
+
279
220
  if transparent is None:
280
221
  transparent = _S.get("transparent", True)
281
222
  if mode is None:
282
223
  mode = _S.get("mode", "publication")
283
- # Resolve theme from YAML (default: "light")
284
224
  if theme is None:
285
225
  theme = _resolve("theme.mode", None, "light", str)
286
226
 
287
- # Always use mm-control pathway with SCITEX_STYLE defaults
288
- if True:
289
- # Use mm-control pathway
290
- return self._create_with_mm_control(
291
- *args,
292
- track=track,
293
- sharex=sharex,
294
- sharey=sharey,
295
- axes_width_mm=axes_width_mm,
296
- axes_height_mm=axes_height_mm,
297
- margin_left_mm=margin_left_mm,
298
- margin_right_mm=margin_right_mm,
299
- margin_bottom_mm=margin_bottom_mm,
300
- margin_top_mm=margin_top_mm,
301
- space_w_mm=space_w_mm,
302
- space_h_mm=space_h_mm,
303
- axes_thickness_mm=axes_thickness_mm,
304
- tick_length_mm=tick_length_mm,
305
- tick_thickness_mm=tick_thickness_mm,
306
- trace_thickness_mm=trace_thickness_mm,
307
- marker_size_mm=marker_size_mm,
308
- axis_font_size_pt=axis_font_size_pt,
309
- tick_font_size_pt=tick_font_size_pt,
310
- title_font_size_pt=title_font_size_pt,
311
- legend_font_size_pt=legend_font_size_pt,
312
- suptitle_font_size_pt=suptitle_font_size_pt,
313
- n_ticks=n_ticks,
314
- mode=mode,
315
- dpi=dpi,
316
- styles=styles,
317
- transparent=transparent,
318
- theme=theme,
319
- **kwargs,
320
- )
321
-
322
- def _create_with_mm_control(
323
- self,
324
- *args,
325
- track=True,
326
- sharex=False,
327
- sharey=False,
328
- axes_width_mm=None,
329
- axes_height_mm=None,
330
- margin_left_mm=None,
331
- margin_right_mm=None,
332
- margin_bottom_mm=None,
333
- margin_top_mm=None,
334
- space_w_mm=None,
335
- space_h_mm=None,
336
- axes_thickness_mm=None,
337
- tick_length_mm=None,
338
- tick_thickness_mm=None,
339
- trace_thickness_mm=None,
340
- marker_size_mm=None,
341
- axis_font_size_pt=None,
342
- tick_font_size_pt=None,
343
- title_font_size_pt=None,
344
- legend_font_size_pt=None,
345
- suptitle_font_size_pt=None,
346
- label_pad_pt=None,
347
- tick_pad_pt=None,
348
- title_pad_pt=None,
349
- font_family=None,
350
- n_ticks=None,
351
- mode=None,
352
- dpi=None,
353
- styles=None,
354
- transparent=None, # Resolved from caller
355
- theme=None, # Color theme: "light" or "dark"
356
- **kwargs,
357
- ):
358
- """Create figure with mm-based control over axes dimensions."""
359
- from scitex.plt.utils import mm_to_inch, apply_style_mm
360
-
361
- # Parse nrows, ncols from args or kwargs (like matplotlib.pyplot.subplots)
362
- nrows, ncols = 1, 1
363
- if len(args) >= 1:
364
- nrows = args[0]
365
- elif "nrows" in kwargs:
366
- nrows = kwargs.pop("nrows")
367
- if len(args) >= 2:
368
- ncols = args[1]
369
- elif "ncols" in kwargs:
370
- ncols = kwargs.pop("ncols")
371
-
372
- n_axes = nrows * ncols
373
-
374
- # Apply mode-specific defaults
375
- if mode == "display":
376
- scale_factor = 3.0
377
- dpi = dpi or 100
378
- else: # publication or None
379
- scale_factor = 1.0
380
- dpi = dpi or 300
381
-
382
- # Set defaults - if value is provided, apply scaling; if not, use scaled default
383
- if axes_width_mm is None:
384
- axes_width_mm = 30.0 * scale_factor
385
- elif mode == "display":
386
- axes_width_mm = axes_width_mm * scale_factor
387
-
388
- if axes_height_mm is None:
389
- axes_height_mm = 21.0 * scale_factor
390
- elif mode == "display":
391
- axes_height_mm = axes_height_mm * scale_factor
392
-
393
- margin_left_mm = (
394
- margin_left_mm if margin_left_mm is not None else (5.0 * scale_factor)
395
- )
396
- margin_right_mm = (
397
- margin_right_mm if margin_right_mm is not None else (2.0 * scale_factor)
398
- )
399
- margin_bottom_mm = (
400
- margin_bottom_mm if margin_bottom_mm is not None else (5.0 * scale_factor)
401
- )
402
- margin_top_mm = (
403
- margin_top_mm if margin_top_mm is not None else (2.0 * scale_factor)
404
- )
405
- space_w_mm = space_w_mm if space_w_mm is not None else (3.0 * scale_factor)
406
- space_h_mm = space_h_mm if space_h_mm is not None else (3.0 * scale_factor)
407
-
408
- # Handle list vs scalar for axes_width_mm and axes_height_mm
409
- if isinstance(axes_width_mm, (list, tuple)):
410
- ax_widths_mm = list(axes_width_mm)
411
- if len(ax_widths_mm) != n_axes:
412
- raise ValueError(
413
- f"axes_width_mm list length ({len(ax_widths_mm)}) must match nrows*ncols ({n_axes})"
414
- )
415
- else:
416
- ax_widths_mm = [axes_width_mm] * n_axes
417
-
418
- if isinstance(axes_height_mm, (list, tuple)):
419
- ax_heights_mm = list(axes_height_mm)
420
- if len(ax_heights_mm) != n_axes:
421
- raise ValueError(
422
- f"axes_height_mm list length ({len(ax_heights_mm)}) must match nrows*ncols ({n_axes})"
423
- )
424
- else:
425
- ax_heights_mm = [axes_height_mm] * n_axes
426
-
427
- # Calculate figure size from axes grid
428
- # For simplicity, use max width per column and max height per row
429
- ax_widths_2d = np.array(ax_widths_mm).reshape(nrows, ncols)
430
- ax_heights_2d = np.array(ax_heights_mm).reshape(nrows, ncols)
431
-
432
- max_widths_per_col = ax_widths_2d.max(axis=0) # Max width in each column
433
- max_heights_per_row = ax_heights_2d.max(axis=1) # Max height in each row
434
-
435
- total_width_mm = (
436
- margin_left_mm
437
- + max_widths_per_col.sum()
438
- + (ncols - 1) * space_w_mm
439
- + margin_right_mm
440
- )
441
- total_height_mm = (
442
- margin_bottom_mm
443
- + max_heights_per_row.sum()
444
- + (nrows - 1) * space_h_mm
445
- + margin_top_mm
227
+ # Determine figrecipe usage
228
+ if use_figrecipe is None:
229
+ use_figrecipe = self._check_figrecipe()
230
+
231
+ # Create figure with mm-control
232
+ fig, axes = create_with_mm_control(
233
+ *args,
234
+ track=track,
235
+ sharex=sharex,
236
+ sharey=sharey,
237
+ axes_width_mm=axes_width_mm,
238
+ axes_height_mm=axes_height_mm,
239
+ margin_left_mm=margin_left_mm,
240
+ margin_right_mm=margin_right_mm,
241
+ margin_bottom_mm=margin_bottom_mm,
242
+ margin_top_mm=margin_top_mm,
243
+ space_w_mm=space_w_mm,
244
+ space_h_mm=space_h_mm,
245
+ axes_thickness_mm=axes_thickness_mm,
246
+ tick_length_mm=tick_length_mm,
247
+ tick_thickness_mm=tick_thickness_mm,
248
+ trace_thickness_mm=trace_thickness_mm,
249
+ marker_size_mm=marker_size_mm,
250
+ axis_font_size_pt=axis_font_size_pt,
251
+ tick_font_size_pt=tick_font_size_pt,
252
+ title_font_size_pt=title_font_size_pt,
253
+ legend_font_size_pt=legend_font_size_pt,
254
+ suptitle_font_size_pt=suptitle_font_size_pt,
255
+ n_ticks=n_ticks,
256
+ mode=mode,
257
+ dpi=dpi,
258
+ styles=styles,
259
+ transparent=transparent,
260
+ theme=theme,
261
+ **kwargs,
446
262
  )
447
263
 
448
- # Create figure with calculated size
449
- figsize_inch = (mm_to_inch(total_width_mm), mm_to_inch(total_height_mm))
450
- if transparent:
451
- # Transparent background for publication figures
452
- self._fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi, facecolor="none")
453
- else:
454
- self._fig_mpl = plt.figure(figsize=figsize_inch, dpi=dpi)
455
-
456
- # Store theme on figure for later retrieval (e.g., when saving plot.json)
457
- if theme is not None:
458
- self._fig_mpl._scitex_theme = theme
459
-
460
- # Create axes array and position each one manually
461
- axes_mpl_list = []
462
- ax_idx = 0
463
-
464
- for row in range(nrows):
465
- for col in range(ncols):
466
- # Calculate position for this axes
467
- # Left position: left margin + sum of previous column widths + spacing
468
- left_mm = (
469
- margin_left_mm + max_widths_per_col[:col].sum() + col * space_w_mm
470
- )
471
-
472
- # Bottom position: bottom margin + sum of heights above this row + spacing
473
- # (rows are counted from top in matplotlib)
474
- rows_below = nrows - row - 1
475
- bottom_mm = (
476
- margin_bottom_mm
477
- + max_heights_per_row[row + 1 :].sum()
478
- + rows_below * space_h_mm
479
- )
480
-
481
- # Convert to figure coordinates [0-1]
482
- left = left_mm / total_width_mm
483
- bottom = bottom_mm / total_height_mm
484
- width = ax_widths_mm[ax_idx] / total_width_mm
485
- height = ax_heights_mm[ax_idx] / total_height_mm
486
-
487
- # Create axes at exact position with transparent background
488
- ax_mpl = self._fig_mpl.add_axes([left, bottom, width, height])
489
- if transparent:
490
- ax_mpl.patch.set_alpha(0.0) # Make axes background transparent
491
- axes_mpl_list.append(ax_mpl)
492
-
493
- # Tag with metadata
494
- ax_mpl._scitex_metadata = {
495
- "created_with": "scitex.plt.subplots",
496
- "mode": mode or "publication",
497
- "axes_size_mm": (ax_widths_mm[ax_idx], ax_heights_mm[ax_idx]),
498
- "position_in_grid": (row, col),
499
- }
500
-
501
- ax_idx += 1
502
-
503
- # Apply styling to each axes
504
- suptitle_font_size_pt = None
505
- for i, ax_mpl in enumerate(axes_mpl_list):
506
- # Determine which style dict to use
507
- if styles is not None:
508
- if isinstance(styles, list):
509
- if len(styles) != n_axes:
510
- raise ValueError(
511
- f"styles list length ({len(styles)}) must match nrows*ncols ({n_axes})"
512
- )
513
- style_dict = styles[i]
514
- else:
515
- style_dict = styles
516
- else:
517
- # Build style dict from individual parameters
518
- style_dict = {}
519
- if axes_thickness_mm is not None:
520
- style_dict["axis_thickness_mm"] = axes_thickness_mm
521
- if tick_length_mm is not None:
522
- style_dict["tick_length_mm"] = tick_length_mm
523
- if tick_thickness_mm is not None:
524
- style_dict["tick_thickness_mm"] = tick_thickness_mm
525
- if trace_thickness_mm is not None:
526
- style_dict["trace_thickness_mm"] = trace_thickness_mm
527
- if marker_size_mm is not None:
528
- style_dict["marker_size_mm"] = marker_size_mm
529
- if axis_font_size_pt is not None:
530
- style_dict["axis_font_size_pt"] = axis_font_size_pt
531
- if tick_font_size_pt is not None:
532
- style_dict["tick_font_size_pt"] = tick_font_size_pt
533
- if title_font_size_pt is not None:
534
- style_dict["title_font_size_pt"] = title_font_size_pt
535
- if legend_font_size_pt is not None:
536
- style_dict["legend_font_size_pt"] = legend_font_size_pt
537
- if suptitle_font_size_pt is not None:
538
- style_dict["suptitle_font_size_pt"] = suptitle_font_size_pt
539
- if label_pad_pt is not None:
540
- style_dict["label_pad_pt"] = label_pad_pt
541
- if tick_pad_pt is not None:
542
- style_dict["tick_pad_pt"] = tick_pad_pt
543
- if title_pad_pt is not None:
544
- style_dict["title_pad_pt"] = title_pad_pt
545
- if font_family is not None:
546
- style_dict["font_family"] = font_family
547
- if n_ticks is not None:
548
- style_dict["n_ticks"] = n_ticks
549
-
550
- # Always add theme to style_dict (default: "light")
551
- if theme is not None:
552
- style_dict["theme"] = theme
553
-
554
- # Extract suptitle font size if available
555
- if "suptitle_font_size_pt" in style_dict:
556
- suptitle_font_size_pt_value = style_dict["suptitle_font_size_pt"]
557
- else:
558
- suptitle_font_size_pt_value = None
559
-
560
- # Apply style if not empty
561
- if style_dict:
562
- apply_style_mm(ax_mpl, style_dict)
563
- # Add style to metadata
564
- ax_mpl._scitex_metadata["style_mm"] = style_dict
565
-
566
- # Store suptitle font size in figure metadata for later use
567
- if suptitle_font_size_pt_value is not None:
568
- self._fig_mpl._scitex_suptitle_font_size_pt = suptitle_font_size_pt_value
569
-
570
- # Wrap the figure
571
- self._fig_scitex = FigWrapper(self._fig_mpl)
572
-
573
- # Reshape axes list to match grid shape
574
- axes_array_mpl = np.array(axes_mpl_list).reshape(nrows, ncols)
575
-
576
- # Handle single axis case
577
- if n_axes == 1:
578
- ax_mpl_scalar = axes_array_mpl.item()
579
- self._axis_scitex = AxisWrapper(self._fig_scitex, ax_mpl_scalar, track)
580
- self._fig_scitex.axes = self._axis_scitex
581
- # Store reference to scitex wrapper on matplotlib axes for metadata collection
582
- ax_mpl_scalar._scitex_wrapper = self._axis_scitex
583
- return self._fig_scitex, self._axis_scitex
584
-
585
- # Handle multiple axes case
586
- axes_flat_scitex_list = []
587
- for ax_mpl in axes_mpl_list:
588
- ax_scitex = AxisWrapper(self._fig_scitex, ax_mpl, track)
589
- # Store reference to scitex wrapper on matplotlib axes for metadata collection
590
- ax_mpl._scitex_wrapper = ax_scitex
591
- axes_flat_scitex_list.append(ax_scitex)
592
-
593
- axes_array_scitex = np.array(axes_flat_scitex_list).reshape(nrows, ncols)
594
- self._axes_scitex = AxesWrapper(self._fig_scitex, axes_array_scitex)
595
- self._fig_scitex.axes = self._axes_scitex
596
-
597
- return self._fig_scitex, self._axes_scitex
598
-
599
- # def __getattr__(self, name):
600
- # """
601
- # Fallback to fetch attributes from the original matplotlib.pyplot.subplots function
602
- # if they are not defined directly in this wrapper instance.
603
- # This allows accessing attributes like __name__, __doc__ etc. from the original function.
604
- # """
605
- # print(f"Attribute of SubplotsWrapper: {name}")
606
- # # Check if the attribute exists in the counterpart function
607
- # if hasattr(self._counter_part, name):
608
- # return getattr(self._counter_part, name)
609
- # # Raise the standard error if not found in the wrapper or the counterpart
610
- # raise AttributeError(
611
- # f"'{type(self).__name__}' object and its counterpart '{self._counter_part.__name__}' have no attribute '{name}'"
612
- # )
613
-
614
- def __dir__(
615
- self,
616
- ):
617
- """
618
- Provide combined directory for tab completion, including
619
- attributes from this wrapper and the original matplotlib.pyplot.subplots function.
264
+ # If figrecipe enabled, create recording layer
265
+ if use_figrecipe:
266
+ self._attach_figrecipe_recorder(fig)
267
+
268
+ self._fig_scitex = fig
269
+ return fig, axes
270
+
271
+ def _attach_figrecipe_recorder(self, fig_wrapper):
272
+ """Attach figrecipe recorder to FigWrapper for recipe export.
273
+
274
+ This creates a RecordingFigure layer that wraps the underlying
275
+ matplotlib figure, enabling save_recipe() on the FigWrapper.
620
276
  """
621
- # Get attributes defined explicitly in this instance/class
277
+ try:
278
+ from figrecipe._recorder import Recorder
279
+
280
+ # Get the underlying matplotlib figure
281
+ mpl_fig = fig_wrapper._fig_mpl
282
+
283
+ # Create recorder
284
+ recorder = Recorder()
285
+ figsize = mpl_fig.get_size_inches()
286
+ dpi_val = mpl_fig.dpi
287
+ recorder.start_figure(figsize=tuple(figsize), dpi=int(dpi_val))
288
+
289
+ # Store recorder on FigWrapper for later recipe export
290
+ fig_wrapper._figrecipe_recorder = recorder
291
+ fig_wrapper._figrecipe_enabled = True
292
+
293
+ # Store style info from scitex in the recipe
294
+ if hasattr(mpl_fig, "_scitex_theme"):
295
+ recorder.figure_record.style = {"theme": mpl_fig._scitex_theme}
296
+
297
+ except Exception:
298
+ # Silently fail - figrecipe is optional
299
+ fig_wrapper._figrecipe_enabled = False
300
+
301
+ def __dir__(self):
302
+ """Provide combined directory for tab completion."""
622
303
  local_attrs = set(super().__dir__())
623
- # Get attributes from the counterpart function
624
304
  try:
625
305
  counterpart_attrs = set(dir(self._counter_part))
626
306
  except Exception:
627
307
  counterpart_attrs = set()
628
- # Return the sorted union
629
308
  return sorted(local_attrs.union(counterpart_attrs))
630
309
 
631
310
 
632
- # Instantiate the wrapper. This instance will be imported and used.
311
+ # Instantiate the wrapper
633
312
  subplots = SubplotsWrapper()
634
313
 
314
+
635
315
  if __name__ == "__main__":
636
316
  import matplotlib
317
+
637
318
  import scitex
638
319
 
639
- matplotlib.use("TkAgg") # "TkAgg"
320
+ matplotlib.use("TkAgg")
640
321
 
641
322
  fig, ax = subplots()
642
323
  ax.plot([1, 2, 3], [4, 5, 6], id="plot1")
643
324
  ax.plot([4, 5, 6], [1, 2, 3], id="plot2")
644
325
  scitex.io.save(fig, "/tmp/subplots_demo/plots.png")
645
326
 
646
- # Behaves like native matplotlib.pyplot.subplots without tracking
647
- fig, ax = subplots(track=False)
648
- ax.plot([1, 2, 3], [4, 5, 6], id="plot3")
649
- ax.plot([4, 5, 6], [1, 2, 3], id="plot4")
650
- scitex.io.save(fig, "/tmp/subplots_demo/plots.png")
651
-
652
- fig, ax = subplots()
653
- ax.scatter([1, 2, 3], [4, 5, 6], id="scatter1")
654
- ax.scatter([4, 5, 6], [1, 2, 3], id="scatter2")
655
- scitex.io.save(fig, "/tmp/subplots_demo/scatters.png")
656
-
657
- fig, ax = subplots()
658
- ax.boxplot([1, 2, 3], id="boxplot1")
659
- scitex.io.save(fig, "/tmp/subplots_demo/boxplot1.png")
660
-
661
- fig, ax = subplots()
662
- ax.bar(["A", "B", "C"], [4, 5, 6], id="bar1")
663
- scitex.io.save(fig, "/tmp/subplots_demo/bar1.png")
664
-
665
327
  print(ax.export_as_csv())
666
- # plot1_plot_x plot1_plot_y plot2_plot_x ... boxplot1_boxplot_x bar1_bar_x bar1_bar_y
667
- # 0 1.0 4.0 4.0 ... 1.0 A 4.0
668
- # 1 2.0 5.0 5.0 ... 2.0 B 5.0
669
- # 2 3.0 6.0 6.0 ... 3.0 C 6.0
670
-
671
- print(ax.export_as_csv().keys()) # plot3 and plot 4 are not tracked
672
- # [3 rows x 11 columns]
673
- # Index(['plot1_plot_x', 'plot1_plot_y', 'plot2_plot_x', 'plot2_plot_y',
674
- # 'scatter1_scatter_x', 'scatter1_scatter_y', 'scatter2_scatter_x',
675
- # 'scatter2_scatter_y', 'boxplot1_boxplot_x', 'bar1_bar_x', 'bar1_bar_y'],
676
- # dtype='object')
677
-
678
- # If a path is passed, the sigmaplot-friendly dataframe is saved as a csv file.
679
- ax.export_as_csv("./tmp/subplots_demo/for_sigmaplot.csv")
680
- # Saved to: ./tmp/subplots_demo/for_sigmaplot.csv
681
-
682
- """
683
- from matplotlib.pyplot import subplots as counter_part
684
- from scitex.plt import subplots as msubplots
685
- print(set(dir(msubplots)) - set(dir(counter_part)))
686
- is_compatible = np.all([kk in set(dir(msubplots)) for kk in set(dir(counter_part))])
687
- if is_compatible:
688
- print(f"{msubplots.__name__} is compatible with {counter_part.__name__}")
689
- else:
690
- print(f"{msubplots.__name__} is incompatible with {counter_part.__name__}")
691
- """
692
328
 
693
329
  # EOF