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
scitex/cli/capture.py ADDED
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SciTeX CLI - Capture Commands (Screenshot/Monitoring)
4
+
5
+ Provides screen capture, monitoring, and GIF creation.
6
+ """
7
+
8
+ import sys
9
+
10
+ import click
11
+
12
+
13
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
14
+ def capture():
15
+ """
16
+ Screen capture and monitoring utilities
17
+
18
+ \b
19
+ Commands:
20
+ snap Take a single screenshot
21
+ start Start continuous monitoring
22
+ stop Stop monitoring
23
+ gif Create GIF from session
24
+ info Display info (monitors, windows)
25
+ window Capture specific window by handle
26
+
27
+ \b
28
+ Examples:
29
+ scitex capture snap # Take screenshot
30
+ scitex capture snap --message "debug" # With message in filename
31
+ scitex capture start --interval 2 # Monitor every 2 seconds
32
+ scitex capture stop # Stop monitoring
33
+ scitex capture gif # Create GIF from latest session
34
+ scitex capture info # List monitors and windows
35
+ """
36
+ pass
37
+
38
+
39
+ @capture.command()
40
+ @click.option("--message", "-m", default="", help="Message to include in filename")
41
+ @click.option("--output", "-o", type=click.Path(), help="Output directory")
42
+ @click.option(
43
+ "--quality", "-q", type=int, default=85, help="JPEG quality 1-100 (default: 85)"
44
+ )
45
+ @click.option(
46
+ "--monitor", type=int, default=0, help="Monitor number (0-based, default: 0)"
47
+ )
48
+ @click.option("--all-monitors", is_flag=True, help="Capture all monitors combined")
49
+ def snap(message, output, quality, monitor, all_monitors):
50
+ """
51
+ Take a single screenshot
52
+
53
+ \b
54
+ Examples:
55
+ scitex capture snap
56
+ scitex capture snap --message "before-change"
57
+ scitex capture snap --all-monitors
58
+ scitex capture snap --monitor 1 --quality 95
59
+ """
60
+ try:
61
+ from scitex.capture import snap as take_snap
62
+
63
+ click.echo("Taking screenshot...")
64
+
65
+ # Build kwargs
66
+ kwargs = {"message": message}
67
+ if output:
68
+ kwargs["output_dir"] = output
69
+ if quality != 85:
70
+ kwargs["quality"] = quality
71
+ if all_monitors:
72
+ kwargs["capture_all"] = True
73
+ else:
74
+ kwargs["monitor_id"] = monitor
75
+
76
+ result = take_snap(**kwargs)
77
+
78
+ if result:
79
+ click.secho(f"Screenshot saved: {result}", fg="green")
80
+ else:
81
+ click.secho("Screenshot taken", fg="green")
82
+
83
+ except Exception as e:
84
+ click.secho(f"Error: {e}", fg="red", err=True)
85
+ sys.exit(1)
86
+
87
+
88
+ @capture.command()
89
+ @click.option(
90
+ "--interval",
91
+ "-i",
92
+ type=float,
93
+ default=1.0,
94
+ help="Seconds between captures (default: 1.0)",
95
+ )
96
+ @click.option("--output", "-o", type=click.Path(), help="Output directory")
97
+ @click.option(
98
+ "--quality", "-q", type=int, default=60, help="JPEG quality 1-100 (default: 60)"
99
+ )
100
+ @click.option(
101
+ "--monitor", type=int, default=0, help="Monitor number (0-based, default: 0)"
102
+ )
103
+ @click.option("--all-monitors", is_flag=True, help="Capture all monitors combined")
104
+ def start(interval, output, quality, monitor, all_monitors):
105
+ """
106
+ Start continuous screenshot monitoring
107
+
108
+ \b
109
+ Examples:
110
+ scitex capture start # Default 1 second interval
111
+ scitex capture start --interval 0.5 # Every 0.5 seconds
112
+ scitex capture start --all-monitors
113
+ """
114
+ try:
115
+ from scitex.capture import start as start_monitor
116
+
117
+ click.echo(f"Starting monitoring (interval: {interval}s)...")
118
+ click.echo("Press Ctrl+C or run 'scitex capture stop' to stop")
119
+
120
+ kwargs = {"interval": interval}
121
+ if output:
122
+ kwargs["output_dir"] = output
123
+ if quality != 60:
124
+ kwargs["quality"] = quality
125
+ if all_monitors:
126
+ kwargs["capture_all"] = True
127
+ else:
128
+ kwargs["monitor_id"] = monitor
129
+
130
+ start_monitor(**kwargs)
131
+ click.secho("Monitoring started", fg="green")
132
+
133
+ except Exception as e:
134
+ click.secho(f"Error: {e}", fg="red", err=True)
135
+ sys.exit(1)
136
+
137
+
138
+ @capture.command()
139
+ def stop():
140
+ """
141
+ Stop continuous monitoring
142
+
143
+ \b
144
+ Example:
145
+ scitex capture stop
146
+ """
147
+ try:
148
+ from scitex.capture import stop as stop_monitor
149
+
150
+ stop_monitor()
151
+ click.secho("Monitoring stopped", fg="green")
152
+
153
+ except Exception as e:
154
+ click.secho(f"Error: {e}", fg="red", err=True)
155
+ sys.exit(1)
156
+
157
+
158
+ @capture.command()
159
+ @click.option(
160
+ "--session",
161
+ "-s",
162
+ help="Session ID (e.g., '20250823_104523'). Use 'latest' for most recent.",
163
+ )
164
+ @click.option("--output", "-o", type=click.Path(), help="Output GIF path")
165
+ @click.option(
166
+ "--duration",
167
+ "-d",
168
+ type=float,
169
+ default=0.5,
170
+ help="Duration per frame in seconds (default: 0.5)",
171
+ )
172
+ @click.option("--max-frames", type=int, help="Maximum number of frames to include")
173
+ @click.option(
174
+ "--pattern", "-p", help="Glob pattern for images (alternative to session)"
175
+ )
176
+ def gif(session, output, duration, max_frames, pattern):
177
+ """
178
+ Create animated GIF from screenshots
179
+
180
+ \b
181
+ Examples:
182
+ scitex capture gif # From latest session
183
+ scitex capture gif --session 20250823_104523
184
+ scitex capture gif --duration 0.3 --max-frames 50
185
+ scitex capture gif --pattern "./screenshots/*.jpg"
186
+ """
187
+ try:
188
+ if pattern:
189
+ from scitex.capture import create_gif_from_pattern
190
+
191
+ click.echo(f"Creating GIF from pattern: {pattern}")
192
+ result = create_gif_from_pattern(
193
+ pattern=pattern,
194
+ output_path=output,
195
+ duration=duration,
196
+ max_frames=max_frames,
197
+ )
198
+ elif session:
199
+ from scitex.capture import create_gif_from_session
200
+
201
+ click.echo(f"Creating GIF from session: {session}")
202
+ result = create_gif_from_session(
203
+ session_id=session,
204
+ output_path=output,
205
+ duration=duration,
206
+ max_frames=max_frames,
207
+ )
208
+ else:
209
+ from scitex.capture import create_gif_from_latest_session
210
+
211
+ click.echo("Creating GIF from latest session...")
212
+ result = create_gif_from_latest_session(
213
+ output_path=output,
214
+ duration=duration,
215
+ max_frames=max_frames,
216
+ )
217
+
218
+ if result:
219
+ click.secho(f"GIF created: {result}", fg="green")
220
+ else:
221
+ click.secho("No screenshots found to create GIF", fg="yellow")
222
+
223
+ except Exception as e:
224
+ click.secho(f"Error: {e}", fg="red", err=True)
225
+ sys.exit(1)
226
+
227
+
228
+ @capture.command()
229
+ @click.option("--json", "as_json", is_flag=True, help="Output as JSON")
230
+ def info(as_json):
231
+ """
232
+ Display system info (monitors, windows, virtual desktops)
233
+
234
+ \b
235
+ Examples:
236
+ scitex capture info
237
+ scitex capture info --json
238
+ """
239
+ try:
240
+ from scitex.capture import get_info
241
+
242
+ info_data = get_info()
243
+
244
+ if as_json:
245
+ import json
246
+
247
+ click.echo(json.dumps(info_data, indent=2, default=str))
248
+ else:
249
+ click.secho("Display Information", fg="cyan", bold=True)
250
+ click.echo("=" * 50)
251
+
252
+ # Monitors
253
+ monitors = info_data.get("Monitors", {})
254
+ click.secho(f"\nMonitors ({monitors.get('Count', 0)}):", fg="yellow")
255
+ for i, mon in enumerate(monitors.get("Details", [])):
256
+ primary = " (Primary)" if mon.get("Primary") else ""
257
+ click.echo(f" [{i}] {mon.get('Width')}x{mon.get('Height')}{primary}")
258
+
259
+ # Windows
260
+ windows = info_data.get("Windows", {})
261
+ click.secho(f"\nWindows ({windows.get('Count', 0)}):", fg="yellow")
262
+ for win in windows.get("Details", [])[:10]: # Show first 10
263
+ title = win.get("Title", "")[:40]
264
+ handle = win.get("Handle", "")
265
+ click.echo(f" [{handle}] {title}")
266
+ if windows.get("Count", 0) > 10:
267
+ click.echo(f" ... and {windows.get('Count') - 10} more")
268
+
269
+ except Exception as e:
270
+ click.secho(f"Error: {e}", fg="red", err=True)
271
+ sys.exit(1)
272
+
273
+
274
+ @capture.command()
275
+ @click.argument("handle", type=int)
276
+ @click.option("--output", "-o", type=click.Path(), help="Output file path")
277
+ @click.option("--quality", "-q", type=int, default=85, help="JPEG quality 1-100")
278
+ def window(handle, output, quality):
279
+ """
280
+ Capture a specific window by its handle
281
+
282
+ \b
283
+ Get window handles with: scitex capture info
284
+
285
+ \b
286
+ Examples:
287
+ scitex capture window 12345
288
+ scitex capture window 12345 --output ./window.jpg
289
+ """
290
+ try:
291
+ from scitex.capture import capture_window
292
+
293
+ click.echo(f"Capturing window {handle}...")
294
+ result = capture_window(handle, output)
295
+
296
+ if result:
297
+ click.secho(f"Window captured: {result}", fg="green")
298
+ else:
299
+ click.secho("Window captured", fg="green")
300
+
301
+ except Exception as e:
302
+ click.secho(f"Error: {e}", fg="red", err=True)
303
+ sys.exit(1)
304
+
305
+
306
+ if __name__ == "__main__":
307
+ capture()
scitex/cli/convert.py CHANGED
@@ -227,17 +227,19 @@ def validate_bundles(paths: tuple, verbose: bool):
227
227
  scitex convert validate output.stx
228
228
  scitex convert validate ./figures/*.stx --verbose
229
229
  """
