scitex 2.10.3__py3-none-any.whl → 2.13.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 (504) hide show
  1. scitex/__init__.py +1 -4
  2. scitex/__main__.py +24 -5
  3. scitex/__version__.py +1 -1
  4. scitex/_install_guide.py +14 -2
  5. scitex/_optional_deps.py +33 -0
  6. scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
  7. scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
  8. scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
  9. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
  10. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
  11. scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
  12. scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
  13. scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
  14. scitex/ai/plt/_plot_feature_importance.py +1 -1
  15. scitex/ai/plt/_plot_learning_curve.py +1 -1
  16. scitex/ai/plt/_plot_optuna_study.py +1 -1
  17. scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
  18. scitex/ai/plt/_plot_roc_curve.py +1 -1
  19. scitex/ai/plt/_stx_conf_mat.py +1 -1
  20. scitex/ai/training/_LearningCurveLogger.py +1 -1
  21. scitex/audio/mcp_server.py +38 -8
  22. scitex/bridge/_figrecipe.py +1 -1
  23. scitex/bridge/_helpers.py +1 -1
  24. scitex/bridge/_plt_vis.py +1 -1
  25. scitex/bridge/_stats_plt.py +1 -1
  26. scitex/bridge/_stats_vis.py +2 -2
  27. scitex/browser/automation/CookieHandler.py +1 -1
  28. scitex/browser/core/BrowserMixin.py +1 -1
  29. scitex/browser/core/ChromeProfileManager.py +1 -1
  30. scitex/browser/debugging/_browser_logger.py +1 -1
  31. scitex/browser/debugging/_highlight_element.py +1 -1
  32. scitex/browser/debugging/_show_grid.py +1 -1
  33. scitex/browser/interaction/click_center.py +1 -1
  34. scitex/browser/interaction/click_with_fallbacks.py +1 -1
  35. scitex/browser/interaction/close_popups.py +1 -1
  36. scitex/browser/interaction/fill_with_fallbacks.py +1 -1
  37. scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
  38. scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
  39. scitex/browser/stealth/HumanBehavior.py +1 -1
  40. scitex/browser/stealth/StealthManager.py +1 -1
  41. scitex/{fig → canvas}/__init__.py +84 -96
  42. scitex/canvas/_mcp_handlers.py +372 -0
  43. scitex/canvas/_mcp_tool_schemas.py +219 -0
  44. scitex/{fig → canvas}/backend/_parser.py +1 -1
  45. scitex/{fig → canvas}/canvas.py +13 -14
  46. scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
  47. scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
  48. scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
  49. scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
  50. scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
  51. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
  52. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
  53. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
  54. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
  55. scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
  56. scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
  57. scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
  58. scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
  59. scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
  60. scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
  61. scitex/{fig → canvas}/io/__init__.py +32 -38
  62. scitex/{fig → canvas}/io/_bundle.py +217 -154
  63. scitex/{fig → canvas}/io/_canvas.py +1 -1
  64. scitex/{fig → canvas}/io/_data.py +1 -1
  65. scitex/{fig → canvas}/io/_export.py +1 -1
  66. scitex/{fig → canvas}/io/_load.py +1 -1
  67. scitex/{fig → canvas}/io/_panel.py +1 -1
  68. scitex/{fig → canvas}/io/_save.py +1 -1
  69. scitex/canvas/mcp_server.py +151 -0
  70. scitex/{fig → canvas}/model/__init__.py +1 -1
  71. scitex/{fig → canvas}/model/_annotations.py +1 -1
  72. scitex/{fig → canvas}/model/_axes.py +1 -1
  73. scitex/{fig → canvas}/model/_figure.py +1 -1
  74. scitex/{fig → canvas}/model/_guides.py +1 -1
  75. scitex/{fig → canvas}/model/_plot.py +1 -1
  76. scitex/{fig → canvas}/model/_styles.py +1 -1
  77. scitex/{fig → canvas}/utils/__init__.py +1 -1
  78. scitex/capture/mcp_server.py +41 -12
  79. scitex/cli/audio.py +233 -0
  80. scitex/cli/capture.py +307 -0
  81. scitex/cli/convert.py +10 -6
  82. scitex/cli/main.py +27 -4
  83. scitex/cli/repro.py +233 -0
  84. scitex/cli/resource.py +240 -0
  85. scitex/cli/stats.py +325 -0
  86. scitex/cli/template.py +236 -0
  87. scitex/cli/tex.py +286 -0
  88. scitex/cli/web.py +11 -12
  89. scitex/dev/__init__.py +3 -0
  90. scitex/dev/_pyproject.py +405 -0
  91. scitex/dev/plt/__init__.py +2 -2
  92. scitex/dev/plt/mpl/get_dir_ax.py +1 -1
  93. scitex/dev/plt/mpl/get_signatures.py +1 -1
  94. scitex/dev/plt/mpl/get_signatures_details.py +1 -1
  95. scitex/diagram/README.md +7 -7
  96. scitex/diagram/_mcp_handlers.py +400 -0
  97. scitex/diagram/_mcp_tool_schemas.py +157 -0
  98. scitex/diagram/mcp_server.py +151 -0
  99. scitex/dsp/_demo_sig.py +51 -5
  100. scitex/dsp/_mne.py +13 -2
  101. scitex/dsp/_modulation_index.py +15 -3
  102. scitex/dsp/_pac.py +23 -5
  103. scitex/dsp/_psd.py +16 -4
  104. scitex/dsp/_resample.py +24 -4
  105. scitex/dsp/_transform.py +16 -3
  106. scitex/dsp/add_noise.py +15 -1
  107. scitex/dsp/norm.py +17 -2
  108. scitex/dsp/reference.py +17 -1
  109. scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
  110. scitex/dsp/utils/_zero_pad.py +18 -4
  111. scitex/dt/_normalize_timestamp.py +1 -1
  112. scitex/git/_session.py +1 -1
  113. scitex/io/__init__.py +7 -19
  114. scitex/io/_load.py +15 -19
  115. scitex/io/_load_modules/_canvas.py +2 -2
  116. scitex/io/_load_modules/_con.py +17 -6
  117. scitex/io/_load_modules/_eeg.py +28 -13
  118. scitex/io/_load_modules/_optuna.py +21 -63
  119. scitex/io/_load_modules/_torch.py +11 -3
  120. scitex/io/_save.py +11 -16
  121. scitex/io/_save_modules/__init__.py +6 -10
  122. scitex/io/_save_modules/_canvas.py +3 -3
  123. scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
  124. scitex/io/_save_modules/_plot_bundle.py +112 -0
  125. scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
  126. scitex/io/_save_modules/_stx_bundle.py +16 -16
  127. scitex/io/_save_modules/_torch.py +11 -3
  128. scitex/io/bundle/README.md +89 -80
  129. scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
  130. scitex/io/bundle/__init__.py +67 -35
  131. scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
  132. scitex/io/bundle/_core.py +184 -97
  133. scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
  134. scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
  135. scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
  136. scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
  137. scitex/io/bundle/_manifest.py +99 -0
  138. scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
  139. scitex/io/bundle/_nested.py +113 -100
  140. scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
  141. scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
  142. scitex/io/bundle/_types.py +41 -16
  143. scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
  144. scitex/io/bundle/_zip.py +21 -31
  145. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
  146. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
  147. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
  148. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
  149. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
  150. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
  151. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
  152. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
  153. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
  154. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
  155. scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
  156. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
  157. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
  158. scitex/io/bundle/schemas/__init__.py +30 -0
  159. scitex/mcp_server.py +159 -0
  160. scitex/parallel/_run.py +5 -4
  161. scitex/path/_find.py +60 -83
  162. scitex/path/_get_module_path.py +23 -21
  163. scitex/path/_get_spath.py +6 -27
  164. scitex/path/_getsize.py +23 -9
  165. scitex/path/_increment_version.py +31 -38
  166. scitex/path/_mk_spath.py +26 -29
  167. scitex/path/_path.py +5 -12
  168. scitex/path/_split.py +27 -15
  169. scitex/path/_this_path.py +23 -9
  170. scitex/plt/_mcp_handlers.py +361 -0
  171. scitex/plt/_mcp_tool_schemas.py +169 -0
  172. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
  173. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
  174. scitex/plt/gallery/_generate.py +76 -50
  175. scitex/plt/io/__init__.py +17 -19
  176. scitex/plt/io/_bundle.py +99 -52
  177. scitex/plt/io/_layered_bundle.py +303 -168
  178. scitex/plt/mcp_server.py +205 -0
  179. scitex/plt/utils/_csv_column_naming.py +250 -118
  180. scitex/repro/README_RandomStateManager.md +3 -3
  181. scitex/repro/_RandomStateManager.py +14 -14
  182. scitex/repro/_gen_ID.py +1 -1
  183. scitex/repro/_gen_timestamp.py +1 -1
  184. scitex/repro/_hash_array.py +4 -4
  185. scitex/schema/__init__.py +69 -73
  186. scitex/schema/_canvas.py +1 -1
  187. scitex/schema/_stats.py +2 -2
  188. scitex/scholar/__main__.py +24 -2
  189. scitex/scholar/_mcp_handlers.py +685 -0
  190. scitex/scholar/_mcp_tool_schemas.py +339 -0
  191. scitex/scholar/docs/template.py +1 -1
  192. scitex/scholar/examples/07_storage_integration.py +1 -1
  193. scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
  194. scitex/scholar/impact_factor/jcr/build_database.py +1 -1
  195. scitex/scholar/mcp_server.py +315 -0
  196. scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
  197. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
  198. scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
  199. scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
  200. scitex/scholar/storage/PaperIO.py +1 -1
  201. scitex/session/README.md +4 -4
  202. scitex/session/__init__.py +1 -1
  203. scitex/session/_decorator.py +9 -9
  204. scitex/session/_lifecycle.py +5 -5
  205. scitex/session/template.py +1 -1
  206. scitex/stats/__init__.py +30 -33
  207. scitex/stats/__main__.py +281 -0
  208. scitex/stats/_mcp_handlers.py +1191 -0
  209. scitex/stats/_mcp_tool_schemas.py +384 -0
  210. scitex/stats/_schema.py +1 -1
  211. scitex/stats/correct/_correct_bonferroni.py +1 -1
  212. scitex/stats/correct/_correct_fdr.py +1 -1
  213. scitex/stats/correct/_correct_fdr_.py +1 -1
  214. scitex/stats/correct/_correct_holm.py +1 -1
  215. scitex/stats/correct/_correct_sidak.py +1 -1
  216. scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
  217. scitex/stats/effect_sizes/_cohens_d.py +1 -1
  218. scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
  219. scitex/stats/effect_sizes/_eta_squared.py +1 -1
  220. scitex/stats/effect_sizes/_prob_superiority.py +1 -1
  221. scitex/stats/io/__init__.py +10 -11
  222. scitex/stats/io/_bundle.py +16 -16
  223. scitex/stats/mcp_server.py +405 -0
  224. scitex/stats/posthoc/_dunnett.py +1 -1
  225. scitex/stats/posthoc/_games_howell.py +1 -1
  226. scitex/stats/posthoc/_tukey_hsd.py +1 -1
  227. scitex/stats/power/_power.py +1 -1
  228. scitex/stats/utils/_effect_size.py +1 -1
  229. scitex/stats/utils/_formatters.py +1 -1
  230. scitex/stats/utils/_power.py +1 -1
  231. scitex/template/_mcp_handlers.py +259 -0
  232. scitex/template/_mcp_tool_schemas.py +112 -0
  233. scitex/template/mcp_server.py +186 -0
  234. scitex/utils/_verify_scitex_format.py +2 -2
  235. scitex/utils/template.py +1 -1
  236. scitex/web/__init__.py +12 -11
  237. scitex/web/_scraping.py +26 -265
  238. scitex/web/download_images.py +316 -0
  239. scitex/writer/Writer.py +1 -1
  240. scitex/writer/_clone_writer_project.py +1 -1
  241. scitex/writer/_validate_tree_structures.py +1 -1
  242. scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
  243. scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
  244. scitex/writer/dataclasses/core/_Document.py +1 -1
  245. scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
  246. scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
  247. scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
  248. scitex/writer/utils/.legacy_git_retry.py +7 -5
  249. scitex/writer/utils/_parse_latex_logs.py +1 -1
  250. scitex-2.13.0.dist-info/METADATA +1231 -0
  251. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/RECORD +376 -470
  252. scitex-2.13.0.dist-info/entry_points.txt +11 -0
  253. scitex/fig/editor/_defaults.py +0 -300
  254. scitex/fig/editor/edit/panel_loader.py +0 -232
  255. scitex/fig/editor/flask_editor/_bbox.py +0 -1299
  256. scitex/fig/editor/flask_editor/_core.py +0 -1429
  257. scitex/fig/editor/flask_editor/_renderer.py +0 -813
  258. scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
  259. scitex/fts/README.md +0 -262
  260. scitex/fts/TODO.md +0 -66
  261. scitex/fts/__init__.py +0 -90
  262. scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
  263. scitex/fts/_bundle/__init__.py +0 -38
  264. scitex/fts/_bundle/_utils/__init__.py +0 -55
  265. scitex/fts/_bundle/_utils/_const.py +0 -26
  266. scitex/fts/_bundle/_utils/_errors.py +0 -73
  267. scitex/fts/_bundle/_utils/_generate.py +0 -21
  268. scitex/fts/_bundle/_utils/_types.py +0 -76
  269. scitex/fts/_bundle/_zipbundle.py +0 -165
  270. scitex/fts/_fig/__init__.py +0 -22
  271. scitex/fts/_fig/_backend/_parser.py +0 -188
  272. scitex/fts/_fig/_editor/__init__.py +0 -14
  273. scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
  274. scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
  275. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
  276. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
  277. scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
  278. scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
  279. scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
  280. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
  281. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
  282. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
  283. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
  284. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
  285. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
  286. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
  287. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
  288. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
  289. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
  290. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
  291. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
  292. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
  293. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
  294. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
  295. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
  296. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
  297. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
  298. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
  299. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
  300. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
  301. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
  302. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
  303. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
  304. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
  305. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
  306. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
  307. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
  308. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
  309. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
  310. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
  311. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
  312. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
  313. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
  314. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
  315. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
  316. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
  317. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
  318. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
  319. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
  320. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
  321. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
  322. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
  323. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
  324. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
  325. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
  326. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
  327. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
  328. scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
  329. scitex/fts/_fig/_models/_Annotations.py +0 -115
  330. scitex/fts/_fig/_models/_Axes.py +0 -152
  331. scitex/fts/_fig/_models/_Figure.py +0 -138
  332. scitex/fts/_fig/_models/_Plot.py +0 -123
  333. scitex/fts/_fig/_utils/_plot_layout.py +0 -397
  334. scitex/fts/_kinds/_figure/_composite.py +0 -345
  335. scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
  336. scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
  337. scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
  338. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
  339. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
  340. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
  341. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
  342. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
  343. scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
  344. scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
  345. scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
  346. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
  347. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
  348. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
  349. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
  350. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
  351. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
  352. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
  353. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
  354. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
  355. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
  356. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
  357. scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
  358. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
  359. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
  360. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
  361. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
  362. scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
  363. scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
  364. scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
  365. scitex/fts/_kinds/_table/_latex/_export.py +0 -279
  366. scitex/fts/_stats/__init__.py +0 -48
  367. scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
  368. scitex/fts/_stats/_dataclasses/__init__.py +0 -48
  369. scitex/fts/_tables/__init__.py +0 -65
  370. scitex/fts/_tables/_latex/__init__.py +0 -93
  371. scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
  372. scitex/fts/_tables/_latex/_editor/_app.py +0 -725
  373. scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
  374. scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
  375. scitex/fts/_tables/_latex/_table_exporter.py +0 -362
  376. scitex/fts/_tables/_latex/_utils.py +0 -369
  377. scitex/fts/_tables/_latex/_validator.py +0 -445
  378. scitex/io/_save_modules/_pltz_bundle.py +0 -356
  379. scitex-2.10.3.dist-info/METADATA +0 -952
  380. scitex-2.10.3.dist-info/entry_points.txt +0 -2
  381. /scitex/{fig → canvas}/README.md +0 -0
  382. /scitex/{fig → canvas}/backend/__init__.py +0 -0
  383. /scitex/{fig → canvas}/backend/_export.py +0 -0
  384. /scitex/{fig → canvas}/backend/_render.py +0 -0
  385. /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
  386. /scitex/{fig → canvas}/editor/__init__.py +0 -0
  387. /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
  388. /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
  389. /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
  390. /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
  391. /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
  392. /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
  393. /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
  394. /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
  395. /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
  396. /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
  397. /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
  398. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
  399. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
  400. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
  401. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
  402. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
  403. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
  404. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
  405. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
  406. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
  407. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
  408. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
  409. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
  410. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
  411. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
  412. /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
  413. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
  414. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
  415. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
  416. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
  417. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
  418. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
  419. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
  420. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
  421. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
  422. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
  423. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
  424. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
  425. /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
  426. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
  427. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
  428. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
  429. /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
  430. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
  431. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
  432. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
  433. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
  434. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
  435. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
  436. /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
  437. /scitex/{fig → canvas}/io/_directory.py +0 -0
  438. /scitex/{fig → canvas}/model/_plot_types.py +0 -0
  439. /scitex/{fig → canvas}/utils/_defaults.py +0 -0
  440. /scitex/{fig → canvas}/utils/_validate.py +0 -0
  441. /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
  442. /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
  443. /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
  444. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
  445. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
  446. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
  447. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
  448. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
  449. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
  450. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
  451. /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
  452. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
  453. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
  454. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
  455. /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
  456. /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
  457. /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
  458. /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
  459. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
  460. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
  461. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
  462. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
  463. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
  464. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
  465. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
  466. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
  467. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
  468. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
  469. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
  470. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
  471. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
  472. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
  473. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
  474. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
  475. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
  476. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
  477. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
  478. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
  479. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
  480. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
  481. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
  482. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
  483. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
  484. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
  485. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
  486. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
  487. /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
  488. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
  489. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
  490. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
  491. /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
  492. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
  493. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
  494. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
  495. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
  496. /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
  497. /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
  498. /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
  499. /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
  500. /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
  501. /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
  502. /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
  503. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
  504. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,664 +0,0 @@
