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,314 +0,0 @@
1
- /**
2
- * Axis-Based Alignment
3
- * Scientific plot alignment using axes bounding boxes
4
- */
5
-
6
- // ============================================================================
7
- // Get Axes Bbox for Panel
8
- // ============================================================================
9
- function getAxesBboxForPanel(panelName) {
10
- const cache = panelBboxesCache[panelName];
11
- if (!cache || !cache.bboxes) return null;
12
-
13
- const bboxes = cache.bboxes;
14
-
15
- // Method 1: Look for ax_00_panel, ax_01_panel, etc.
16
- for (const key of Object.keys(bboxes)) {
17
- if (key.endsWith('_panel') && key.startsWith('ax_')) {
18
- const bbox = bboxes[key];
19
- if (bbox && bbox.x0 !== undefined) {
20
- return {
21
- x0: bbox.x0,
22
- y0: bbox.y0,
23
- x1: bbox.x1,
24
- y1: bbox.y1,
25
- key: key
26
- };
27
- }
28
- }
29
- }
30
-
31
- // Method 2: Calculate axes bbox from spine bboxes (xaxis_spine + yaxis_spine)
32
- // This is the common case for matplotlib figures
33
- let xSpine = null, ySpine = null;
34
- for (const key of Object.keys(bboxes)) {
35
- if (key.endsWith('_xaxis_spine') && key.startsWith('ax_')) {
36
- xSpine = bboxes[key];
37
- }
38
- if (key.endsWith('_yaxis_spine') && key.startsWith('ax_')) {
39
- ySpine = bboxes[key];
40
- }
41
- }
42
-
43
- if (xSpine && ySpine) {
44
- // Combine spine bboxes to get axes area
45
- // Y-spine defines left edge, X-spine defines bottom edge
46
- const x0 = ySpine.x0 !== undefined ? ySpine.x0 : ySpine.x;
47
- const y0 = ySpine.y0 !== undefined ? ySpine.y0 : ySpine.y;
48
- const x1 = xSpine.x1 !== undefined ? xSpine.x1 : (xSpine.x + xSpine.width);
49
- const y1 = xSpine.y1 !== undefined ? xSpine.y1 : (xSpine.y + xSpine.height);
50
-
51
- return {
52
- x0: Math.min(x0, xSpine.x0 || xSpine.x || x0),
53
- y0: Math.min(y0, xSpine.y0 || xSpine.y || y0),
54
- x1: Math.max(x1, ySpine.x1 || (ySpine.x + ySpine.width) || x1),
55
- y1: Math.max(y1, ySpine.y1 || (ySpine.y + ySpine.height) || y1),
56
- key: 'derived_from_spines'
57
- };
58
- }
59
-
60
- // Method 3: Fallback to _meta.axes_bbox_px for single-axes plots
61
- if (bboxes._meta && bboxes._meta.axes_bbox_px) {
62
- const axBbox = bboxes._meta.axes_bbox_px;
63
- return {
64
- x0: axBbox.x0 || axBbox.x,
65
- y0: axBbox.y0 || axBbox.y,
66
- x1: axBbox.x1 || (axBbox.x + axBbox.width),
67
- y1: axBbox.y1 || (axBbox.y + axBbox.height),
68
- key: '_meta.axes_bbox_px'
69
- };
70
- }
71
-
72
- return null;
73
- }
74
-
75
- // ============================================================================
76
- // Calculate Axis Edge Offset
77
- // ============================================================================
78
- function getAxisEdgeOffset(panel, axesBbox, edge, imgSize) {
79
- if (!axesBbox || !imgSize) return 0;
80
-
81
- // Scale factor from image pixels to displayed panel pixels
82
- const panelEl = panel;
83
- const displayWidth = panelEl.offsetWidth;
84
- const displayHeight = panelEl.offsetHeight;
85
- const scaleX = displayWidth / imgSize.width;
86
- const scaleY = displayHeight / imgSize.height;
87
-
88
- switch(edge) {
89
- case 'left':
90
- // Y-axis left edge
91
- return axesBbox.x0 * scaleX;
92
- case 'right':
93
- // Right edge of axes
94
- return axesBbox.x1 * scaleX;
95
- case 'top':
96
- // Top edge of axes
97
- return axesBbox.y0 * scaleY;
98
- case 'bottom':
99
- // X-axis bottom edge
100
- return axesBbox.y1 * scaleY;
101
- case 'center-h':
102
- // Horizontal center of axes
103
- return ((axesBbox.x0 + axesBbox.x1) / 2) * scaleX;
104
- case 'center-v':
105
- // Vertical center of axes
106
- return ((axesBbox.y0 + axesBbox.y1) / 2) * scaleY;
107
- default:
108
- return 0;
109
- }
110
- }
111
-
112
- // ============================================================================
113
- // Align Panels by Axis
114
- // ============================================================================
115
- function alignPanelsByAxis(edge) {
116
- // Use selected panels only
117
- const panels = Array.from(document.querySelectorAll('.panel-canvas-item.selected'));
118
- if (panels.length < 2) {
119
- setStatus('Select at least 2 panels for axis alignment', true);
120
- return;
121
- }
122
-
123
- // Collect panel info with axes bboxes
124
- const panelInfos = [];
125
- for (const panel of panels) {
126
- const panelName = panel.dataset.panelName;
127
- const cache = panelBboxesCache[panelName];
128
- const axesBbox = getAxesBboxForPanel(panelName);
129
-
130
- if (!axesBbox || !cache) {
131
- console.warn(`Panel ${panelName}: no axes bbox found`);
132
- continue;
133
- }
134
-
135
- const currentPos = panelPositions[panelName];
136
- const axisOffset = getAxisEdgeOffset(panel, axesBbox, edge, cache.imgSize);
137
-
138
- panelInfos.push({
139
- panel,
140
- panelName,
141
- axesBbox,
142
- imgSize: cache.imgSize,
143
- currentPos,
144
- axisOffset
145
- });
146
- }
147
-
148
- if (panelInfos.length < 2) {
149
- setStatus('Not enough panels with axes info', true);
150
- return;
151
- }
152
-
153
- // Calculate target position - use the first panel's axis position as reference
154
- const referenceInfo = panelInfos[0];
155
- const referenceAxisPos = referenceInfo.currentPos.x + (edge.includes('h') || edge === 'left' || edge === 'right' ? referenceInfo.axisOffset : 0);
156
- const referenceAxisPosY = referenceInfo.currentPos.y + (edge.includes('v') || edge === 'top' || edge === 'bottom' ? referenceInfo.axisOffset : 0);
157
-
158
- if (edge === 'left' || edge === 'right' || edge === 'center-h') {
159
- // Align horizontally (match X positions of axis edges)
160
- // Target = first panel's axis X position in canvas coords
161
- for (const info of panelInfos) {
162
- const newX = referenceAxisPos - info.axisOffset;
163
- info.currentPos.x = newX;
164
- info.panel.style.left = newX + 'px';
165
- panelLayoutMm[info.panelName].x_mm = newX / canvasScale;
166
- }
167
- } else {
168
- // Align vertically (match Y positions of axis edges)
169
- // Target = first panel's axis Y position in canvas coords
170
- for (const info of panelInfos) {
171
- const newY = referenceAxisPosY - info.axisOffset;
172
- info.currentPos.y = newY;
173
- info.panel.style.top = newY + 'px';
174
- panelLayoutMm[info.panelName].y_mm = newY / canvasScale;
175
- }
176
- }
177
-
178
- // Update layout data
179
- updatePanelLayoutFromDOM();
180
- layoutModified = true;
181
- }
182
-
183
- // ============================================================================
184
- // Stack Panels Vertically
185
- // ============================================================================
186
- function stackPanelsVertically() {
187
- // Use selected panels only
188
- const panels = Array.from(document.querySelectorAll('.panel-canvas-item.selected'));
189
- if (panels.length < 2) {
190
- setStatus('Select at least 2 panels for stacking', true);
191
- return;
192
- }
193
-
194
- // Collect panel info with axes bboxes
195
- const panelInfos = [];
196
- for (const panel of panels) {
197
- const panelName = panel.dataset.panelName;
198
- const cache = panelBboxesCache[panelName];
199
- const axesBbox = getAxesBboxForPanel(panelName);
200
-
201
- if (!axesBbox || !cache) continue;
202
-
203
- const currentPos = panelPositions[panelName];
204
- const axisOffsetLeft = getAxisEdgeOffset(panel, axesBbox, 'left', cache.imgSize);
205
-
206
- panelInfos.push({
207
- panel,
208
- panelName,
209
- axesBbox,
210
- imgSize: cache.imgSize,
211
- currentPos,
212
- axisOffsetLeft,
213
- height: panel.offsetHeight
214
- });
215
- }
216
-
217
- if (panelInfos.length < 2) return;
218
-
219
- // Sort by current vertical position
220
- panelInfos.sort((a, b) => a.currentPos.y - b.currentPos.y);
221
-
222
- // Use first panel as reference for Y-axis alignment
223
- const referenceAxisX = panelInfos[0].currentPos.x + panelInfos[0].axisOffsetLeft;
224
-
225
- // Stack panels vertically with small gap, aligned by Y-axis
226
- const gap = 10; // pixels
227
- let currentY = panelInfos[0].currentPos.y;
228
-
229
- for (const info of panelInfos) {
230
- // Align Y-axis (left edge of axes)
231
- const newX = referenceAxisX - info.axisOffsetLeft;
232
- info.currentPos.x = newX;
233
- info.panel.style.left = newX + 'px';
234
-
235
- // Stack vertically
236
- info.currentPos.y = currentY;
237
- info.panel.style.top = currentY + 'px';
238
- currentY += info.height + gap;
239
- }
240
-
241
- // Update layout data
242
- updatePanelLayoutFromDOM();
243
- layoutModified = true;
244
- }
245
-
246
- // ============================================================================
247
- // Axis Alignment Shortcut Handler
248
- // ============================================================================
249
- function handleAlignByAxisShortcut(key) {
250
- const panels = document.querySelectorAll('.panel-canvas-item');
251
- if (panels.length < 2) {
252
- setStatus('Need multiple panels for axis alignment', true);
253
- return;
254
- }
255
-
256
- const dirNames = {
257
- 'l': 'Y-axis (left edge)',
258
- 'r': 'Right edge',
259
- 't': 'Top edge',
260
- 'b': 'X-axis (bottom edge)',
261
- 'c': 'Center horizontal',
262
- 'm': 'Center vertical',
263
- 's': 'Stacked vertically'
264
- };
265
-
266
- switch(key) {
267
- case 'l': alignPanelsByAxis('left'); break; // Y-axis left
268
- case 'r': alignPanelsByAxis('right'); break; // Right edge
269
- case 't': alignPanelsByAxis('top'); break; // Top edge
270
- case 'b': alignPanelsByAxis('bottom'); break; // X-axis bottom
271
- case 'c': alignPanelsByAxis('center-h'); break; // Horizontal center
272
- case 'm': alignPanelsByAxis('center-v'); break; // Vertical center
273
- case 's': stackPanelsVertically(); break; // Stack with Y-axis alignment
274
- default:
275
- setStatus('Unknown axis key: ' + key + '. Use L/R/T/B/C/M/S', true);
276
- return;
277
- }
278
- if (dirNames[key]) {
279
- setStatus(`Aligned by axis: ${dirNames[key]}`, false);
280
- }
281
- }
282
-
283
- // ============================================================================
284
- // Panel Movement (Arrow Keys)
285
- // ============================================================================
286
- function moveSelectedPanel(direction, amountMm) {
287
- const selected = document.querySelector('.panel-canvas-item.selected');
288
- if (!selected) return;
289
-
290
- const panelName = selected.dataset.panelName;
291
- const pos = panelPositions[panelName];
292
- if (!pos) return;
293
-
294
- switch(direction) {
295
- case 'left': pos.x -= amountMm * canvasScale; break;
296
- case 'right': pos.x += amountMm * canvasScale; break;
297
- case 'up': pos.y -= amountMm * canvasScale; break;
298
- case 'down': pos.y += amountMm * canvasScale; break;
299
- }
300
-
301
- // Update position in pixels (canvasScale = px/mm)
302
- selected.style.left = pos.x + 'px';
303
- selected.style.top = pos.y + 'px';
304
-
305
- // Update layout data
306
- panelLayoutMm[panelName] = {
307
- ...panelLayoutMm[panelName],
308
- x_mm: pos.x / canvasScale,
309
- y_mm: pos.y / canvasScale
310
- };
311
-
312
- layoutModified = true;
313
- setStatus(`Moved ${panelName} ${direction} by ${amountMm}mm`);
314
- }
@@ -1,107 +0,0 @@
1
- /**
2
- * Basic Panel Alignment
3
- * Bounding box-based alignment (non-scientific)
4
- */
5
-
6
- // ============================================================================
7
- // Basic Alignment (by bounding box)
8
- // ============================================================================
9
- function alignPanels(mode) {
10
- const selectedPanels = getSelectedPanels();
11
- if (selectedPanels.length < 2) return;
12
-
13
- // Get bounds
14
- let targetValue;
15
- switch(mode) {
16
- case 'left':
17
- targetValue = Math.min(...selectedPanels.map(p => p.pos.x));
18
- selectedPanels.forEach(p => {
19
- p.pos.x = targetValue;
20
- p.item.style.left = targetValue + 'px';
21
- });
22
- break;
23
- case 'right':
24
- targetValue = Math.max(...selectedPanels.map(p => p.pos.x + p.pos.width));
25
- selectedPanels.forEach(p => {
26
- p.pos.x = targetValue - p.pos.width;
27
- p.item.style.left = p.pos.x + 'px';
28
- });
29
- break;
30
- case 'top':
31
- targetValue = Math.min(...selectedPanels.map(p => p.pos.y));
32
- selectedPanels.forEach(p => {
33
- p.pos.y = targetValue;
34
- p.item.style.top = targetValue + 'px';
35
- });
36
- break;
37
- case 'bottom':
38
- targetValue = Math.max(...selectedPanels.map(p => p.pos.y + p.pos.height));
39
- selectedPanels.forEach(p => {
40
- p.pos.y = targetValue - p.pos.height;
41
- p.item.style.top = p.pos.y + 'px';
42
- });
43
- break;
44
- case 'center-h':
45
- const avgX = selectedPanels.reduce((sum, p) => sum + p.pos.x + p.pos.width/2, 0) / selectedPanels.length;
46
- selectedPanels.forEach(p => {
47
- p.pos.x = avgX - p.pos.width/2;
48
- p.item.style.left = p.pos.x + 'px';
49
- });
50
- break;
51
- case 'center-v':
52
- const avgY = selectedPanels.reduce((sum, p) => sum + p.pos.y + p.pos.height/2, 0) / selectedPanels.length;
53
- selectedPanels.forEach(p => {
54
- p.pos.y = avgY - p.pos.height/2;
55
- p.item.style.top = p.pos.y + 'px';
56
- });
57
- break;
58
- }
59
-
60
- // Update layout data
61
- updatePanelLayoutFromDOM();
62
- layoutModified = true;
63
- setStatus(`Aligned panels: ${mode}`);
64
- }
65
-
66
- // ============================================================================
67
- // Alignment Shortcut Handler
68
- // ============================================================================
69
- function handleAlignShortcut(key, isShift) {
70
- const panels = document.querySelectorAll('.panel-canvas-item');
71
- if (panels.length < 2) {
72
- setStatus('Need multiple panels for alignment', true);
73
- return;
74
- }
75
-
76
- switch(key) {
77
- case 'l': alignPanels('left'); break;
78
- case 'r': alignPanels('right'); break;
79
- case 't': alignPanels('top'); break;
80
- case 'b': alignPanels('bottom'); break;
81
- case 'c': alignPanels('center-h'); break;
82
- case 'm': alignPanels('center-v'); break;
83
- case 'h': distributePanels('horizontal'); break;
84
- case 'v': distributePanels('vertical'); break;
85
- default:
86
- setStatus('Unknown alignment key: ' + key, true);
87
- }
88
- }
89
-
90
- // ============================================================================
91
- // Z-Order Management
92
- // ============================================================================
93
- function bringPanelToFront() {
94
- const selected = document.querySelector('.panel-canvas-item.selected');
95
- if (selected) {
96
- selected.style.zIndex = (parseInt(selected.style.zIndex || 0) + 1).toString();
97
- setStatus('Brought panel to front');
98
- }
99
- }
100
-
101
- function sendPanelToBack() {
102
- const selected = document.querySelector('.panel-canvas-item.selected');
103
- if (selected) {
104
- selected.style.zIndex = (parseInt(selected.style.zIndex || 0) - 1).toString();
105
- setStatus('Sent panel to back');
106
- }
107
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Panel Distribution
3
- * Evenly distribute panels horizontally or vertically
4
- */
5
-
6
- // ============================================================================
7
- // Distribute Panels
8
- // ============================================================================
9
- function distributePanels(direction) {
10
- const selectedPanels = getSelectedPanels();
11
- if (selectedPanels.length < 3) {
12
- setStatus('Need at least 3 panels for distribution', true);
13
- return;
14
- }
15
-
16
- if (direction === 'horizontal') {
17
- // Sort by X position
18
- selectedPanels.sort((a, b) => a.pos.x - b.pos.x);
19
-
20
- const first = selectedPanels[0];
21
- const last = selectedPanels[selectedPanels.length - 1];
22
- const totalSpace = (last.pos.x + last.pos.width) - first.pos.x;
23
- const totalPanelWidth = selectedPanels.reduce((sum, p) => sum + p.pos.width, 0);
24
- const gap = (totalSpace - totalPanelWidth) / (selectedPanels.length - 1);
25
-
26
- let currentX = first.pos.x;
27
- selectedPanels.forEach(p => {
28
- p.pos.x = currentX;
29
- p.item.style.left = currentX + 'px';
30
- currentX += p.pos.width + gap;
31
- });
32
- } else {
33
- // Sort by Y position
34
- selectedPanels.sort((a, b) => a.pos.y - b.pos.y);
35
-
36
- const first = selectedPanels[0];
37
- const last = selectedPanels[selectedPanels.length - 1];
38
- const totalSpace = (last.pos.y + last.pos.height) - first.pos.y;
39
- const totalPanelHeight = selectedPanels.reduce((sum, p) => sum + p.pos.height, 0);
40
- const gap = (totalSpace - totalPanelHeight) / (selectedPanels.length - 1);
41
-
42
- let currentY = first.pos.y;
43
- selectedPanels.forEach(p => {
44
- p.pos.y = currentY;
45
- p.item.style.top = currentY + 'px';
46
- currentY += p.pos.height + gap;
47
- });
48
- }
49
-
50
- // Update layout data
51
- updatePanelLayoutFromDOM();
52
- layoutModified = true;
53
- setStatus(`Distributed panels ${direction}ly`);
54
- }
@@ -1,172 +0,0 @@
1
- /**
2
- * Canvas View Management
3
- * Handles the unified canvas view for multi-panel figures
4
- */
5
-
6
- // ============================================================================
7
- // Canvas Mode Control
8
- // ============================================================================
9
- function setCanvasMode(mode) {
10
- canvasMode = mode;
11
- document.getElementById('canvas-grid').classList.toggle('canvas-mode', mode === 'canvas');
12
- document.getElementById('canvas-grid').classList.toggle('grid-mode', mode === 'grid');
13
- }
14
-
15
- // ============================================================================
16
- // Canvas Rendering
17
- // ============================================================================
18
- function renderCanvasView() {
19
- const container = document.getElementById('canvas-grid');
20
- container.innerHTML = '';
21
-
22
- // Fetch panels if not cached
23
- if (!panelData || !panelData.panels) {
24
- return;
25
- }
26
-
27
- if (canvasMode === 'canvas') {
28
- // Calculate canvas size based on number of panels
29
- const panels = panelData.panels;
30
-
31
- panels.forEach((panel, idx) => {
32
- const item = document.createElement('div');
33
- item.className = 'panel-canvas-item';
34
- item.dataset.panelName = panel.name;
35
-
36
- // Initialize position if not set
37
- if (!panelPositions[panel.name]) {
38
- panelPositions[panel.name] = {
39
- x: idx * 150,
40
- y: idx * 150,
41
- width: panel.width_px || 400,
42
- height: panel.height_px || 300
43
- };
44
- }
45
-
46
- const pos = panelPositions[panel.name];
47
- item.style.left = pos.x + 'px';
48
- item.style.top = pos.y + 'px';
49
- item.style.width = pos.width + 'px';
50
- item.style.height = pos.height + 'px';
51
-
52
- item.innerHTML = `
53
- <div class="panel-drag-handle">☰</div>
54
- <div class="panel-label">${panel.name}</div>
55
- <img src="data:image/png;base64,${panel.image_base64}" style="width: 100%; height: 100%; object-fit: contain;">
56
- <canvas class="panel-overlay"></canvas>
57
- `;
58
-
59
- container.appendChild(item);
60
-
61
- // Double-click to edit
62
- item.addEventListener('dblclick', () => {
63
- loadPanelForEditing(panel.name);
64
- });
65
-
66
- // Drag start
67
- initPanelDrag(item, panel.name);
68
- });
69
-
70
- // Update canvas height to fit all panels
71
- updateCanvasSize();
72
- } else {
73
- // Grid mode - use CSS grid layout (simpler)
74
- loadPanelGrid();
75
- }
76
- }
77
-
78
- // ============================================================================
79
- // Interactive Element Detection Helper
80
- // ============================================================================
81
- function isInteractiveElement(target) {
82
- // SVG paths with hover-path class are interactive elements
83
- if (target.classList && target.classList.contains('hover-path')) {
84
- return true;
85
- }
86
- // Check parent elements for hover-path (click might be on child)
87
- let parent = target.parentElement;
88
- while (parent) {
89
- if (parent.tagName === 'path' || parent.classList.contains('hover-path')) {
90
- // Path elements in SVG overlay are interactive
91
- return true;
92
- }
93
- parent = parent.parentElement;
94
- }
95
- return false;
96
- }
97
-
98
- // ============================================================================
99
- // Canvas Size Management
100
- // ============================================================================
101
- function updateCanvasSize() {
102
- // Find the maximum extent of all panels
103
- let maxX = 0;
104
- let maxY = 0;
105
-
106
- Object.values(panelPositions).forEach(pos => {
107
- maxX = Math.max(maxX, pos.x + pos.width);
108
- maxY = Math.max(maxY, pos.y + pos.height);
109
- });
110
-
111
- // Add some padding
112
- const container = document.getElementById('canvas-grid');
113
- if (container && canvasMode === 'canvas') {
114
- container.style.minHeight = (maxY + 100) + 'px';
115
- container.style.minWidth = (maxX + 100) + 'px';
116
- }
117
- }
118
-
119
- // ============================================================================
120
- // Canvas Zoom Functions
121
- // ============================================================================
122
- function zoomCanvas(factor) {
123
- canvasZoom = Math.max(0.1, Math.min(5.0, canvasZoom * factor));
124
- const container = document.getElementById('canvas-grid');
125
- if (container) {
126
- container.style.transform = `scale(${canvasZoom})`;
127
- container.style.transformOrigin = 'top left';
128
- }
129
- }
130
-
131
- function fitCanvasToWindow() {
132
- const container = document.getElementById('canvas-grid');
133
- if (!container) return;
134
-
135
- const containerWidth = container.scrollWidth;
136
- const windowWidth = window.innerWidth - 400; // Account for side panels
137
- canvasZoom = Math.min(1.0, windowWidth / containerWidth);
138
- container.style.transform = `scale(${canvasZoom})`;
139
- container.style.transformOrigin = 'top left';
140
- }
141
-
142
- function resizeCanvas(factor) {
143
- const container = document.getElementById('canvas-grid');
144
- if (!container) return;
145
-
146
- // Scale all panel positions and sizes
147
- Object.keys(panelPositions).forEach(name => {
148
- const pos = panelPositions[name];
149
- pos.x *= factor;
150
- pos.y *= factor;
151
- pos.width *= factor;
152
- pos.height *= factor;
153
- });
154
-
155
- renderCanvasView();
156
- }
157
-
158
- // ============================================================================
159
- // Panel Layout Update from DOM
160
- // ============================================================================
161
- function updatePanelLayoutFromDOM() {
162
- document.querySelectorAll('.panel-canvas-item').forEach(item => {
163
- const name = item.dataset.panelName;
164
- const rect = item.getBoundingClientRect();
165
- panelPositions[name] = {
166
- x: parseFloat(item.style.left),
167
- y: parseFloat(item.style.top),
168
- width: rect.width,
169
- height: rect.height
170
- };
171
- });
172
- }