230
- # Use FTS instead of deprecated io.bundle
230
+ # Use Bundle for validation
231
231
  try:
232
- from scitex.fts import FTS as ZipBundle
232
+ from scitex.io.bundle import Bundle as ZipBundle
233
+
233
234
  def validate_stx_bundle(path):
234
235
  try:
235
236
  bundle = ZipBundle(path)
236
237
  return bundle.validate(level="strict")
237
238
  except Exception as e:
238
239
  return {"valid": False, "errors": [str(e)]}
240
+
239
241
  except ImportError:
240
- click.echo("Error: scitex.fts not available", err=True)
242
+ click.echo("Error: scitex.io.bundle not available", err=True)
241
243
  return
242
244
 
243
245
  valid = 0
@@ -303,9 +305,9 @@ def bundle_info(path: str):
303
305
  scitex convert info figure.stx
304
306
  """
305
307
  try:
306
- from scitex.fts import FTS as ZipBundle
308
+ from scitex.io.bundle import Bundle as ZipBundle
307
309
  except ImportError:
308
- click.echo("Error: scitex.fts not available", err=True)
310
+ click.echo("Error: scitex.io.bundle not available", err=True)
309
311
  return
310
312
 
311
313
  bundle_path = Path(path)
@@ -368,12 +370,14 @@ def _convert_bundle(input_path: Path, output_path: Path) -> None:
368
370
  """