1
- #!/usr/bin/env python3
2
- # File: ./src/scitex/vis/editor/flask_editor/plotter.py
3
- """CSV plotting functionality for Flask editor."""
4
-
5
- from typing import Any, Dict, Optional
6
-
7
- import numpy as np
8
- import pandas as pd
9
-
10
-
11
- def _apply_element_overrides(
12
- kwargs: Dict[str, Any],
13
- element_key: str,
14
- element_overrides: Dict[str, Any],
15
- element_type: str,
16
- ) -> Dict[str, Any]:
17
- """Apply element-specific overrides to kwargs.
18
-
19
- Args:
20
- kwargs: Original kwargs dict
21
- element_key: Key to look up in element_overrides (e.g., 'ax_00_scatter_0')
22
- element_overrides: Dict mapping element keys to their override values
23
- element_type: Type of element ('trace', 'scatter', 'fill', 'bar')
24
-
25
- Returns:
26
- Updated kwargs dict with overrides applied
27
- """
28
- if not element_key or element_key not in element_overrides:
29
- return kwargs
30
-
31
- overrides = element_overrides[element_key]
32
- result = kwargs.copy()
33
-
34
- if element_type == "trace":
35
- # Line/trace overrides: color, linewidth, linestyle, marker, markersize, alpha
36
- if "color" in overrides:
37
- result["color"] = overrides["color"]
38
- if "linewidth" in overrides:
39
- result["linewidth"] = overrides["linewidth"]
40
- if "linestyle" in overrides:
41
- result["linestyle"] = overrides["linestyle"]
42
- if "marker" in overrides and overrides["marker"]:
43
- result["marker"] = overrides["marker"]
44
- if "markersize" in overrides:
45
- result["markersize"] = overrides["markersize"]
46
- if "alpha" in overrides:
47
- result["alpha"] = overrides["alpha"]
48
- if "label" in overrides and overrides["label"]:
49
- result["label"] = overrides["label"]
50
-
51
- elif element_type == "scatter":
52
- # Scatter overrides: color (c), size (s), marker, alpha, edgecolor
53
- if "color" in overrides:
54
- result["c"] = overrides["color"]
55
- # Remove facecolors if present (conflicts with c)
56
- result.pop("facecolors", None)
57
- if "size" in overrides:
58
- result["s"] = overrides["size"]
59
- if "marker" in overrides:
60
- result["marker"] = overrides["marker"]
61
- if "alpha" in overrides:
62
- result["alpha"] = overrides["alpha"]
63
- if "edgecolor" in overrides:
64
- result["edgecolors"] = overrides["edgecolor"]
65
-
66
- elif element_type == "fill":
67
- # Fill overrides: color, alpha
68
- if "color" in overrides:
69
- result["color"] = overrides["color"]
70
- if "alpha" in overrides:
71
- result["alpha"] = overrides["alpha"]
72
-
73
- elif element_type == "bar":
74
- # Bar overrides: facecolor (color), edgecolor, alpha
75
- if "facecolor" in overrides:
76
- result["color"] = overrides["facecolor"]
77
- if "edgecolor" in overrides:
78
- result["edgecolor"] = overrides["edgecolor"]
79
- if "alpha" in overrides:
80
- result["alpha"] = overrides["alpha"]
81
-
82
- return result
83
-
84
-
85
- def plot_from_csv(
86
- ax,
87
- csv_data: Optional[pd.DataFrame],
88
- overrides: Dict[str, Any],
89
- linewidth: float = 1.0,
90
- ):
91
- """Reconstruct plot from CSV data using trace info from overrides.
92
-
93
- Args:
94
- ax: Matplotlib axes object
95
- csv_data: DataFrame containing CSV data
96
- overrides: Dictionary with override settings including traces
97
- linewidth: Default line width in points
98
- """
99
- if csv_data is None or not isinstance(csv_data, pd.DataFrame):
100
- return
101
-
102
- df = csv_data
103
- o = overrides
104
-
105
- # Get legend settings from overrides
106
- legend_fontsize = o.get("legend_fontsize", 6)
107
- legend_visible = o.get("legend_visible", True)
108
- legend_frameon = o.get("legend_frameon", False)
109
- legend_loc = o.get("legend_loc", "best")
110
- legend_x = o.get("legend_x", 0.5)
111
- legend_y = o.get("legend_y", 0.5)
112
-
113
- # Get traces from overrides (which may have been edited by user)
114
- traces = o.get("traces", [])
115
-
116
- if traces:
117
- _plot_with_traces(
118
- ax,
119
- df,
120
- traces,
121
- linewidth,
122
- legend_fontsize,
123
- legend_visible,
124
- legend_frameon,
125
- legend_loc,
126
- legend_x,
127
- legend_y,
128
- )
129
- else:
130
- _plot_fallback(
131
- ax,
132
- df,
133
- linewidth,
134
- legend_fontsize,
135
- legend_visible,
136
- legend_frameon,
137
- legend_loc,
138
- legend_x,
139
- legend_y,
140
- )
141
-
142
-
143
- def plot_from_recipe(
144
- ax,
145
- csv_data: Optional[pd.DataFrame],
146
- ax_spec: Dict[str, Any],
147
- overrides: Dict[str, Any],
148
- linewidth: float = 1.0,
149
- ax_id: str = "",
150
- ):
151
- """Plot from new recipe schema (scitex.plt.figure.recipe).
152
-
153
- Args:
154
- ax: Matplotlib axes object
155
- csv_data: DataFrame containing CSV data
156
- ax_spec: Axis specification from recipe JSON (includes 'calls' list)
157
- overrides: Dictionary with override settings
158
- linewidth: Default line width in points
159
- ax_id: Axis identifier (e.g., 'ax_00') for element override lookup
160
- """
161
- if csv_data is None or not isinstance(csv_data, pd.DataFrame):
162
- return
163
-
164
- df = csv_data
165
- calls = ax_spec.get("calls", [])
166
-
167
- # Get element overrides from overrides dict
168
- element_overrides = overrides.get("element_overrides", {})
169
-
170
- # Track element indices per type for this axis
171
- element_counts = {"trace": 0, "scatter": 0, "fill": 0, "bar": 0}
172
-
173
- for call in calls:
174
- method = call.get("method", "")
175
- data_ref = call.get("data_ref", {})
176
- kwargs = call.get("kwargs", {}).copy() # Copy to avoid modifying original
177
- call_id = call.get("id", "")
178
-
179
- # Build element key for override lookup
180
- element_key = None
181
-
182
- try:
183
- if method == "plot":
184
- element_key = (
185
- f"{ax_id}_trace_{element_counts['trace']}"
186
- if ax_id
187
- else f"trace_{element_counts['trace']}"
188
- )
189
- kwargs = _apply_element_overrides(
190
- kwargs, element_key, element_overrides, "trace"
191
- )
192
- _render_plot(ax, df, data_ref, kwargs, linewidth)
193
- element_counts["trace"] += 1
194
- elif method == "scatter":
195
- element_key = (
196
- f"{ax_id}_scatter_{element_counts['scatter']}"
197
- if ax_id
198
- else f"scatter_{element_counts['scatter']}"
199
- )
200
- kwargs = _apply_element_overrides(
201
- kwargs, element_key, element_overrides, "scatter"
202
- )
203
- _render_scatter(ax, df, data_ref, kwargs)
204
- element_counts["scatter"] += 1
205
- elif method == "bar":
206
- element_key = (
207
- f"{ax_id}_bar_{element_counts['bar']}"
208
- if ax_id
209
- else f"bar_{element_counts['bar']}"
210
- )
211
- kwargs = _apply_element_overrides(
212
- kwargs, element_key, element_overrides, "bar"
213
- )
214
- _render_bar(ax, df, data_ref, kwargs)
215
- element_counts["bar"] += 1
216
- elif method == "fill_between":
217
- element_key = (
218
- f"{ax_id}_fill_{element_counts['fill']}"
219
- if ax_id
220
- else f"fill_{element_counts['fill']}"
221
- )
222
- kwargs = _apply_element_overrides(
223
- kwargs, element_key, element_overrides, "fill"
224
- )
225
- _render_fill_between(ax, df, data_ref, kwargs)
226
- element_counts["fill"] += 1
227
- elif method == "errorbar":
228
- _render_errorbar(ax, df, data_ref, kwargs, linewidth)
229
- elif method == "imshow":
230
- _render_imshow(ax, df, data_ref, kwargs)
231
- elif method == "contour":
232
- _render_contour(ax, df, data_ref, kwargs)
233
- elif method == "contourf":
234
- _render_contourf(ax, df, data_ref, kwargs)
235
- elif method in (
236
- "stx_shaded_line",
237
- "stx_fillv",
238
- "stx_violin",
239
- "stx_box",
240
- "stx_rectangle",
241
- "stx_raster",
242
- ):
243
- _render_stx_method(ax, df, method, data_ref, kwargs)
244
- elif method == "hist":
245
- _render_hist(ax, df, data_ref, kwargs)
246
- elif method == "text":
247
- _render_text(ax, df, data_ref, kwargs)
248
- else:
249
- # Try generic approach for unknown methods
250
- _render_generic(ax, df, method, data_ref, kwargs, linewidth)
251
- except Exception as e:
252
- print(f"Error rendering {method} for {call_id}: {e}")
253
-
254
- # Handle legend
255
- legend_fontsize = overrides.get("legend_fontsize", 6)
256
- legend_visible = overrides.get("legend_visible", True)
257
- legend_frameon = overrides.get("legend_frameon", False)
258
-
259
- if legend_visible:
260
- handles, labels = ax.get_legend_handles_labels()
261
- if handles:
262
- ax.legend(fontsize=legend_fontsize, frameon=legend_frameon)
263
-
264
-
265
- def _get_column_data(df, col_ref: str) -> Optional[np.ndarray]:
266
- """Get column data from DataFrame, handling missing columns gracefully.
267
-
268
- Handles the naming mismatch between JSON data_ref and CSV columns:
269
- - JSON: ax-row-0-col-0_trace-id-ax_00_ch1_variable-x
270
- - CSV: ax-row-0-col-0_trace-id-ch1_variable-x
271
- """
272
- if not col_ref:
273
- return None
274
-
275
- # Direct match
276
- if col_ref in df.columns:
277
- return df[col_ref].dropna().values
278
-
279
- # Try removing ax_XX_ prefix from trace-id portion
280
- # Pattern: ax-row-X-col-Y_trace-id-ax_XX_NAME_variable-Z
281
- # Should become: ax-row-X-col-Y_trace-id-NAME_variable-Z
282
- import re
283
-
284
- simplified = re.sub(r"(trace-id-)ax_\d+_", r"\1", col_ref)
285
- if simplified in df.columns:
286
- return df[simplified].dropna().values
287
-
288
- # Try case variations (lowercase the trace-id part)
289
- simplified_lower = re.sub(
290
- r"(trace-id-)[^_]+", lambda m: m.group(0).lower(), simplified
291
- )
292
- if simplified_lower in df.columns:
293
- return df[simplified_lower].dropna().values
294
-
295
- # Try matching by suffix (variable-x, variable-y, etc.)
296
- suffix_match = re.search(r"_variable-(\w+)$", col_ref)
297
- if suffix_match:
298
- var_suffix = suffix_match.group(0)
299
- # Extract trace-id pattern
300
- trace_match = re.search(r"trace-id-(?:ax_\d+_)?([^_]+)", col_ref)
301
- if trace_match:
302
- trace_name = trace_match.group(1).lower()
303
- for col in df.columns:
304
- if f"trace-id-{trace_name}" in col.lower() and col.endswith(var_suffix):
305
- return df[col].dropna().values
306
-
307
- # Last resort: fuzzy match by ending
308
- for col in df.columns:
309
- # Match if same variable suffix and similar trace pattern
310
- if col_ref.split("_variable-")[-1] == col.split("_variable-")[-1]:
311
- # Check if trace-id portion is similar
312
- ref_trace = re.search(r"trace-id-(?:ax_\d+_)?(.+?)_variable", col_ref)
313
- col_trace = re.search(r"trace-id-(.+?)_variable", col)
314
- if ref_trace and col_trace:
315
- if ref_trace.group(1).lower() == col_trace.group(1).lower():
316
- return df[col].dropna().values
317
-
318
- return None
319
-
320
-
321
- def _render_plot(ax, df, data_ref, kwargs, linewidth):
322
- """Render line plot."""
323
- x_col = data_ref.get("x", "")
324
- y_col = data_ref.get("y", "")
325
-
326
- x = _get_column_data(df, x_col)
327
- y = _get_column_data(df, y_col)
328
-
329
- if x is not None and y is not None and len(x) == len(y):
330
- lw = kwargs.pop("linewidth", linewidth)
331
- ax.plot(x, y, linewidth=lw, **kwargs)
332
-
333
-
334
- def _render_scatter(ax, df, data_ref, kwargs):
335
- """Render scatter plot."""
336
- x_col = data_ref.get("x", "")
337
- y_col = data_ref.get("y", "")
338
-
339
- x = _get_column_data(df, x_col)
340
- y = _get_column_data(df, y_col)
341
-
342
- if x is not None and y is not None and len(x) == len(y):
343
- ax.scatter(x, y, **kwargs)
344
-
345
-
346
- def _render_bar(ax, df, data_ref, kwargs):
347
- """Render bar plot."""
348
- x_col = data_ref.get("x", "")
349
- y_col = data_ref.get("y", "")
350
-
351
- x = _get_column_data(df, x_col)
352
- y = _get_column_data(df, y_col)
353
-
354
- if x is not None and y is not None and len(x) == len(y):
355
- ax.bar(x, y, **kwargs)
356
-
357
-
358
- def _render_fill_between(ax, df, data_ref, kwargs):
359
- """Render fill_between."""
360
- x_col = data_ref.get("x", "")
361
- y1_col = data_ref.get("y1", "")
362
- y2_col = data_ref.get("y2", "")
363
-
364
- x = _get_column_data(df, x_col)
365
- y1 = _get_column_data(df, y1_col)
366
- y2 = _get_column_data(df, y2_col)
367
-
368
- if x is not None and y1 is not None and y2 is not None:
369
- min_len = min(len(x), len(y1), len(y2))
370
- ax.fill_between(x[:min_len], y1[:min_len], y2[:min_len], **kwargs)
371
-
372
-
373
- def _render_errorbar(ax, df, data_ref, kwargs, linewidth):
374
- """Render errorbar plot."""
375
- x_col = data_ref.get("x", "")
376
- y_col = data_ref.get("y", "")
377
- yerr_col = data_ref.get("yerr", "")
378
-
379
- x = _get_column_data(df, x_col)
380
- y = _get_column_data(df, y_col)
381
- yerr = _get_column_data(df, yerr_col) if yerr_col else None
382
-
383
- if x is not None and y is not None and len(x) == len(y):
384
- ax.errorbar(x, y, yerr=yerr, linewidth=linewidth, **kwargs)
385
-
386
-
387
- def _render_imshow(ax, df, data_ref, kwargs):
388
- """Render imshow (heatmap)."""
389
- data_col = data_ref.get("data", "")
390
- # For imshow, data is typically in a special format - try to reconstruct
391
- # Look for row/col/value columns
392
- row_col = data_ref.get("row", "")
393
- col_col = data_ref.get("col", "")
394
- value_col = data_ref.get("value", "")
395
-
396
- if row_col and col_col and value_col:
397
- rows = _get_column_data(df, row_col)
398
- cols = _get_column_data(df, col_col)
399
- values = _get_column_data(df, value_col)
400
-
401
- if rows is not None and cols is not None and values is not None:
402
- # Reconstruct 2D array
403
- n_rows = int(rows.max()) + 1
404
- n_cols = int(cols.max()) + 1
405
- data = np.zeros((n_rows, n_cols))
406
- for r, c, v in zip(rows.astype(int), cols.astype(int), values):
407
- data[r, c] = v
408
- ax.imshow(data, **kwargs)
409
-
410
-
411
- def _render_contour(ax, df, data_ref, kwargs):
412
- """Render contour plot."""
413
- x_col = data_ref.get("x", "")
414
- y_col = data_ref.get("y", "")
415
- z_col = data_ref.get("z", "")
416
-
417
- x = _get_column_data(df, x_col)
418
- y = _get_column_data(df, y_col)
419
- z = _get_column_data(df, z_col)
420
-
421
- if x is not None and y is not None and z is not None:
422
- # Assume data is on a grid - reconstruct
423
- n = int(np.sqrt(len(x)))
424
- if n * n == len(x):
425
- X = x.reshape(n, n)
426
- Y = y.reshape(n, n)
427
- Z = z.reshape(n, n)
428
- ax.contour(X, Y, Z, **kwargs)
429
-
430
-
431
- def _render_contourf(ax, df, data_ref, kwargs):
432
- """Render filled contour plot."""
433
- x_col = data_ref.get("x", "")
434
- y_col = data_ref.get("y", "")
435
- z_col = data_ref.get("z", "")
436
-
437
- x = _get_column_data(df, x_col)
438
- y = _get_column_data(df, y_col)
439
- z = _get_column_data(df, z_col)
440
-
441
- if x is not None and y is not None and z is not None:
442
- # Assume data is on a grid - reconstruct
443
- n = int(np.sqrt(len(x)))
444
- if n * n == len(x):
445
- X = x.reshape(n, n)
446
- Y = y.reshape(n, n)
447
- Z = z.reshape(n, n)
448
- ax.contourf(X, Y, Z, **kwargs)
449
-
450
-
451
- def _render_stx_method(ax, df, method, data_ref, kwargs):
452
- """Render scitex-specific methods (shaded_line, fillv, etc.)."""
453
- # These are custom methods - for now, skip or implement basic versions
454
- if method == "stx_shaded_line":
455
- x_col = data_ref.get("x", "")
456
- y_lower_col = data_ref.get("y_lower", "")
457
- y_middle_col = data_ref.get("y_middle", "")
458
- y_upper_col = data_ref.get("y_upper", "")
459
-
460
- x = _get_column_data(df, x_col)
461
- y_lower = _get_column_data(df, y_lower_col)
462
- y_middle = _get_column_data(df, y_middle_col)
463
- y_upper = _get_column_data(df, y_upper_col)
464
-
465
- if all(v is not None for v in [x, y_lower, y_middle, y_upper]):
466
- min_len = min(len(x), len(y_lower), len(y_middle), len(y_upper))
467
- ax.fill_between(
468
- x[:min_len],
469
- y_lower[:min_len],
470
- y_upper[:min_len],
471
- alpha=0.3,
472
- **{k: v for k, v in kwargs.items() if k not in ["linewidth"]},
473
- )
474
- ax.plot(x[:min_len], y_middle[:min_len], **kwargs)
475
-
476
-
477
- def _render_hist(ax, df, data_ref, kwargs):
478
- """Render histogram."""
479
- data_col = data_ref.get("data", data_ref.get("x", ""))
480
- data = _get_column_data(df, data_col)
481
- if data is not None:
482
- ax.hist(data, **kwargs)
483
-
484
-
485
- def _render_text(ax, df, data_ref, kwargs):
486
- """Render text annotation."""
487
- x_col = data_ref.get("x", "")
488
- y_col = data_ref.get("y", "")
489
- content_col = data_ref.get("content", "")
490
-
491
- x = _get_column_data(df, x_col)
492
- y = _get_column_data(df, y_col)
493
-
494
- if x is not None and y is not None and len(x) > 0:
495
- # Get text content from CSV or kwargs
496
- text = kwargs.pop("text", "")
497
- if not text and content_col:
498
- content = _get_column_data(df, content_col)
499
- if content is not None and len(content) > 0:
500
- text = str(content[0])
501
- ax.text(x[0], y[0], text, **kwargs)
502
-
503
-
504
- def _render_generic(ax, df, method, data_ref, kwargs, linewidth):
505
- """Try to render using generic approach."""
506
- # For unknown methods, try to get x/y data and plot as line
507
- x_col = data_ref.get("x", "")
508
- y_col = data_ref.get("y", "")
509
-
510
- x = _get_column_data(df, x_col)
511
- y = _get_column_data(df, y_col)
512
-
513
- if x is not None and y is not None and len(x) == len(y):
514
- # Filter out kwargs that are not valid for ax.plot()
515
- invalid_plot_kwargs = {
516
- "levels",
517
- "extend",
518
- "origin",
519
- "extent",
520
- "aspect",
521
- "norm",
522
- "vmin",
523
- "vmax",
524
- "interpolation",
525
- "filternorm",
526
- "filterrad",
527
- "resample",
528
- "bins",
529
- "range",
530
- "density",
531
- "weights",
532
- "cumulative",
533
- "bottom",
534
- "histtype",
535
- "align",
536
- "orientation",
537
- "rwidth",
538
- "log",
539
- "stacked",
540
- "data",
541
- "width",
542
- "height",
543
- "edgecolors",
544
- "s",
545
- "c",
546
- "facecolors",
547
- }
548
- filtered_kwargs = {
549
- k: v for k, v in kwargs.items() if k not in invalid_plot_kwargs
550
- }
551
- ax.plot(x, y, linewidth=linewidth, **filtered_kwargs)
552
-
553
-
554
- def _plot_with_traces(
555
- ax,
556
- df,
557
- traces,
558
- linewidth,
559
- legend_fontsize,
560
- legend_visible,
561
- legend_frameon,
562
- legend_loc,
563
- legend_x,
564
- legend_y,
565
- ):
566
- """Plot using trace information from overrides."""
567
- for trace in traces:
568
- # Support both old format (csv_columns.x/y) and new format (x_col/y_col)
569
- csv_cols = trace.get("csv_columns", {})
570
- x_col = csv_cols.get("x") or trace.get("x_col")
571
- y_col = csv_cols.get("y") or trace.get("y_col")
572
-
573
- if x_col and y_col and x_col in df.columns and y_col in df.columns:
574
- ax.plot(
575
- df[x_col],
576
- df[y_col],
577
- label=trace.get("label", trace.get("id", "")),
578
- color=trace.get("color"),
579
- linestyle=trace.get("linestyle", "-"),
580
- linewidth=trace.get("linewidth", linewidth),
581
- marker=trace.get("marker", None),
582
- markersize=trace.get("markersize", 6),
583
- )
584
-
585
- # Add legend if there are labeled traces
586
- if legend_visible and any(t.get("label") for t in traces):
587
- _add_legend(ax, legend_fontsize, legend_frameon, legend_loc, legend_x, legend_y)
588
-
589
-
590
- def _plot_fallback(
591
- ax,
592
- df,
593
- linewidth,
594
- legend_fontsize,
595
- legend_visible,
596
- legend_frameon,
597
- legend_loc,
598
- legend_x,
599
- legend_y,
600
- ):
601
- """Fallback plotting when no trace info available - smart parsing of column names."""
602
- cols = df.columns.tolist()
603
-
604
- # Group columns by trace ID
605
- trace_groups = {}
606
- for col in cols:
607
- if col.endswith("_x"):
608
- trace_id = col[:-2] # Remove '_x'
609
- y_col = trace_id + "_y"
610
- if y_col in cols:
611
- # Extract label from column name (e.g., ax_00_sine_plot -> sine)
612
- parts = trace_id.split("_")
613
- label = parts[2] if len(parts) > 2 else trace_id
614
- trace_groups[trace_id] = {
615
- "x_col": col,
616
- "y_col": y_col,
617
- "label": label,
618
- }
619
-
620
- if trace_groups:
621
- for trace_id, info in trace_groups.items():
622
- ax.plot(
623
- df[info["x_col"]],
624
- df[info["y_col"]],
625
- label=info["label"],
626
- linewidth=linewidth,
627
- )
628
- if legend_visible:
629
- _add_legend(
630
- ax, legend_fontsize, legend_frameon, legend_loc, legend_x, legend_y
631
- )
632
-
633
- elif len(cols) >= 2:
634
- # Last resort: assume first column is x, rest are y
635
- x_col = cols[0]
636
- for y_col in cols[1:]:
637
- try:
638
- ax.plot(df[x_col], df[y_col], label=str(y_col), linewidth=linewidth)
639
- except Exception:
640
- pass
641
- if len(cols) > 2 and legend_visible:
642
- _add_legend(
643
- ax, legend_fontsize, legend_frameon, legend_loc, legend_x, legend_y
644
- )
645
-
646
-
647
- def _add_legend(ax, fontsize, frameon, loc, x, y):
648
- """Add legend to axes with specified settings."""
649
- if loc == "custom":
650
- ax.legend(
651
- fontsize=fontsize,
652
- frameon=frameon,
653
- loc="upper left",
654
- bbox_to_anchor=(x, y),
655
- )
656
- else:
657
- ax.legend(
658
- fontsize=fontsize,
659
- frameon=frameon,
660
- loc=loc,
661
- )
662
-
663
-
664
- # EOF