scitex 2.14.0__py3-none-any.whl → 2.15.3__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 (264) hide show
  1. scitex/__init__.py +71 -17
  2. scitex/_env_loader.py +156 -0
  3. scitex/_mcp_resources/__init__.py +37 -0
  4. scitex/_mcp_resources/_cheatsheet.py +135 -0
  5. scitex/_mcp_resources/_figrecipe.py +138 -0
  6. scitex/_mcp_resources/_formats.py +102 -0
  7. scitex/_mcp_resources/_modules.py +337 -0
  8. scitex/_mcp_resources/_session.py +149 -0
  9. scitex/_mcp_tools/__init__.py +4 -0
  10. scitex/_mcp_tools/audio.py +66 -0
  11. scitex/_mcp_tools/diagram.py +11 -95
  12. scitex/_mcp_tools/introspect.py +210 -0
  13. scitex/_mcp_tools/plt.py +260 -305
  14. scitex/_mcp_tools/scholar.py +74 -0
  15. scitex/_mcp_tools/social.py +27 -0
  16. scitex/_mcp_tools/template.py +24 -0
  17. scitex/_mcp_tools/writer.py +17 -210
  18. scitex/ai/_gen_ai/_PARAMS.py +10 -7
  19. scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
  20. scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
  21. scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
  22. scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
  23. scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
  24. scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
  25. scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
  26. scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
  27. scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
  28. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +30 -1550
  29. scitex/ai/classification/timeseries/_sliding_window_core.py +467 -0
  30. scitex/ai/classification/timeseries/_sliding_window_plotting.py +369 -0
  31. scitex/audio/README.md +40 -36
  32. scitex/audio/__init__.py +129 -61
  33. scitex/audio/_branding.py +185 -0
  34. scitex/audio/_mcp/__init__.py +32 -0
  35. scitex/audio/_mcp/handlers.py +59 -6
  36. scitex/audio/_mcp/speak_handlers.py +238 -0
  37. scitex/audio/_relay.py +225 -0
  38. scitex/audio/_tts.py +18 -10
  39. scitex/audio/engines/base.py +17 -10
  40. scitex/audio/engines/elevenlabs_engine.py +7 -2
  41. scitex/audio/mcp_server.py +228 -75
  42. scitex/canvas/README.md +1 -1
  43. scitex/canvas/editor/_dearpygui/__init__.py +25 -0
  44. scitex/canvas/editor/_dearpygui/_editor.py +147 -0
  45. scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
  46. scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
  47. scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
  48. scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
  49. scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
  50. scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
  51. scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
  52. scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
  53. scitex/canvas/editor/_dearpygui/_selection.py +295 -0
  54. scitex/canvas/editor/_dearpygui/_state.py +93 -0
  55. scitex/canvas/editor/_dearpygui/_utils.py +61 -0
  56. scitex/canvas/editor/flask_editor/_core/__init__.py +27 -0
  57. scitex/canvas/editor/flask_editor/_core/_bbox_extraction.py +200 -0
  58. scitex/canvas/editor/flask_editor/_core/_editor.py +173 -0
  59. scitex/canvas/editor/flask_editor/_core/_export_helpers.py +353 -0
  60. scitex/canvas/editor/flask_editor/_core/_routes_basic.py +190 -0
  61. scitex/canvas/editor/flask_editor/_core/_routes_export.py +332 -0
  62. scitex/canvas/editor/flask_editor/_core/_routes_panels.py +252 -0
  63. scitex/canvas/editor/flask_editor/_core/_routes_save.py +218 -0
  64. scitex/canvas/editor/flask_editor/_core.py +25 -1684
  65. scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
  66. scitex/cli/__init__.py +38 -43
  67. scitex/cli/audio.py +160 -41
  68. scitex/cli/capture.py +133 -20
  69. scitex/cli/introspect.py +488 -0
  70. scitex/cli/main.py +200 -109
  71. scitex/cli/mcp.py +60 -34
  72. scitex/cli/plt.py +414 -0
  73. scitex/cli/repro.py +15 -8
  74. scitex/cli/resource.py +15 -8
  75. scitex/cli/scholar/__init__.py +154 -8
  76. scitex/cli/scholar/_crossref_scitex.py +296 -0
  77. scitex/cli/scholar/_fetch.py +25 -3
  78. scitex/cli/social.py +355 -0
  79. scitex/cli/stats.py +136 -11
  80. scitex/cli/template.py +129 -12
  81. scitex/cli/tex.py +15 -8
  82. scitex/cli/writer.py +49 -299
  83. scitex/cloud/__init__.py +41 -2
  84. scitex/config/README.md +1 -1
  85. scitex/config/__init__.py +16 -2
  86. scitex/config/_env_registry.py +256 -0
  87. scitex/context/__init__.py +22 -0
  88. scitex/dev/__init__.py +20 -1
  89. scitex/diagram/__init__.py +42 -19
  90. scitex/diagram/mcp_server.py +13 -125
  91. scitex/gen/__init__.py +50 -14
  92. scitex/gen/_list_packages.py +4 -4
  93. scitex/introspect/__init__.py +82 -0
  94. scitex/introspect/_call_graph.py +303 -0
  95. scitex/introspect/_class_hierarchy.py +163 -0
  96. scitex/introspect/_core.py +41 -0
  97. scitex/introspect/_docstring.py +131 -0
  98. scitex/introspect/_examples.py +113 -0
  99. scitex/introspect/_imports.py +271 -0
  100. scitex/{gen/_inspect_module.py → introspect/_list_api.py} +48 -56
  101. scitex/introspect/_mcp/__init__.py +41 -0
  102. scitex/introspect/_mcp/handlers.py +233 -0
  103. scitex/introspect/_members.py +155 -0
  104. scitex/introspect/_resolve.py +89 -0
  105. scitex/introspect/_signature.py +131 -0
  106. scitex/introspect/_source.py +80 -0
  107. scitex/introspect/_type_hints.py +172 -0
  108. scitex/io/_save.py +1 -2
  109. scitex/io/bundle/README.md +1 -1
  110. scitex/logging/_formatters.py +19 -9
  111. scitex/mcp_server.py +98 -5
  112. scitex/os/__init__.py +4 -0
  113. scitex/{gen → os}/_check_host.py +4 -5
  114. scitex/plt/__init__.py +245 -550
  115. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
  116. scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  117. scitex/plt/gallery/README.md +1 -1
  118. scitex/plt/utils/_hitmap/__init__.py +82 -0
  119. scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
  120. scitex/plt/utils/_hitmap/_color_application.py +346 -0
  121. scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
  122. scitex/plt/utils/_hitmap/_constants.py +40 -0
  123. scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
  124. scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
  125. scitex/plt/utils/_hitmap/_query.py +113 -0
  126. scitex/plt/utils/_hitmap.py +46 -1616
  127. scitex/plt/utils/_metadata/__init__.py +80 -0
  128. scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
  129. scitex/plt/utils/_metadata/_artists/_base.py +195 -0
  130. scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
  131. scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
  132. scitex/plt/utils/_metadata/_artists/_images.py +80 -0
  133. scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
  134. scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
  135. scitex/plt/utils/_metadata/_artists/_text.py +106 -0
  136. scitex/plt/utils/_metadata/_csv.py +416 -0
  137. scitex/plt/utils/_metadata/_detect.py +225 -0
  138. scitex/plt/utils/_metadata/_legend.py +127 -0
  139. scitex/plt/utils/_metadata/_rounding.py +117 -0
  140. scitex/plt/utils/_metadata/_verification.py +202 -0
  141. scitex/schema/README.md +1 -1
  142. scitex/scholar/__init__.py +8 -0
  143. scitex/scholar/_mcp/crossref_handlers.py +265 -0
  144. scitex/scholar/core/Scholar.py +63 -1700
  145. scitex/scholar/core/_mixins/__init__.py +36 -0
  146. scitex/scholar/core/_mixins/_enrichers.py +270 -0
  147. scitex/scholar/core/_mixins/_library_handlers.py +100 -0
  148. scitex/scholar/core/_mixins/_loaders.py +103 -0
  149. scitex/scholar/core/_mixins/_pdf_download.py +375 -0
  150. scitex/scholar/core/_mixins/_pipeline.py +312 -0
  151. scitex/scholar/core/_mixins/_project_handlers.py +125 -0
  152. scitex/scholar/core/_mixins/_savers.py +69 -0
  153. scitex/scholar/core/_mixins/_search.py +103 -0
  154. scitex/scholar/core/_mixins/_services.py +88 -0
  155. scitex/scholar/core/_mixins/_url_finding.py +105 -0
  156. scitex/scholar/crossref_scitex.py +367 -0
  157. scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  158. scitex/scholar/examples/00_run_all.sh +120 -0
  159. scitex/scholar/jobs/_executors.py +27 -3
  160. scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
  161. scitex/scholar/pdf_download/_cli.py +154 -0
  162. scitex/scholar/pdf_download/strategies/__init__.py +11 -8
  163. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
  164. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
  165. scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
  166. scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
  167. scitex/scholar/pipelines/_single_steps.py +71 -36
  168. scitex/scholar/storage/_LibraryManager.py +97 -1695
  169. scitex/scholar/storage/_mixins/__init__.py +30 -0
  170. scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
  171. scitex/scholar/storage/_mixins/_library_operations.py +218 -0
  172. scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
  173. scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
  174. scitex/scholar/storage/_mixins/_resolution.py +376 -0
  175. scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
  176. scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
  177. scitex/security/README.md +3 -3
  178. scitex/session/README.md +1 -1
  179. scitex/session/__init__.py +26 -7
  180. scitex/session/_decorator.py +1 -1
  181. scitex/sh/README.md +1 -1
  182. scitex/sh/__init__.py +7 -4
  183. scitex/social/__init__.py +155 -0
  184. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  185. scitex/stats/_mcp/_handlers/__init__.py +31 -0
  186. scitex/stats/_mcp/_handlers/_corrections.py +113 -0
  187. scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
  188. scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
  189. scitex/stats/_mcp/_handlers/_format.py +94 -0
  190. scitex/stats/_mcp/_handlers/_normality.py +110 -0
  191. scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
  192. scitex/stats/_mcp/_handlers/_power.py +247 -0
  193. scitex/stats/_mcp/_handlers/_recommend.py +102 -0
  194. scitex/stats/_mcp/_handlers/_run_test.py +279 -0
  195. scitex/stats/_mcp/_handlers/_stars.py +48 -0
  196. scitex/stats/_mcp/handlers.py +19 -1171
  197. scitex/stats/auto/_stat_style.py +175 -0
  198. scitex/stats/auto/_style_definitions.py +411 -0
  199. scitex/stats/auto/_styles.py +22 -620
  200. scitex/stats/descriptive/__init__.py +11 -8
  201. scitex/stats/descriptive/_ci.py +39 -0
  202. scitex/stats/power/_power.py +15 -4
  203. scitex/str/__init__.py +2 -1
  204. scitex/str/_title_case.py +63 -0
  205. scitex/template/README.md +1 -1
  206. scitex/template/__init__.py +25 -10
  207. scitex/template/_code_templates.py +147 -0
  208. scitex/template/_mcp/handlers.py +81 -0
  209. scitex/template/_mcp/tool_schemas.py +55 -0
  210. scitex/template/_templates/__init__.py +51 -0
  211. scitex/template/_templates/audio.py +233 -0
  212. scitex/template/_templates/canvas.py +312 -0
  213. scitex/template/_templates/capture.py +268 -0
  214. scitex/template/_templates/config.py +43 -0
  215. scitex/template/_templates/diagram.py +294 -0
  216. scitex/template/_templates/io.py +107 -0
  217. scitex/template/_templates/module.py +53 -0
  218. scitex/template/_templates/plt.py +202 -0
  219. scitex/template/_templates/scholar.py +267 -0
  220. scitex/template/_templates/session.py +130 -0
  221. scitex/template/_templates/session_minimal.py +43 -0
  222. scitex/template/_templates/session_plot.py +67 -0
  223. scitex/template/_templates/session_stats.py +77 -0
  224. scitex/template/_templates/stats.py +323 -0
  225. scitex/template/_templates/writer.py +296 -0
  226. scitex/template/clone_writer_directory.py +5 -5
  227. scitex/ui/_backends/_email.py +10 -2
  228. scitex/ui/_backends/_webhook.py +5 -1
  229. scitex/web/_search_pubmed.py +10 -6
  230. scitex/writer/README.md +1 -1
  231. scitex/writer/__init__.py +43 -34
  232. scitex/writer/_mcp/handlers.py +11 -744
  233. scitex/writer/_mcp/tool_schemas.py +5 -335
  234. scitex-2.15.3.dist-info/METADATA +667 -0
  235. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/RECORD +241 -120
  236. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  237. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  238. scitex/diagram/_compile.py +0 -312
  239. scitex/diagram/_diagram.py +0 -355
  240. scitex/diagram/_mcp/__init__.py +0 -4
  241. scitex/diagram/_mcp/handlers.py +0 -400
  242. scitex/diagram/_mcp/tool_schemas.py +0 -157
  243. scitex/diagram/_presets.py +0 -173
  244. scitex/diagram/_schema.py +0 -182
  245. scitex/diagram/_split.py +0 -278
  246. scitex/gen/_ci.py +0 -12
  247. scitex/gen/_title_case.py +0 -89
  248. scitex/plt/_mcp/__init__.py +0 -4
  249. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  250. scitex/plt/_mcp/_handlers_figure.py +0 -195
  251. scitex/plt/_mcp/_handlers_plot.py +0 -252
  252. scitex/plt/_mcp/_handlers_style.py +0 -219
  253. scitex/plt/_mcp/handlers.py +0 -74
  254. scitex/plt/_mcp/tool_schemas.py +0 -497
  255. scitex/plt/mcp_server.py +0 -231
  256. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  257. scitex/scholar/examples/dev.py +0 -38
  258. scitex-2.14.0.dist-info/METADATA +0 -1238
  259. /scitex/{gen → context}/_detect_environment.py +0 -0
  260. /scitex/{gen → context}/_get_notebook_path.py +0 -0
  261. /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
  262. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/WHEEL +0 -0
  263. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/entry_points.txt +0 -0
  264. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/licenses/LICENSE +0 -0