369
371
  import json
370
372
  import tempfile
371
- import zipfile
372
373
 
373
374
  # Generate bundle ID and normalize spec - inline functions since io.bundle is deprecated
374
375
  import uuid
376
+ import zipfile
377
+
375
378
  def generate_bundle_id():
376
379
  return str(uuid.uuid4())[:8]
380
+
377
381
  def normalize_spec(spec):
378
382
  return spec # FTS handles normalization internally
379
383
 
scitex/cli/main.py CHANGED
@@ -8,7 +8,22 @@ import sys
8
8
 
9
9
  import click
10
10
 
11
- from . import cloud, config, convert, scholar, security, web, writer
11
+ from . import (
12
+ audio,
13
+ capture,
14
+ cloud,
15
+ config,
16
+ convert,
17
+ repro,
18
+ resource,
19
+ scholar,
20
+ security,
21
+ stats,
22
+ template,
23
+ tex,
24
+ web,
25
+ writer,
26
+ )
12
27
 
13
28
 
14
29
  @click.group(context_settings={"help_option_names": ["-h", "--help"]})
@@ -28,6 +43,10 @@ def cli():
28
43
  scitex security check --save
29
44
  scitex web get-urls https://example.com
30
45
  scitex web download-images https://example.com --output ./downloads
46
+ scitex audio speak "Hello world"
47
+ scitex capture snap --output screenshot.jpg
48
+ scitex resource usage
49
+ scitex stats recommend --data data.csv
31
50
 
32
51
  \b
33
52
  Enable tab-completion:
@@ -38,11 +57,18 @@ def cli():
38
57
 
39
58
 
40
59
  # Add command groups
60
+ cli.add_command(audio.audio)
61
+ cli.add_command(capture.capture)
41
62
  cli.add_command(cloud.cloud)
42
63
  cli.add_command(config.config)
43
64
  cli.add_command(convert.convert)
65
+ cli.add_command(repro.repro)
66
+ cli.add_command(resource.resource)
44
67
  cli.add_command(scholar.scholar)
45
68
  cli.add_command(security.security)
69
+ cli.add_command(stats.stats)
70
+ cli.add_command(template.template)
71
+ cli.add_command(tex.tex)
46
72
  cli.add_command(web.web)
47
73
  cli.add_command(writer.writer)
48
74
 
@@ -111,15 +137,12 @@ def completion(shell, show):
111
137
 
112
138
  # Generate completion script
113
139
  if shell == "bash":
114
- completion_script = f"_SCITEX_COMPLETE=bash_source {scitex_full}"
115
140
  rc_file = os.path.expanduser("~/.bashrc")
116
141
  eval_line = f'eval "$(_SCITEX_COMPLETE=bash_source {scitex_full})"'
117
142
  elif shell == "zsh":
118
- completion_script = f"_SCITEX_COMPLETE=zsh_source {scitex_full}"
119
143
  rc_file = os.path.expanduser("~/.zshrc")
120
144
  eval_line = f'eval "$(_SCITEX_COMPLETE=zsh_source {scitex_full})"'
121
145
  elif shell == "fish":
122
- completion_script = f"_SCITEX_COMPLETE=fish_source {scitex_full}"
123
146
  rc_file = os.path.expanduser("~/.config/fish/config.fish")
124
147
  eval_line = f"eval (env _SCITEX_COMPLETE=fish_source {scitex_full})"
125
148
 