scitex/__init__.py CHANGED
@@ -29,19 +29,9 @@ warnings.filterwarnings("default", category=DeprecationWarning, module="scitex.*
29
29
  # Version
30
30
  from .__version__ import __version__
31
31
 
32
- # Installation guide - show users what modules are available
33
- from ._install_guide import show_install_guide
34
-
35
-
36
- # Sentinel object for decorator-injected parameters
37
- class _InjectedSentinel:
38
- """Sentinel value indicating a parameter will be injected by a decorator"""
39
-
40
- def __repr__(self):
41
- return "<INJECTED>"
42
-
43
-
44
- INJECTED = _InjectedSentinel()
32
+ # BACKWARD COMPATIBILITY: Deprecated items accessible via __getattr__
33
+ # These are handled at the end of this file after lazy modules are defined
34
+ _DEPRECATED_ATTRS = {"INJECTED", "show_install_guide", "Diagram"}
45
35
 
46
36
 
47
37
  # Lazy loading for all modules
@@ -196,6 +186,56 @@ config = _LazyModule("config")
196
186
  audio = _LazyModule("audio")
197
187
  msword = _LazyModule("msword")
198
188
  fts = _LazyModule("fts") # Bundle schemas module
189
+ social = _LazyModule("social") # Social media integration (socialia wrapper)
190
+ diagram = _LazyModule("diagram") # Diagram creation (delegates to figrecipe)
191
+ introspect = _LazyModule("introspect") # Python introspection utilities
192
+ sh = _LazyModule("sh") # Shell command execution
193
+ os = _LazyModule("os") # OS utilities (file operations)
194
+ cv = _LazyModule("cv") # Computer vision utilities
195
+ ui = _LazyModule("ui") # User interface utilities
196
+ git = _LazyModule("git") # Git operations
197
+ schema = _LazyModule("schema") # Data schema utilities
198
+ canvas = _LazyModule("canvas") # Canvas utilities for figure composition
199
+ security = _LazyModule("security") # Security utilities
200
+ benchmark = _LazyModule("benchmark") # Benchmarking utilities
201
+ bridge = _LazyModule("bridge") # Bridge utilities
202
+ browser = _LazyModule("browser") # Browser automation
203
+ compat = _LazyModule("compat") # Compatibility utilities
204
+ cli = _LazyModule("cli") # Command-line interface
205
+
206
+
207
+ # BACKWARD COMPATIBILITY: Module-level __getattr__ for deprecated attributes
208
+ def __getattr__(name):
209
+ """Handle deprecated attributes with warnings."""
210
+ if name == "INJECTED":
211
+ warnings.warn(
212
+ "scitex.INJECTED is deprecated, use scitex.session.INJECTED instead",
213
+ DeprecationWarning,
214
+ stacklevel=2,
215
+ )
216
+ from .session import INJECTED
217
+
218
+ return INJECTED
219
+ if name == "show_install_guide":
220
+ warnings.warn(
221
+ "scitex.show_install_guide() is deprecated, use scitex.dev.show_install_guide() instead",
222
+ DeprecationWarning,
223
+ stacklevel=2,
224
+ )
225
+ from .dev import show_install_guide
226
+
227
+ return show_install_guide
228
+ if name == "Diagram":
229
+ warnings.warn(
230
+ "scitex.Diagram is deprecated, use scitex.diagram.Diagram instead",
231
+ DeprecationWarning,
232
+ stacklevel=2,
233
+ )
234
+ from .diagram import Diagram
235
+
236
+ return Diagram
237
+ raise AttributeError(f"module 'scitex' has no attribute '{name}'")
238
+
199
239
 
200
240
  # Centralized path configuration - eager loaded for convenience
201
241
  # Usage: scitex.PATHS.logs, scitex.PATHS.cache, etc.
@@ -213,6 +253,7 @@ if _os.environ.get("SCITEX_CLOUD_CODE_WORKSPACE") == "true":
213
253
  pass # Silently fail if matplotlib not available
214
254
 
215
255
  __all__ = [
256
+ # Core modules
216
257
  "io",
217
258
  "gen",
218
259
  "plt",
@@ -224,7 +265,6 @@ __all__ = [
224
265
  "path",
225
266
  "dict",
226
267
  "decorators",
227
- "__version__",
228
268
  "sh",
229
269
  "errors",
230
270
  "units",
@@ -248,7 +288,7 @@ __all__ = [
248
288
  "linalg",
249
289
  "parallel",
250
290
  "datetime",
251
- "dt", # Alias for datetime (shorter name)
291
+ "dt",
252
292
  "types",
253
293
  "utils",
254
294
  "etc",
@@ -260,9 +300,23 @@ __all__ = [
260
300
  "audio",
261
301
  "msword",
262
302
  "fts",
263
- "fsb", # Legacy alias
303
+ "social",
304
+ "diagram",
305
+ "introspect",
306
+ "os",
307
+ "cv",
308
+ "ui",
309
+ "git",
310
+ "schema",
311
+ "canvas",
312
+ "security",
313
+ "benchmark",
314
+ "bridge",
315
+ "browser",
316
+ "compat",
317
+ "cli",
264
318
  "PATHS",
265
- "INJECTED",
319
+ "__version__",
266
320
  ]
267
321
 
268
322
  # EOF
scitex/_env_loader.py ADDED
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-24
3
+ # File: src/scitex/_env_loader.py
4
+
5
+ """
6
+ Environment variable loader for SCITEX_ENV_SRC.
7
+
8
+ Parses and loads bash-compatible .src files containing environment variable definitions.
9
+ Supports both directory paths (all *.src files) and single file paths.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ import os
16
+ import re
17
+ from pathlib import Path
18
+ from typing import Dict, List
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Pattern to match: export VAR=value or VAR=value (with optional quotes)
23
+ _ENV_PATTERN = re.compile(r"^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)$")
24
+
25
+
26
+ def _parse_value(value: str) -> str:
27
+ """Parse a bash-style value, handling quotes and escapes."""
28
+ value = value.strip()
29
+
30
+ # Handle double-quoted strings
31
+ if value.startswith('"') and value.endswith('"'):
32
+ value = value[1:-1]
33
+ # Unescape common bash escapes
34
+ value = value.replace('\\"', '"')
35
+ value = value.replace("\\$", "$")
36
+ value = value.replace("\\\\", "\\")
37
+ # Handle single-quoted strings (no escaping in bash single quotes)
38
+ elif value.startswith("'") and value.endswith("'"):
39
+ value = value[1:-1]
40
+
41
+ # Expand $VAR and ${VAR} references
42
+ def expand_var(match):
43
+ var_name = match.group(1) or match.group(2)
44
+ return os.environ.get(var_name, "")
45
+
46
+ value = re.sub(r"\$\{([^}]+)\}|\$([A-Za-z_][A-Za-z0-9_]*)", expand_var, value)
47
+
48
+ return value
49
+
50
+
51
+ def parse_src_file(filepath: Path) -> Dict[str, str]:
52
+ """
53
+ Parse a bash-compatible .src file and extract environment variables.
54
+
55
+ Parameters
56
+ ----------
57
+ filepath : Path
58
+ Path to the .src file.
59
+
60
+ Returns
61
+ -------
62
+ dict
63
+ Dictionary of variable names to values.
64
+ """
65
+ env_vars = {}
66
+
67
+ try:
68
+ with open(filepath) as f:
69
+ for line_num, line in enumerate(f, 1):
70
+ line = line.strip()
71
+
72
+ # Skip empty lines and comments
73
+ if not line or line.startswith("#"):
74
+ continue
75
+
76
+ match = _ENV_PATTERN.match(line)
77
+ if match:
78
+ name, value = match.groups()
79
+ env_vars[name] = _parse_value(value)
80
+
81
+ except Exception as e:
82
+ logger.warning(f"Failed to parse {filepath}: {e}")
83
+
84
+ return env_vars
85
+
86
+
87
+ def load_env_from_path(path: str) -> Dict[str, str]:
88
+ """
89
+ Load environment variables from a file or directory.
90
+
91
+ Parameters
92
+ ----------
93
+ path : str
94
+ Path to a .src file or directory containing .src files.
95
+
96
+ Returns
97
+ -------
98
+ dict
99
+ All loaded environment variables.
100
+ """
101
+ loaded = {}
102
+ path_obj = Path(path).expanduser()
103
+
104
+ if not path_obj.exists():
105
+ logger.warning(f"SCITEX_ENV_SRC path does not exist: {path}")
106
+ return loaded
107
+
108
+ files_to_load: List[Path] = []
109
+
110
+ if path_obj.is_dir():
111
+ # Load all .src files in directory
112
+ files_to_load = sorted(path_obj.glob("*.src"))
113
+ elif path_obj.is_file():
114
+ files_to_load = [path_obj]
115
+ else:
116
+ logger.warning(f"SCITEX_ENV_SRC is not a file or directory: {path}")
117
+ return loaded
118
+
119
+ for src_file in files_to_load:
120
+ env_vars = parse_src_file(src_file)
121
+ if env_vars:
122
+ logger.info(f"Loaded {len(env_vars)} vars from {src_file.name}")
123
+ loaded.update(env_vars)
124
+
125
+ return loaded
126
+
127
+
128
+ def load_scitex_env() -> int:
129
+ """
130
+ Load environment variables from SCITEX_ENV_SRC if set.
131
+
132
+ This function should be called early in the MCP server startup.
133
+
134
+ Returns
135
+ -------
136
+ int
137
+ Number of environment variables loaded.
138
+ """
139
+ env_src = os.environ.get("SCITEX_ENV_SRC")
140
+
141
+ if not env_src:
142
+ return 0
143
+
144
+ loaded = load_env_from_path(env_src)
145
+
146
+ # Apply to current process environment
147
+ for name, value in loaded.items():
148
+ os.environ[name] = value
149
+
150
+ if loaded:
151
+ logger.info(f"SCITEX_ENV_SRC: Loaded {len(loaded)} environment variables")
152
+
153
+ return len(loaded)
154
+
155
+
156
+ # EOF
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_resources/__init__.py
4
+ """MCP Resources for SciTeX - Dynamic documentation for AI agents.
5
+
6
+ This module provides MCP resources that expose SciTeX documentation,
7
+ patterns, and examples to AI agents for code generation guidance.
8
+
9
+ Resources:
10
+ - scitex://cheatsheet - Quick reference for all core patterns
11
+ - scitex://session-tree - Output directory structure explanation
12
+ - scitex://module/{name} - Module-specific documentation (io, plt, stats, scholar, session)
13
+ - scitex://io-formats - Supported file formats
14
+ - scitex://figrecipe-spec - Figure recipe specification
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from ._cheatsheet import register_cheatsheet_resources
20
+ from ._figrecipe import register_figrecipe_resources
21
+ from ._formats import register_format_resources
22
+ from ._modules import register_module_resources
23
+ from ._session import register_session_resources
24
+
25
+ __all__ = ["register_resources"]
26
+
27
+
28
+ def register_resources(mcp) -> None:
29
+ """Register all MCP resources with the FastMCP server."""
30
+ register_cheatsheet_resources(mcp)
31
+ register_session_resources(mcp)
32
+ register_module_resources(mcp)
33
+ register_format_resources(mcp)
34
+ register_figrecipe_resources(mcp)
35
+
36
+
37
+ # EOF
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_resources/_cheatsheet.py
4
+ """Core SciTeX cheatsheet resource for AI agents."""
5
+
6
+ from __future__ import annotations
7
+
8
+ __all__ = ["register_cheatsheet_resources"]
9
+
10
+ CHEATSHEET = """\
11
+ # SciTeX Cheatsheet for AI Agents
12
+ =================================
13
+
14
+ ## Import Pattern (ALWAYS use this)
15
+ ```python
16
+ import scitex as stx
17
+ import numpy as np
18
+ ```
19
+
20
+ ## 1. @stx.session - Reproducible Experiment Tracking
21
+
22
+ The MOST IMPORTANT pattern. Wrap your main function with @stx.session:
23
+
24
+ ```python
25
+ @stx.session
26
+ def main(
27
+ # User parameters (become CLI arguments automatically)
28
+ input_file="data.csv", # --input-file (default: data.csv)
29
+ n_samples=100, # --n-samples (default: 100)
30
+
31
+ # INJECTED parameters (auto-provided by session)
32
+ CONFIG=stx.INJECTED, # Session config with ID, paths
33
+ plt=stx.INJECTED, # Pre-configured matplotlib
34
+ COLORS=stx.INJECTED, # Color palette
35
+ rng=stx.INJECTED, # Seeded random generator
36
+ logger=stx.INJECTED, # Session logger
37
+ ):
38
+ \"\"\"This docstring becomes --help description.\"\"\"
39
+
40
+ # Your analysis code here
41
+ data = stx.io.load(input_file)
42
+ results = process(data, n_samples)
43
+
44
+ # Save outputs (automatically to session directory)
45
+ stx.io.save(results, "results.csv")
46
+ stx.io.save(fig, "plot.png", symlink_to="./data")
47
+
48
+ return 0 # Exit status
49
+
50
+ if __name__ == "__main__":
51
+ main() # CLI mode when no args passed
52
+ ```
53
+
54
+ ## 2. stx.io - Universal File I/O (30+ formats)
55
+
56
+ ALWAYS use stx.io.save() and stx.io.load() for file operations:
57
+
58
+ ```python
59
+ # Saving - extension determines format automatically
60
+ stx.io.save(df, "data.csv") # DataFrame -> CSV
61
+ stx.io.save(arr, "data.npy") # NumPy array
62
+ stx.io.save(obj, "data.pkl") # Any Python object
63
+ stx.io.save(fig, "plot.png") # Figure + auto CSV
64
+
65
+ # Loading - format auto-detected
66
+ data = stx.io.load("data.csv")
67
+
68
+ # With options
69
+ stx.io.save(fig, "plot.png",
70
+ metadata={"exp": "exp01"}, # Embedded metadata
71
+ symlink_to="./data", # Create symlink
72
+ verbose=True, # Log messages
73
+ )
74
+ ```
75
+
76
+ IMPORTANT: stx.io.save shows logging messages:
77
+ ```
78
+ SUCC: Saved to: ./script_out/results.csv (4.0 KiB)
79
+ SUCC: Symlinked: ./script_out/results.csv -> ./data/results.csv
80
+ ```
81
+
82
+ ## 3. stx.plt - Publication-Ready Figures (Auto CSV Export)
83
+
84
+ ```python
85
+ fig, ax = stx.plt.subplots()
86
+
87
+ # Use stx_ prefixed methods for auto CSV export
88
+ ax.stx_line(x, y, label="Signal") # Tracked: exports to CSV
89
+ ax.stx_scatter(x, y) # Tracked
90
+
91
+ # Set labels with convenience method
92
+ ax.set_xyt("X axis", "Y axis", "Title")
93
+
94
+ # Save figure -> creates BOTH plot.png AND plot.csv
95
+ stx.io.save(fig, "plot.png")
96
+ fig.close()
97
+ ```
98
+
99
+ ## 4. stx.stats - Publication Statistics (23 tests)
100
+
101
+ ```python
102
+ result = stx.stats.test_ttest_ind(group1, group2, return_as="dataframe")
103
+ # Returns: p-value, Cohen's d, 95% CI, normality check, power analysis
104
+
105
+ result = stx.stats.test_anova(*groups, return_as="latex")
106
+ ```
107
+
108
+ ## 5. stx.scholar - Literature Management
109
+
110
+ ```bash
111
+ scitex scholar bibtex papers.bib --project myresearch --num-workers 8
112
+ # Enriches BibTeX with abstracts, DOIs, impact factors, downloads PDFs
113
+ ```
114
+
115
+ ## Quick Tips
116
+
117
+ 1. ALWAYS use `import scitex as stx`
118
+ 2. ALWAYS wrap main functions with `@stx.session`
119
+ 3. ALWAYS use `stx.io.save()` and `stx.io.load()` for files
120
+ 4. ALWAYS use `stx.plt.subplots()` for figures
121
+ 5. ALWAYS use `ax.stx_*` methods for auto CSV export
122
+ 6. ALWAYS return exit status (0 for success) from main
123
+ """
124
+
125
+
126
+ def register_cheatsheet_resources(mcp) -> None:
127
+ """Register cheatsheet resource."""
128
+
129
+ @mcp.resource("scitex://cheatsheet")
130
+ def cheatsheet() -> str:
131
+ """Complete SciTeX quick reference for AI code generation."""
132
+ return CHEATSHEET
133
+
134
+
135
+ # EOF
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_resources/_figrecipe.py
4
+ """Figrecipe integration documentation for stx.plt MCP tools."""
5
+
6
+ from __future__ import annotations
7
+
8
+ __all__ = ["register_figrecipe_resources"]
9
+
10
+ FIGRECIPE_INTEGRATION = """\
11
+ # stx.plt - Powered by FigRecipe
12
+ =================================
13
+
14
+ stx.plt provides publication-ready figures with **automatic reproducibility**.
15
+ It's built on FigRecipe, which records all matplotlib calls to YAML recipes.
16
+
17
+ ## Using stx.plt in @stx.session
18
+ ```python
19
+ @stx.session
20
+ def main(plt=stx.INJECTED, COLORS=stx.INJECTED):
21
+ fig, ax = stx.plt.subplots()
22
+
23
+ # Use stx_ prefixed methods for auto CSV export
24
+ ax.stx_line(x, y, color=COLORS.blue, label="data")
25
+ ax.set_xyt("X", "Y", "Title")
26
+
27
+ # Save creates: plot.png + plot.csv (data)
28
+ stx.io.save(fig, "plot.png", symlink_to="./data")
29
+ fig.close()
30
+ return 0
31
+ ```
32
+
33
+ ## Output Files from stx.io.save(fig, ...)
34
+ ```
35
+ script_out/
36
+ ├── plot.png # Image file
37
+ ├── plot.csv # Extracted plot data (auto-generated)
38
+ └── plot.yaml # FigRecipe recipe (if using fr.save directly)
39
+ ```
40
+
41
+ ## Tracked Methods (stx_ prefix)
42
+ These methods track data for automatic CSV export:
43
+ - ax.stx_line(x, y)
44
+ - ax.stx_scatter(x, y)
45
+ - ax.stx_bar(x, height)
46
+ - ax.stx_errorbar(x, y, yerr)
47
+ - ax.stx_hist(data, bins)
48
+ - ax.stx_boxplot(data)
49
+ - ax.stx_violinplot(data)
50
+ - ax.stx_imshow(matrix)
51
+
52
+ ## MCP Declarative Spec (via plt_plot tool)
53
+
54
+ ### RECOMMENDED: CSV Column Input
55
+ Use CSV files - enables code to write data, MCP to visualize:
56
+ ```yaml
57
+ plots:
58
+ - type: scatter
59
+ data_file: results.csv # CSV from your analysis
60
+ x: time # Column name (string)
61
+ y: measurement # Column name
62
+ color: blue
63
+ ```
64
+
65
+ **Workflow**: Python writes CSV → MCP reads columns → Creates figure
66
+
67
+ ### Alternative: Inline Data (simple cases only)
68
+ ```yaml
69
+ plots:
70
+ - type: line
71
+ x: [1, 2, 3, 4, 5] # Inline array (less flexible)
72
+ y: [1, 4, 9, 16, 25]
73
+ color: blue
74
+ ```
75
+
76
+ ### Full Example
77
+ ```yaml
78
+ figure:
79
+ width_mm: 85 # Nature single-column width
80
+ height_mm: 60
81
+ plots:
82
+ - type: scatter
83
+ data_file: experiment.csv
84
+ x: time_hours
85
+ y: concentration_mm
86
+ color: blue
87
+ label: "Data"
88
+ xlabel: "Time (h)"
89
+ ylabel: "Concentration (mM)"
90
+ title: "Enzyme Kinetics"
91
+ legend: true
92
+ stat_annotations:
93
+ - x1: 1
94
+ x2: 3
95
+ p_value: 0.01
96
+ style: stars
97
+ ```
98
+
99
+ ## Statistical Annotations
100
+ ```python
101
+ # Method 1: Via stx.plt (Python API)
102
+ ax.add_stat_annotation(x1=0, x2=1, p_value=0.01, style="stars")
103
+
104
+ # Method 2: Via MCP spec (declarative)
105
+ stat_annotations:
106
+ - x1: 0
107
+ x2: 1
108
+ p_value: 0.01 # Converts to ** automatically
109
+ ```
110
+
111
+ ## Color Palette (COLORS=stx.INJECTED)
112
+ ```python
113
+ COLORS.blue, COLORS.red, COLORS.green, COLORS.orange
114
+ COLORS.purple, COLORS.navy, COLORS.pink, COLORS.brown
115
+ ```
116
+
117
+ ## For Detailed FigRecipe Documentation
118
+ See figrecipe MCP resources directly:
119
+ - figrecipe://cheatsheet - Quick reference
120
+ - figrecipe://api/core - Full API documentation
121
+ - figrecipe://mcp-spec - Declarative spec format
122
+
123
+ ## Supported Plot Types
124
+ line, scatter, bar, barh, hist, boxplot, violinplot, imshow, heatmap,
125
+ errorbar, fill_between, contour, contourf, pie, stem
126
+ """
127
+
128
+
129
+ def register_figrecipe_resources(mcp) -> None:
130
+ """Register figrecipe integration resource."""
131
+
132
+ @mcp.resource("scitex://plt-figrecipe")
133
+ def figrecipe_integration() -> str:
134
+ """stx.plt integration with FigRecipe for reproducible figures."""
135
+ return FIGRECIPE_INTEGRATION
136
+
137
+
138
+ # EOF
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2026-01-20
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/_mcp_resources/_formats.py
4
+ """IO format documentation resource."""
5
+
6
+ from __future__ import annotations
7
+
8
+ __all__ = ["register_format_resources"]
9
+
10
+ IO_FORMATS = """\
11
+ # stx.io Supported Formats
12
+ ===========================
13
+
14
+ ## Data Formats
15
+
16
+ | Extension | Type | Save | Load | Notes |
17
+ |-----------|------|:----:|:----:|-------|
18
+ | .csv | DataFrame/Array | ✓ | ✓ | Comma-separated |
19
+ | .tsv | DataFrame/Array | ✓ | ✓ | Tab-separated |
20
+ | .xlsx | DataFrame | ✓ | ✓ | Excel workbook |
21
+ | .json | Dict/List | ✓ | ✓ | JSON format |
22
+ | .yaml/.yml | Dict/List | ✓ | ✓ | YAML format |
23
+ | .pkl/.pickle | Any | ✓ | ✓ | Python pickle |
24
+ | .npy | Array | ✓ | ✓ | NumPy array |
25
+ | .npz | Dict[Array] | ✓ | ✓ | Compressed NumPy |
26
+ | .h5/.hdf5 | Array/Dict | ✓ | ✓ | HDF5 format |
27
+ | .zarr | Array | ✓ | ✓ | Zarr array |
28
+ | .parquet | DataFrame | ✓ | ✓ | Apache Parquet |
29
+ | .feather | DataFrame | ✓ | ✓ | Feather format |
30
+
31
+ ## Image Formats
32
+
33
+ | Extension | Type | Save | Load | Notes |
34
+ |-----------|------|:----:|:----:|-------|
35
+ | .png | Figure/Array | ✓ | ✓ | Lossless, metadata |
36
+ | .jpg/.jpeg | Figure/Array | ✓ | ✓ | Lossy, metadata |
37
+ | .tiff/.tif | Figure/Array | ✓ | ✓ | Scientific imaging |
38
+ | .pdf | Figure | ✓ | ✓ | Vector format |
39
+ | .svg | Figure | ✓ | - | Vector format |
40
+
41
+ ## Scientific Formats
42
+
43
+ | Extension | Type | Load | Notes |
44
+ |-----------|------|:----:|-------|
45
+ | .edf | EEG | ✓ | European Data Format |
46
+ | .fif | MNE | ✓ | MNE-Python |
47
+ | .set | EEGLAB | ✓ | EEGLAB format |
48
+ | .mat | MATLAB | ✓ | MATLAB files |
49
+
50
+ ## PyTorch Formats
51
+
52
+ | Extension | Type | Save | Load |
53
+ |-----------|------|:----:|:----:|
54
+ | .pt | Tensor/Model | ✓ | ✓ |
55
+ | .pth | Model | ✓ | ✓ |
56
+
57
+ ## Usage Notes
58
+
59
+ 1. **Extension determines handler**: `stx.io.save(df, "data.csv")` uses CSV
60
+ 2. **Metadata embedding**: PNG/JPEG support embedded metadata
61
+ 3. **Figure auto-CSV**: Saving figures also exports plotted data as CSV
62
+ 4. **Symlink support**: `symlink_to="./data"` creates symlinks
63
+
64
+ ## Examples
65
+
66
+ ```python
67
+ import scitex as stx
68
+ import pandas as pd
69
+ import numpy as np
70
+
71
+ # DataFrame
72
+ df = pd.DataFrame({"x": [1, 2], "y": [3, 4]})
73
+ stx.io.save(df, "data.csv")
74
+ stx.io.save(df, "data.parquet")
75
+
76
+ # NumPy
77
+ arr = np.random.randn(100, 100)
78
+ stx.io.save(arr, "array.npy")
79
+ stx.io.save(arr, "array.npz")
80
+
81
+ # Any Python object
82
+ stx.io.save({"config": "value"}, "config.yaml")
83
+ stx.io.save(complex_obj, "obj.pkl")
84
+
85
+ # Figure with auto-CSV
86
+ fig, ax = stx.plt.subplots()
87
+ ax.stx_line([1, 2, 3], [4, 5, 6])
88
+ stx.io.save(fig, "plot.png") # Creates plot.png + plot.csv
89
+ ```
90
+ """
91
+
92
+
93
+ def register_format_resources(mcp) -> None:
94
+ """Register IO formats resource."""
95
+
96
+ @mcp.resource("scitex://io-formats")
97
+ def io_formats() -> str:
98
+ """List all supported file formats for stx.io."""
99
+ return IO_FORMATS
100
+
101
+
102
+ # EOF