scitex/cli/repro.py ADDED
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SciTeX CLI - Repro Commands (Reproducibility)
4
+
5
+ Provides reproducibility utilities: ID generation, timestamps, hashing.
6
+ """
7
+
8
+ import sys
9
+
10
+ import click
11
+
12
+
13
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
14
+ def repro():
15
+ """
16
+ Reproducibility utilities
17
+
18
+ \b
19
+ Commands:
20
+ gen-id Generate unique identifier
21
+ gen-timestamp Generate timestamp
22
+ hash Hash array/file for reproducibility
23
+ seed Set random seed across all libraries
24
+
25
+ \b
26
+ Examples:
27
+ scitex repro gen-id # Generate unique ID
28
+ scitex repro gen-timestamp # Generate timestamp
29
+ scitex repro hash data.npy # Hash array file
30
+ scitex repro seed 42 # Set random seed
31
+ """
32
+ pass
33
+
34
+
35
+ @repro.command("gen-id")
36
+ @click.option("--length", "-l", type=int, default=8, help="ID length (default: 8)")
37
+ @click.option("--prefix", "-p", default="", help="Prefix to add to ID")
38
+ @click.option("--count", "-n", type=int, default=1, help="Number of IDs to generate")
39
+ def gen_id(length, prefix, count):
40
+ """
41
+ Generate unique identifier(s)
42
+
43
+ \b
44
+ Examples:
45
+ scitex repro gen-id
46
+ scitex repro gen-id --length 12
47
+ scitex repro gen-id --prefix exp_
48
+ scitex repro gen-id --count 5
49
+ """
50
+ try:
51
+ from scitex.repro import gen_ID
52
+
53
+ for _ in range(count):
54
+ id_str = gen_ID()
55
+ if length != 8:
56
+ id_str = id_str[:length]
57
+ if prefix:
58
+ id_str = f"{prefix}{id_str}"
59
+ click.echo(id_str)
60
+
61
+ except Exception as e:
62
+ click.secho(f"Error: {e}", fg="red", err=True)
63
+ sys.exit(1)
64
+
65
+
66
+ @repro.command("gen-timestamp")
67
+ @click.option(
68
+ "--format",
69
+ "-f",
70
+ "fmt",
71
+ type=click.Choice(["iso", "file", "compact", "human"]),
72
+ default="iso",
73
+ help="Timestamp format (default: iso)",
74
+ )
75
+ @click.option("--utc", is_flag=True, help="Use UTC timezone")
76
+ def gen_timestamp(fmt, utc):
77
+ """
78
+ Generate timestamp
79
+
80
+ \b
81
+ Formats:
82
+ iso - ISO 8601 format (2025-01-08T12:30:45)
83
+ file - File-safe format (20250108_123045)
84
+ compact - Compact format (20250108123045)
85
+ human - Human readable (Jan 08, 2025 12:30:45)
86
+
87
+ \b
88
+ Examples:
89
+ scitex repro gen-timestamp
90
+ scitex repro gen-timestamp --format file
91
+ scitex repro gen-timestamp --format human --utc
92
+ """
93
+ try:
94
+ from datetime import datetime, timezone
95
+
96
+ from scitex.repro import gen_timestamp as make_timestamp
97
+
98
+ if utc:
99
+ now = datetime.now(timezone.utc)
100
+ else:
101
+ now = datetime.now()
102
+
103
+ if fmt == "iso":
104
+ ts = now.isoformat()
105
+ elif fmt == "file":
106
+ ts = now.strftime("%Y%m%d_%H%M%S")
107
+ elif fmt == "compact":
108
+ ts = now.strftime("%Y%m%d%H%M%S")
109
+ elif fmt == "human":
110
+ ts = now.strftime("%b %d, %Y %H:%M:%S")
111
+ else:
112
+ ts = make_timestamp()
113
+
114
+ click.echo(ts)
115
+
116
+ except Exception as e:
117
+ click.secho(f"Error: {e}", fg="red", err=True)
118
+ sys.exit(1)
119
+
120
+
121
+ @repro.command()
122
+ @click.argument("file_path", type=click.Path(exists=True))
123
+ @click.option(
124
+ "--algorithm", "-a", default="sha256", help="Hash algorithm (default: sha256)"
125
+ )
126
+ @click.option("--short", "-s", is_flag=True, help="Output short hash (first 8 chars)")
127
+ def hash(file_path, algorithm, short):
128
+ """
129
+ Hash array or file for reproducibility verification
130
+
131
+ \b
132
+ Supported file types:
133
+ .npy, .npz - NumPy arrays
134
+ .pt, .pth - PyTorch tensors
135
+ .pkl - Pickle files
136
+ * - Any file (raw bytes hash)
137
+
138
+ \b
139
+ Examples:
140
+ scitex repro hash data.npy
141
+ scitex repro hash model.pt --short
142
+ scitex repro hash weights.npz --algorithm md5
143
+ """
144
+ try:
145
+ import hashlib
146
+ from pathlib import Path
147
+
148
+ path = Path(file_path)
149
+
150
+ # Try to load as array first
151
+ hash_val = None
152
+ try:
153
+ if path.suffix in (".npy", ".npz"):
154
+ import numpy as np
155
+
156
+ from scitex.repro import hash_array
157
+
158
+ arr = np.load(path, allow_pickle=True)
159
+ if isinstance(arr, np.lib.npyio.NpzFile):
160
+ # For npz, hash all arrays
161
+ hashes = []
162
+ for key in arr.files:
163
+ hashes.append(hash_array(arr[key]))
164
+ hash_val = hashlib.sha256("".join(hashes).encode()).hexdigest()
165
+ else:
166
+ hash_val = hash_array(arr)
167
+ elif path.suffix in (".pt", ".pth"):
168
+ import torch
169
+
170
+ data = torch.load(path, map_location="cpu")
171
+ if isinstance(data, torch.Tensor):
172
+ hash_val = hashlib.sha256(data.numpy().tobytes()).hexdigest()
173
+ else:
174
+ # State dict or other
175
+ hash_val = hashlib.sha256(str(data).encode()).hexdigest()
176
+ except ImportError:
177
+ pass
178
+
179
+ # Fall back to file hash
180
+ if hash_val is None:
181
+ h = hashlib.new(algorithm)
182
+ with open(path, "rb") as f:
183
+ for chunk in iter(lambda: f.read(8192), b""):
184
+ h.update(chunk)
185
+ hash_val = h.hexdigest()
186
+
187
+ if short:
188
+ hash_val = hash_val[:8]
189
+
190
+ click.echo(f"{hash_val} {path.name}")
191
+
192
+ except Exception as e:
193
+ click.secho(f"Error: {e}", fg="red", err=True)
194
+ sys.exit(1)
195
+
196
+
197
+ @repro.command()
198
+ @click.argument("seed", type=int)
199
+ @click.option("--verbose", "-v", is_flag=True, help="Show what was seeded")
200
+ def seed(seed, verbose):
201
+ """
202
+ Set random seed across all available libraries
203
+
204
+ \b
205
+ Affects: os, random, numpy, torch, tensorflow, jax
206
+
207
+ \b
208
+ Examples:
209
+ scitex repro seed 42
210
+ scitex repro seed 12345 --verbose
211
+ """
212
+ try:
213
+ from scitex.repro import RandomStateManager
214
+
215
+ rsm = RandomStateManager(seed=seed, verbose=verbose)
216
+
217
+ click.secho(f"Random seed set to: {seed}", fg="green")
218
+ if verbose:
219
+ click.echo("Seeded libraries:")
220
+ click.echo(" - os.environ['PYTHONHASHSEED']")
221
+ click.echo(" - random")
222
+ click.echo(" - numpy (if available)")
223
+ click.echo(" - torch (if available)")
224
+ click.echo(" - tensorflow (if available)")
225
+ click.echo(" - jax (if available)")
226
+
227
+ except Exception as e:
228
+ click.secho(f"Error: {e}", fg="red", err=True)
229
+ sys.exit(1)
230
+
231
+
232
+ if __name__ == "__main__":
233
+ repro()