scitex 2.0.0__py2.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 (572) hide show
  1. scitex/__init__.py +73 -0
  2. scitex/__main__.py +89 -0
  3. scitex/__version__.py +14 -0
  4. scitex/_sh.py +59 -0
  5. scitex/ai/_LearningCurveLogger.py +583 -0
  6. scitex/ai/__Classifiers.py +101 -0
  7. scitex/ai/__init__.py +55 -0
  8. scitex/ai/_gen_ai/_Anthropic.py +173 -0
  9. scitex/ai/_gen_ai/_BaseGenAI.py +336 -0
  10. scitex/ai/_gen_ai/_DeepSeek.py +175 -0
  11. scitex/ai/_gen_ai/_Google.py +161 -0
  12. scitex/ai/_gen_ai/_Groq.py +97 -0
  13. scitex/ai/_gen_ai/_Llama.py +142 -0
  14. scitex/ai/_gen_ai/_OpenAI.py +230 -0
  15. scitex/ai/_gen_ai/_PARAMS.py +565 -0
  16. scitex/ai/_gen_ai/_Perplexity.py +191 -0
  17. scitex/ai/_gen_ai/__init__.py +32 -0
  18. scitex/ai/_gen_ai/_calc_cost.py +78 -0
  19. scitex/ai/_gen_ai/_format_output_func.py +183 -0
  20. scitex/ai/_gen_ai/_genai_factory.py +71 -0
  21. scitex/ai/act/__init__.py +8 -0
  22. scitex/ai/act/_define.py +11 -0
  23. scitex/ai/classification/__init__.py +7 -0
  24. scitex/ai/classification/classification_reporter.py +1137 -0
  25. scitex/ai/classification/classifier_server.py +131 -0
  26. scitex/ai/classification/classifiers.py +101 -0
  27. scitex/ai/classification_reporter.py +1161 -0
  28. scitex/ai/classifier_server.py +131 -0
  29. scitex/ai/clustering/__init__.py +11 -0
  30. scitex/ai/clustering/_pca.py +115 -0
  31. scitex/ai/clustering/_umap.py +376 -0
  32. scitex/ai/early_stopping.py +149 -0
  33. scitex/ai/feature_extraction/__init__.py +56 -0
  34. scitex/ai/feature_extraction/vit.py +148 -0
  35. scitex/ai/genai/__init__.py +277 -0
  36. scitex/ai/genai/anthropic.py +177 -0
  37. scitex/ai/genai/anthropic_provider.py +320 -0
  38. scitex/ai/genai/anthropic_refactored.py +109 -0
  39. scitex/ai/genai/auth_manager.py +200 -0
  40. scitex/ai/genai/base_genai.py +336 -0
  41. scitex/ai/genai/base_provider.py +291 -0
  42. scitex/ai/genai/calc_cost.py +78 -0
  43. scitex/ai/genai/chat_history.py +307 -0
  44. scitex/ai/genai/cost_tracker.py +276 -0
  45. scitex/ai/genai/deepseek.py +188 -0
  46. scitex/ai/genai/deepseek_provider.py +251 -0
  47. scitex/ai/genai/format_output_func.py +183 -0
  48. scitex/ai/genai/genai_factory.py +71 -0
  49. scitex/ai/genai/google.py +169 -0
  50. scitex/ai/genai/google_provider.py +228 -0
  51. scitex/ai/genai/groq.py +104 -0
  52. scitex/ai/genai/groq_provider.py +248 -0
  53. scitex/ai/genai/image_processor.py +250 -0
  54. scitex/ai/genai/llama.py +155 -0
  55. scitex/ai/genai/llama_provider.py +214 -0
  56. scitex/ai/genai/mock_provider.py +127 -0
  57. scitex/ai/genai/model_registry.py +304 -0
  58. scitex/ai/genai/openai.py +230 -0
  59. scitex/ai/genai/openai_provider.py +293 -0
  60. scitex/ai/genai/params.py +565 -0
  61. scitex/ai/genai/perplexity.py +202 -0
  62. scitex/ai/genai/perplexity_provider.py +205 -0
  63. scitex/ai/genai/provider_base.py +302 -0
  64. scitex/ai/genai/provider_factory.py +370 -0
  65. scitex/ai/genai/response_handler.py +235 -0
  66. scitex/ai/layer/_Pass.py +21 -0
  67. scitex/ai/layer/__init__.py +10 -0
  68. scitex/ai/layer/_switch.py +8 -0
  69. scitex/ai/loss/_L1L2Losses.py +34 -0
  70. scitex/ai/loss/__init__.py +12 -0
  71. scitex/ai/loss/multi_task_loss.py +47 -0
  72. scitex/ai/metrics/__init__.py +9 -0
  73. scitex/ai/metrics/_bACC.py +51 -0
  74. scitex/ai/metrics/silhoute_score_block.py +496 -0
  75. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
  76. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
  77. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
  78. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
  79. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
  80. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
  81. scitex/ai/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
  82. scitex/ai/optim/__init__.py +13 -0
  83. scitex/ai/optim/_get_set.py +31 -0
  84. scitex/ai/optim/_optimizers.py +71 -0
  85. scitex/ai/plt/__init__.py +21 -0
  86. scitex/ai/plt/_conf_mat.py +592 -0
  87. scitex/ai/plt/_learning_curve.py +194 -0
  88. scitex/ai/plt/_optuna_study.py +111 -0
  89. scitex/ai/plt/aucs/__init__.py +2 -0
  90. scitex/ai/plt/aucs/example.py +60 -0
  91. scitex/ai/plt/aucs/pre_rec_auc.py +223 -0
  92. scitex/ai/plt/aucs/roc_auc.py +246 -0
  93. scitex/ai/sampling/undersample.py +29 -0
  94. scitex/ai/sk/__init__.py +11 -0
  95. scitex/ai/sk/_clf.py +58 -0
  96. scitex/ai/sk/_to_sktime.py +100 -0
  97. scitex/ai/sklearn/__init__.py +26 -0
  98. scitex/ai/sklearn/clf.py +58 -0
  99. scitex/ai/sklearn/to_sktime.py +100 -0
  100. scitex/ai/training/__init__.py +7 -0
  101. scitex/ai/training/early_stopping.py +150 -0
  102. scitex/ai/training/learning_curve_logger.py +555 -0
  103. scitex/ai/utils/__init__.py +22 -0
  104. scitex/ai/utils/_check_params.py +50 -0
  105. scitex/ai/utils/_default_dataset.py +46 -0
  106. scitex/ai/utils/_format_samples_for_sktime.py +26 -0
  107. scitex/ai/utils/_label_encoder.py +134 -0
  108. scitex/ai/utils/_merge_labels.py +22 -0
  109. scitex/ai/utils/_sliding_window_data_augmentation.py +11 -0
  110. scitex/ai/utils/_under_sample.py +51 -0
  111. scitex/ai/utils/_verify_n_gpus.py +16 -0
  112. scitex/ai/utils/grid_search.py +148 -0
  113. scitex/context/__init__.py +9 -0
  114. scitex/context/_suppress_output.py +38 -0
  115. scitex/db/_BaseMixins/_BaseBackupMixin.py +30 -0
  116. scitex/db/_BaseMixins/_BaseBatchMixin.py +31 -0
  117. scitex/db/_BaseMixins/_BaseBlobMixin.py +81 -0
  118. scitex/db/_BaseMixins/_BaseConnectionMixin.py +43 -0
  119. scitex/db/_BaseMixins/_BaseImportExportMixin.py +39 -0
  120. scitex/db/_BaseMixins/_BaseIndexMixin.py +29 -0
  121. scitex/db/_BaseMixins/_BaseMaintenanceMixin.py +33 -0
  122. scitex/db/_BaseMixins/_BaseQueryMixin.py +52 -0
  123. scitex/db/_BaseMixins/_BaseRowMixin.py +32 -0
  124. scitex/db/_BaseMixins/_BaseSchemaMixin.py +44 -0
  125. scitex/db/_BaseMixins/_BaseTableMixin.py +66 -0
  126. scitex/db/_BaseMixins/_BaseTransactionMixin.py +52 -0
  127. scitex/db/_BaseMixins/__init__.py +30 -0
  128. scitex/db/_PostgreSQL.py +126 -0
  129. scitex/db/_PostgreSQLMixins/_BackupMixin.py +166 -0
  130. scitex/db/_PostgreSQLMixins/_BatchMixin.py +82 -0
  131. scitex/db/_PostgreSQLMixins/_BlobMixin.py +231 -0
  132. scitex/db/_PostgreSQLMixins/_ConnectionMixin.py +92 -0
  133. scitex/db/_PostgreSQLMixins/_ImportExportMixin.py +59 -0
  134. scitex/db/_PostgreSQLMixins/_IndexMixin.py +64 -0
  135. scitex/db/_PostgreSQLMixins/_MaintenanceMixin.py +175 -0
  136. scitex/db/_PostgreSQLMixins/_QueryMixin.py +108 -0
  137. scitex/db/_PostgreSQLMixins/_RowMixin.py +75 -0
  138. scitex/db/_PostgreSQLMixins/_SchemaMixin.py +126 -0
  139. scitex/db/_PostgreSQLMixins/_TableMixin.py +176 -0
  140. scitex/db/_PostgreSQLMixins/_TransactionMixin.py +57 -0
  141. scitex/db/_PostgreSQLMixins/__init__.py +34 -0
  142. scitex/db/_SQLite3.py +2136 -0
  143. scitex/db/_SQLite3Mixins/_BatchMixin.py +243 -0
  144. scitex/db/_SQLite3Mixins/_BlobMixin.py +229 -0
  145. scitex/db/_SQLite3Mixins/_ConnectionMixin.py +108 -0
  146. scitex/db/_SQLite3Mixins/_ImportExportMixin.py +80 -0
  147. scitex/db/_SQLite3Mixins/_IndexMixin.py +32 -0
  148. scitex/db/_SQLite3Mixins/_MaintenanceMixin.py +176 -0
  149. scitex/db/_SQLite3Mixins/_QueryMixin.py +83 -0
  150. scitex/db/_SQLite3Mixins/_RowMixin.py +75 -0
  151. scitex/db/_SQLite3Mixins/_TableMixin.py +183 -0
  152. scitex/db/_SQLite3Mixins/_TransactionMixin.py +71 -0
  153. scitex/db/_SQLite3Mixins/__init__.py +30 -0
  154. scitex/db/__init__.py +14 -0
  155. scitex/db/_delete_duplicates.py +397 -0
  156. scitex/db/_inspect.py +163 -0
  157. scitex/decorators/__init__.py +54 -0
  158. scitex/decorators/_auto_order.py +172 -0
  159. scitex/decorators/_batch_fn.py +127 -0
  160. scitex/decorators/_cache_disk.py +32 -0
  161. scitex/decorators/_cache_mem.py +12 -0
  162. scitex/decorators/_combined.py +98 -0
  163. scitex/decorators/_converters.py +282 -0
  164. scitex/decorators/_deprecated.py +26 -0
  165. scitex/decorators/_not_implemented.py +30 -0
  166. scitex/decorators/_numpy_fn.py +86 -0
  167. scitex/decorators/_pandas_fn.py +121 -0
  168. scitex/decorators/_preserve_doc.py +19 -0
  169. scitex/decorators/_signal_fn.py +95 -0
  170. scitex/decorators/_timeout.py +55 -0
  171. scitex/decorators/_torch_fn.py +136 -0
  172. scitex/decorators/_wrap.py +39 -0
  173. scitex/decorators/_xarray_fn.py +88 -0
  174. scitex/dev/__init__.py +15 -0
  175. scitex/dev/_analyze_code_flow.py +284 -0
  176. scitex/dev/_reload.py +59 -0
  177. scitex/dict/_DotDict.py +442 -0
  178. scitex/dict/__init__.py +18 -0
  179. scitex/dict/_listed_dict.py +42 -0
  180. scitex/dict/_pop_keys.py +36 -0
  181. scitex/dict/_replace.py +13 -0
  182. scitex/dict/_safe_merge.py +62 -0
  183. scitex/dict/_to_str.py +32 -0
  184. scitex/dsp/__init__.py +72 -0
  185. scitex/dsp/_crop.py +122 -0
  186. scitex/dsp/_demo_sig.py +331 -0
  187. scitex/dsp/_detect_ripples.py +212 -0
  188. scitex/dsp/_ensure_3d.py +18 -0
  189. scitex/dsp/_hilbert.py +78 -0
  190. scitex/dsp/_listen.py +702 -0
  191. scitex/dsp/_misc.py +30 -0
  192. scitex/dsp/_mne.py +32 -0
  193. scitex/dsp/_modulation_index.py +79 -0
  194. scitex/dsp/_pac.py +319 -0
  195. scitex/dsp/_psd.py +102 -0
  196. scitex/dsp/_resample.py +65 -0
  197. scitex/dsp/_time.py +36 -0
  198. scitex/dsp/_transform.py +68 -0
  199. scitex/dsp/_wavelet.py +212 -0
  200. scitex/dsp/add_noise.py +111 -0
  201. scitex/dsp/example.py +253 -0
  202. scitex/dsp/filt.py +155 -0
  203. scitex/dsp/norm.py +18 -0
  204. scitex/dsp/params.py +51 -0
  205. scitex/dsp/reference.py +43 -0
  206. scitex/dsp/template.py +25 -0
  207. scitex/dsp/utils/__init__.py +15 -0
  208. scitex/dsp/utils/_differential_bandpass_filters.py +120 -0
  209. scitex/dsp/utils/_ensure_3d.py +18 -0
  210. scitex/dsp/utils/_ensure_even_len.py +10 -0
  211. scitex/dsp/utils/_zero_pad.py +48 -0
  212. scitex/dsp/utils/filter.py +408 -0
  213. scitex/dsp/utils/pac.py +177 -0
  214. scitex/dt/__init__.py +8 -0
  215. scitex/dt/_linspace.py +130 -0
  216. scitex/etc/__init__.py +15 -0
  217. scitex/etc/wait_key.py +34 -0
  218. scitex/gen/_DimHandler.py +196 -0
  219. scitex/gen/_TimeStamper.py +244 -0
  220. scitex/gen/__init__.py +95 -0
  221. scitex/gen/_alternate_kwarg.py +13 -0
  222. scitex/gen/_cache.py +11 -0
  223. scitex/gen/_check_host.py +34 -0
  224. scitex/gen/_ci.py +12 -0
  225. scitex/gen/_close.py +222 -0
  226. scitex/gen/_embed.py +78 -0
  227. scitex/gen/_inspect_module.py +257 -0
  228. scitex/gen/_is_ipython.py +12 -0
  229. scitex/gen/_less.py +48 -0
  230. scitex/gen/_list_packages.py +139 -0
  231. scitex/gen/_mat2py.py +88 -0
  232. scitex/gen/_norm.py +170 -0
  233. scitex/gen/_paste.py +18 -0
  234. scitex/gen/_print_config.py +84 -0
  235. scitex/gen/_shell.py +48 -0
  236. scitex/gen/_src.py +111 -0
  237. scitex/gen/_start.py +451 -0
  238. scitex/gen/_symlink.py +55 -0
  239. scitex/gen/_symlog.py +27 -0
  240. scitex/gen/_tee.py +238 -0
  241. scitex/gen/_title2path.py +60 -0
  242. scitex/gen/_title_case.py +88 -0
  243. scitex/gen/_to_even.py +84 -0
  244. scitex/gen/_to_odd.py +34 -0
  245. scitex/gen/_to_rank.py +39 -0
  246. scitex/gen/_transpose.py +37 -0
  247. scitex/gen/_type.py +78 -0
  248. scitex/gen/_var_info.py +73 -0
  249. scitex/gen/_wrap.py +17 -0
  250. scitex/gen/_xml2dict.py +76 -0
  251. scitex/gen/misc.py +730 -0
  252. scitex/gen/path.py +0 -0
  253. scitex/general/__init__.py +5 -0
  254. scitex/gists/_SigMacro_processFigure_S.py +128 -0
  255. scitex/gists/_SigMacro_toBlue.py +172 -0
  256. scitex/gists/__init__.py +12 -0
  257. scitex/io/_H5Explorer.py +292 -0
  258. scitex/io/__init__.py +82 -0
  259. scitex/io/_cache.py +101 -0
  260. scitex/io/_flush.py +24 -0
  261. scitex/io/_glob.py +103 -0
  262. scitex/io/_json2md.py +113 -0
  263. scitex/io/_load.py +168 -0
  264. scitex/io/_load_configs.py +146 -0
  265. scitex/io/_load_modules/__init__.py +38 -0
  266. scitex/io/_load_modules/_catboost.py +66 -0
  267. scitex/io/_load_modules/_con.py +20 -0
  268. scitex/io/_load_modules/_db.py +24 -0
  269. scitex/io/_load_modules/_docx.py +42 -0
  270. scitex/io/_load_modules/_eeg.py +110 -0
  271. scitex/io/_load_modules/_hdf5.py +196 -0
  272. scitex/io/_load_modules/_image.py +19 -0
  273. scitex/io/_load_modules/_joblib.py +19 -0
  274. scitex/io/_load_modules/_json.py +18 -0
  275. scitex/io/_load_modules/_markdown.py +103 -0
  276. scitex/io/_load_modules/_matlab.py +37 -0
  277. scitex/io/_load_modules/_numpy.py +39 -0
  278. scitex/io/_load_modules/_optuna.py +155 -0
  279. scitex/io/_load_modules/_pandas.py +69 -0
  280. scitex/io/_load_modules/_pdf.py +31 -0
  281. scitex/io/_load_modules/_pickle.py +24 -0
  282. scitex/io/_load_modules/_torch.py +16 -0
  283. scitex/io/_load_modules/_txt.py +126 -0
  284. scitex/io/_load_modules/_xml.py +49 -0
  285. scitex/io/_load_modules/_yaml.py +23 -0
  286. scitex/io/_mv_to_tmp.py +19 -0
  287. scitex/io/_path.py +286 -0
  288. scitex/io/_reload.py +78 -0
  289. scitex/io/_save.py +539 -0
  290. scitex/io/_save_modules/__init__.py +66 -0
  291. scitex/io/_save_modules/_catboost.py +22 -0
  292. scitex/io/_save_modules/_csv.py +89 -0
  293. scitex/io/_save_modules/_excel.py +49 -0
  294. scitex/io/_save_modules/_hdf5.py +249 -0
  295. scitex/io/_save_modules/_html.py +48 -0
  296. scitex/io/_save_modules/_image.py +140 -0
  297. scitex/io/_save_modules/_joblib.py +25 -0
  298. scitex/io/_save_modules/_json.py +25 -0
  299. scitex/io/_save_modules/_listed_dfs_as_csv.py +57 -0
  300. scitex/io/_save_modules/_listed_scalars_as_csv.py +42 -0
  301. scitex/io/_save_modules/_matlab.py +24 -0
  302. scitex/io/_save_modules/_mp4.py +29 -0
  303. scitex/io/_save_modules/_numpy.py +57 -0
  304. scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +38 -0
  305. scitex/io/_save_modules/_pickle.py +45 -0
  306. scitex/io/_save_modules/_plotly.py +27 -0
  307. scitex/io/_save_modules/_text.py +23 -0
  308. scitex/io/_save_modules/_torch.py +26 -0
  309. scitex/io/_save_modules/_yaml.py +29 -0
  310. scitex/life/__init__.py +10 -0
  311. scitex/life/_monitor_rain.py +49 -0
  312. scitex/linalg/__init__.py +17 -0
  313. scitex/linalg/_distance.py +63 -0
  314. scitex/linalg/_geometric_median.py +64 -0
  315. scitex/linalg/_misc.py +73 -0
  316. scitex/nn/_AxiswiseDropout.py +27 -0
  317. scitex/nn/_BNet.py +126 -0
  318. scitex/nn/_BNet_Res.py +164 -0
  319. scitex/nn/_ChannelGainChanger.py +44 -0
  320. scitex/nn/_DropoutChannels.py +50 -0
  321. scitex/nn/_Filters.py +489 -0
  322. scitex/nn/_FreqGainChanger.py +110 -0
  323. scitex/nn/_GaussianFilter.py +48 -0
  324. scitex/nn/_Hilbert.py +111 -0
  325. scitex/nn/_MNet_1000.py +157 -0
  326. scitex/nn/_ModulationIndex.py +221 -0
  327. scitex/nn/_PAC.py +414 -0
  328. scitex/nn/_PSD.py +40 -0
  329. scitex/nn/_ResNet1D.py +120 -0
  330. scitex/nn/_SpatialAttention.py +25 -0
  331. scitex/nn/_Spectrogram.py +161 -0
  332. scitex/nn/_SwapChannels.py +50 -0
  333. scitex/nn/_TransposeLayer.py +19 -0
  334. scitex/nn/_Wavelet.py +183 -0
  335. scitex/nn/__init__.py +63 -0
  336. scitex/os/__init__.py +8 -0
  337. scitex/os/_mv.py +50 -0
  338. scitex/parallel/__init__.py +8 -0
  339. scitex/parallel/_run.py +151 -0
  340. scitex/path/__init__.py +33 -0
  341. scitex/path/_clean.py +52 -0
  342. scitex/path/_find.py +108 -0
  343. scitex/path/_get_module_path.py +51 -0
  344. scitex/path/_get_spath.py +35 -0
  345. scitex/path/_getsize.py +18 -0
  346. scitex/path/_increment_version.py +87 -0
  347. scitex/path/_mk_spath.py +51 -0
  348. scitex/path/_path.py +19 -0
  349. scitex/path/_split.py +23 -0
  350. scitex/path/_this_path.py +19 -0
  351. scitex/path/_version.py +101 -0
  352. scitex/pd/__init__.py +41 -0
  353. scitex/pd/_find_indi.py +126 -0
  354. scitex/pd/_find_pval.py +113 -0
  355. scitex/pd/_force_df.py +154 -0
  356. scitex/pd/_from_xyz.py +71 -0
  357. scitex/pd/_ignore_SettingWithCopyWarning.py +34 -0
  358. scitex/pd/_melt_cols.py +81 -0
  359. scitex/pd/_merge_columns.py +221 -0
  360. scitex/pd/_mv.py +63 -0
  361. scitex/pd/_replace.py +62 -0
  362. scitex/pd/_round.py +93 -0
  363. scitex/pd/_slice.py +63 -0
  364. scitex/pd/_sort.py +91 -0
  365. scitex/pd/_to_numeric.py +53 -0
  366. scitex/pd/_to_xy.py +59 -0
  367. scitex/pd/_to_xyz.py +110 -0
  368. scitex/plt/__init__.py +36 -0
  369. scitex/plt/_subplots/_AxesWrapper.py +182 -0
  370. scitex/plt/_subplots/_AxisWrapper.py +249 -0
  371. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +414 -0
  372. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +896 -0
  373. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +368 -0
  374. scitex/plt/_subplots/_AxisWrapperMixins/_TrackingMixin.py +185 -0
  375. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +16 -0
  376. scitex/plt/_subplots/_FigWrapper.py +226 -0
  377. scitex/plt/_subplots/_SubplotsWrapper.py +171 -0
  378. scitex/plt/_subplots/__init__.py +111 -0
  379. scitex/plt/_subplots/_export_as_csv.py +232 -0
  380. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +61 -0
  381. scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +90 -0
  382. scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +49 -0
  383. scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +46 -0
  384. scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +39 -0
  385. scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +125 -0
  386. scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +72 -0
  387. scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +34 -0
  388. scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +36 -0
  389. scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +79 -0
  390. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +59 -0
  391. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +32 -0
  392. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +79 -0
  393. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +75 -0
  394. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +64 -0
  395. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +44 -0
  396. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +70 -0
  397. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +66 -0
  398. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +95 -0
  399. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +67 -0
  400. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +52 -0
  401. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +46 -0
  402. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +46 -0
  403. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +46 -0
  404. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +46 -0
  405. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +44 -0
  406. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +103 -0
  407. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +82 -0
  408. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +58 -0
  409. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +117 -0
  410. scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +30 -0
  411. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +51 -0
  412. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +93 -0
  413. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +94 -0
  414. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +92 -0
  415. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +65 -0
  416. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +59 -0
  417. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +58 -0
  418. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +45 -0
  419. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +70 -0
  420. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +75 -0
  421. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +75 -0
  422. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +155 -0
  423. scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +64 -0
  424. scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +77 -0
  425. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +210 -0
  426. scitex/plt/_subplots/_export_as_csv_formatters/verify_formatters.py +342 -0
  427. scitex/plt/_subplots/_export_as_csv_formatters.py +115 -0
  428. scitex/plt/_tpl.py +28 -0
  429. scitex/plt/ax/__init__.py +114 -0
  430. scitex/plt/ax/_plot/__init__.py +53 -0
  431. scitex/plt/ax/_plot/_plot_circular_hist.py +124 -0
  432. scitex/plt/ax/_plot/_plot_conf_mat.py +136 -0
  433. scitex/plt/ax/_plot/_plot_cube.py +57 -0
  434. scitex/plt/ax/_plot/_plot_ecdf.py +84 -0
  435. scitex/plt/ax/_plot/_plot_fillv.py +55 -0
  436. scitex/plt/ax/_plot/_plot_heatmap.py +266 -0
  437. scitex/plt/ax/_plot/_plot_image.py +94 -0
  438. scitex/plt/ax/_plot/_plot_joyplot.py +76 -0
  439. scitex/plt/ax/_plot/_plot_raster.py +172 -0
  440. scitex/plt/ax/_plot/_plot_rectangle.py +69 -0
  441. scitex/plt/ax/_plot/_plot_scatter_hist.py +133 -0
  442. scitex/plt/ax/_plot/_plot_shaded_line.py +142 -0
  443. scitex/plt/ax/_plot/_plot_statistical_shaded_line.py +221 -0
  444. scitex/plt/ax/_plot/_plot_violin.py +343 -0
  445. scitex/plt/ax/_style/__init__.py +38 -0
  446. scitex/plt/ax/_style/_add_marginal_ax.py +44 -0
  447. scitex/plt/ax/_style/_add_panel.py +92 -0
  448. scitex/plt/ax/_style/_extend.py +64 -0
  449. scitex/plt/ax/_style/_force_aspect.py +37 -0
  450. scitex/plt/ax/_style/_format_label.py +23 -0
  451. scitex/plt/ax/_style/_hide_spines.py +84 -0
  452. scitex/plt/ax/_style/_map_ticks.py +182 -0
  453. scitex/plt/ax/_style/_rotate_labels.py +215 -0
  454. scitex/plt/ax/_style/_sci_note.py +279 -0
  455. scitex/plt/ax/_style/_set_log_scale.py +299 -0
  456. scitex/plt/ax/_style/_set_meta.py +261 -0
  457. scitex/plt/ax/_style/_set_n_ticks.py +37 -0
  458. scitex/plt/ax/_style/_set_size.py +16 -0
  459. scitex/plt/ax/_style/_set_supxyt.py +116 -0
  460. scitex/plt/ax/_style/_set_ticks.py +276 -0
  461. scitex/plt/ax/_style/_set_xyt.py +121 -0
  462. scitex/plt/ax/_style/_share_axes.py +264 -0
  463. scitex/plt/ax/_style/_shift.py +139 -0
  464. scitex/plt/ax/_style/_show_spines.py +333 -0
  465. scitex/plt/color/_PARAMS.py +70 -0
  466. scitex/plt/color/__init__.py +52 -0
  467. scitex/plt/color/_add_hue_col.py +41 -0
  468. scitex/plt/color/_colors.py +205 -0
  469. scitex/plt/color/_get_colors_from_cmap.py +134 -0
  470. scitex/plt/color/_interpolate.py +29 -0
  471. scitex/plt/color/_vizualize_colors.py +54 -0
  472. scitex/plt/utils/__init__.py +44 -0
  473. scitex/plt/utils/_calc_bacc_from_conf_mat.py +46 -0
  474. scitex/plt/utils/_calc_nice_ticks.py +101 -0
  475. scitex/plt/utils/_close.py +68 -0
  476. scitex/plt/utils/_colorbar.py +96 -0
  477. scitex/plt/utils/_configure_mpl.py +295 -0
  478. scitex/plt/utils/_histogram_utils.py +132 -0
  479. scitex/plt/utils/_im2grid.py +70 -0
  480. scitex/plt/utils/_is_valid_axis.py +78 -0
  481. scitex/plt/utils/_mk_colorbar.py +65 -0
  482. scitex/plt/utils/_mk_patches.py +26 -0
  483. scitex/plt/utils/_scientific_captions.py +638 -0
  484. scitex/plt/utils/_scitex_config.py +223 -0
  485. scitex/reproduce/__init__.py +14 -0
  486. scitex/reproduce/_fix_seeds.py +45 -0
  487. scitex/reproduce/_gen_ID.py +55 -0
  488. scitex/reproduce/_gen_timestamp.py +35 -0
  489. scitex/res/__init__.py +5 -0
  490. scitex/resource/__init__.py +13 -0
  491. scitex/resource/_get_processor_usages.py +281 -0
  492. scitex/resource/_get_specs.py +280 -0
  493. scitex/resource/_log_processor_usages.py +190 -0
  494. scitex/resource/_utils/__init__.py +31 -0
  495. scitex/resource/_utils/_get_env_info.py +481 -0
  496. scitex/resource/limit_ram.py +33 -0
  497. scitex/scholar/__init__.py +24 -0
  498. scitex/scholar/_local_search.py +454 -0
  499. scitex/scholar/_paper.py +244 -0
  500. scitex/scholar/_pdf_downloader.py +325 -0
  501. scitex/scholar/_search.py +393 -0
  502. scitex/scholar/_vector_search.py +370 -0
  503. scitex/scholar/_web_sources.py +457 -0
  504. scitex/stats/__init__.py +31 -0
  505. scitex/stats/_calc_partial_corr.py +17 -0
  506. scitex/stats/_corr_test_multi.py +94 -0
  507. scitex/stats/_corr_test_wrapper.py +115 -0
  508. scitex/stats/_describe_wrapper.py +90 -0
  509. scitex/stats/_multiple_corrections.py +63 -0
  510. scitex/stats/_nan_stats.py +93 -0
  511. scitex/stats/_p2stars.py +116 -0
  512. scitex/stats/_p2stars_wrapper.py +56 -0
  513. scitex/stats/_statistical_tests.py +73 -0
  514. scitex/stats/desc/__init__.py +40 -0
  515. scitex/stats/desc/_describe.py +189 -0
  516. scitex/stats/desc/_nan.py +289 -0
  517. scitex/stats/desc/_real.py +94 -0
  518. scitex/stats/multiple/__init__.py +14 -0
  519. scitex/stats/multiple/_bonferroni_correction.py +72 -0
  520. scitex/stats/multiple/_fdr_correction.py +400 -0
  521. scitex/stats/multiple/_multicompair.py +28 -0
  522. scitex/stats/tests/__corr_test.py +277 -0
  523. scitex/stats/tests/__corr_test_multi.py +343 -0
  524. scitex/stats/tests/__corr_test_single.py +277 -0
  525. scitex/stats/tests/__init__.py +22 -0
  526. scitex/stats/tests/_brunner_munzel_test.py +192 -0
  527. scitex/stats/tests/_nocorrelation_test.py +28 -0
  528. scitex/stats/tests/_smirnov_grubbs.py +98 -0
  529. scitex/str/__init__.py +113 -0
  530. scitex/str/_clean_path.py +75 -0
  531. scitex/str/_color_text.py +52 -0
  532. scitex/str/_decapitalize.py +58 -0
  533. scitex/str/_factor_out_digits.py +281 -0
  534. scitex/str/_format_plot_text.py +498 -0
  535. scitex/str/_grep.py +48 -0
  536. scitex/str/_latex.py +155 -0
  537. scitex/str/_latex_fallback.py +471 -0
  538. scitex/str/_mask_api.py +39 -0
  539. scitex/str/_mask_api_key.py +8 -0
  540. scitex/str/_parse.py +158 -0
  541. scitex/str/_print_block.py +47 -0
  542. scitex/str/_print_debug.py +68 -0
  543. scitex/str/_printc.py +62 -0
  544. scitex/str/_readable_bytes.py +38 -0
  545. scitex/str/_remove_ansi.py +23 -0
  546. scitex/str/_replace.py +134 -0
  547. scitex/str/_search.py +125 -0
  548. scitex/str/_squeeze_space.py +36 -0
  549. scitex/tex/__init__.py +10 -0
  550. scitex/tex/_preview.py +103 -0
  551. scitex/tex/_to_vec.py +116 -0
  552. scitex/torch/__init__.py +18 -0
  553. scitex/torch/_apply_to.py +34 -0
  554. scitex/torch/_nan_funcs.py +77 -0
  555. scitex/types/_ArrayLike.py +44 -0
  556. scitex/types/_ColorLike.py +21 -0
  557. scitex/types/__init__.py +14 -0
  558. scitex/types/_is_listed_X.py +70 -0
  559. scitex/utils/__init__.py +22 -0
  560. scitex/utils/_compress_hdf5.py +116 -0
  561. scitex/utils/_email.py +120 -0
  562. scitex/utils/_grid.py +148 -0
  563. scitex/utils/_notify.py +247 -0
  564. scitex/utils/_search.py +121 -0
  565. scitex/web/__init__.py +38 -0
  566. scitex/web/_search_pubmed.py +438 -0
  567. scitex/web/_summarize_url.py +158 -0
  568. scitex-2.0.0.dist-info/METADATA +307 -0
  569. scitex-2.0.0.dist-info/RECORD +572 -0
  570. scitex-2.0.0.dist-info/WHEEL +6 -0
  571. scitex-2.0.0.dist-info/licenses/LICENSE +7 -0
  572. scitex-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,638 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Time-stamp: "2025-06-04 11:17:00 (ywatanabe)"
4
+ # File: ./src/scitex/plt/utils/_scientific_captions.py
5
+
6
+ """
7
+ Functionality:
8
+ Scientific figure caption system for publication-ready figures
9
+ Input:
10
+ Figure objects, caption text, and formatting parameters
11
+ Output:
12
+ Figures with properly formatted scientific captions
13
+ Prerequisites:
14
+ matplotlib, textwrap
15
+ """
16
+
17
+ import matplotlib.pyplot as plt
18
+ import matplotlib.patches as patches
19
+ from matplotlib.patches import FancyBboxPatch
20
+ import textwrap
21
+ from typing import Union, List, Dict, Tuple, Optional
22
+ import re
23
+
24
+
25
+ class ScientificCaption:
26
+ """
27
+ A comprehensive caption system for scientific figures with support for:
28
+ - Figure-level captions
29
+ - Panel-level captions (A, B, C, etc.)
30
+ - Automatic numbering
31
+ - Cross-references
32
+ - Multiple formatting styles
33
+ """
34
+
35
+ def __init__(self):
36
+ self.figure_counter = 0
37
+ self.caption_registry = {}
38
+ self.panel_letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
39
+
40
+ def add_figure_caption(
41
+ self,
42
+ fig,
43
+ caption: str,
44
+ figure_label: str = None,
45
+ style: str = "scientific",
46
+ position: str = "bottom",
47
+ width_ratio: float = 0.9,
48
+ font_size: Union[str, int] = "small",
49
+ wrap_width: int = 80,
50
+ save_to_file: bool = False,
51
+ file_path: str = None
52
+ ) -> str:
53
+ """
54
+ Add a scientific caption to a figure.
55
+
56
+ Parameters
57
+ ----------
58
+ fig : matplotlib.figure.Figure
59
+ The figure to add caption to
60
+ caption : str
61
+ The caption text
62
+ figure_label : str, optional
63
+ Custom figure label (e.g., "Figure 1"), auto-generated if None
64
+ style : str, optional
65
+ Caption style: "scientific", "nature", "ieee", "apa", by default "scientific"
66
+ position : str, optional
67
+ Caption position: "bottom", "top", by default "bottom"
68
+ width_ratio : float, optional
69
+ Width of caption relative to figure width, by default 0.9
70
+ font_size : Union[str, int], optional
71
+ Font size for caption, by default "small"
72
+ wrap_width : int, optional
73
+ Character width for text wrapping, by default 80
74
+ save_to_file : bool, optional
75
+ Whether to save caption to separate file, by default False
76
+ file_path : str, optional
77
+ Path for caption file, by default None
78
+
79
+ Returns
80
+ -------
81
+ str
82
+ The formatted caption text
83
+ """
84
+ # Generate figure label if not provided
85
+ if figure_label is None:
86
+ self.figure_counter += 1
87
+ figure_label = f"Figure {self.figure_counter}"
88
+
89
+ # Format caption according to style
90
+ formatted_caption = self._format_caption(caption, figure_label, style, wrap_width)
91
+
92
+ # Add caption to figure
93
+ self._add_caption_to_figure(fig, formatted_caption, position, width_ratio, font_size)
94
+
95
+ # Register caption
96
+ self.caption_registry[figure_label] = {
97
+ 'text': caption,
98
+ 'formatted': formatted_caption,
99
+ 'style': style,
100
+ 'figure': fig
101
+ }
102
+
103
+ # Save to file if requested
104
+ if save_to_file:
105
+ self._save_caption_to_file(formatted_caption, figure_label, file_path)
106
+
107
+ return formatted_caption
108
+
109
+ def add_panel_captions(
110
+ self,
111
+ fig,
112
+ axes,
113
+ panel_captions: Union[List[str], Dict[str, str]],
114
+ main_caption: str = "",
115
+ figure_label: str = None,
116
+ panel_style: str = "letter_bold",
117
+ position: str = "top_left",
118
+ font_size: Union[str, int] = "medium",
119
+ offset: Tuple[float, float] = (0.02, 0.98)
120
+ ) -> Dict[str, str]:
121
+ """
122
+ Add panel captions (A, B, C, etc.) to subplot panels.
123
+
124
+ Parameters
125
+ ----------
126
+ fig : matplotlib.figure.Figure
127
+ The figure containing panels
128
+ axes : Union[matplotlib.axes.Axes, List, np.ndarray]
129
+ Axes objects for each panel
130
+ panel_captions : Union[List[str], Dict[str, str]]
131
+ Caption text for each panel, either list or dict with panel labels
132
+ main_caption : str, optional
133
+ Main figure caption, by default ""
134
+ figure_label : str, optional
135
+ Figure label, by default None
136
+ panel_style : str, optional
137
+ Panel label style: "letter_bold", "letter_italic", "number", by default "letter_bold"
138
+ position : str, optional
139
+ Panel label position: "top_left", "top_right", "bottom_left", "bottom_right", by default "top_left"
140
+ font_size : Union[str, int], optional
141
+ Font size for panel labels, by default "medium"
142
+ offset : Tuple[float, float], optional
143
+ Position offset for panel labels, by default (0.02, 0.98)
144
+
145
+ Returns
146
+ -------
147
+ Dict[str, str]
148
+ Dictionary mapping panel labels to full caption text
149
+ """
150
+ # Ensure axes is a list
151
+ if not isinstance(axes, (list, tuple)):
152
+ axes = [axes] if hasattr(axes, 'plot') else axes.flatten()
153
+
154
+ # Handle different input formats for panel_captions
155
+ if isinstance(panel_captions, list):
156
+ panel_dict = {self.panel_letters[i]: panel_captions[i]
157
+ for i in range(min(len(panel_captions), len(axes)))}
158
+ else:
159
+ panel_dict = panel_captions
160
+
161
+ # Add panel labels to axes
162
+ formatted_panels = {}
163
+ for i, ax in enumerate(axes):
164
+ if i < len(self.panel_letters):
165
+ panel_letter = self.panel_letters[i]
166
+ if panel_letter in panel_dict:
167
+ formatted_label = self._format_panel_label(panel_letter, panel_style)
168
+ panel_caption = panel_dict[panel_letter]
169
+
170
+ # Add label to axes
171
+ self._add_panel_label_to_axes(ax, formatted_label, position, font_size, offset)
172
+
173
+ formatted_panels[panel_letter] = f"{formatted_label} {panel_caption}"
174
+
175
+ # Add main caption if provided
176
+ if main_caption:
177
+ full_caption = self._combine_panel_and_main_captions(formatted_panels, main_caption)
178
+ self.add_figure_caption(fig, full_caption, figure_label)
179
+
180
+ return formatted_panels
181
+
182
+ def _format_caption(self, caption: str, figure_label: str, style: str, wrap_width: int) -> str:
183
+ """Format caption according to specified style."""
184
+ # Wrap text
185
+ wrapped_text = textwrap.fill(caption, width=wrap_width)
186
+
187
+ if style == "scientific":
188
+ return f"**{figure_label}.** {wrapped_text}"
189
+ elif style == "nature":
190
+ return f"**{figure_label} |** {wrapped_text}"
191
+ elif style == "ieee":
192
+ return f"{figure_label}. {wrapped_text}"
193
+ elif style == "apa":
194
+ return f"*{figure_label}*\n{wrapped_text}"
195
+ else:
196
+ return f"{figure_label}. {wrapped_text}"
197
+
198
+ def _format_panel_label(self, letter: str, style: str) -> str:
199
+ """Format panel label according to style."""
200
+ if style == "letter_bold":
201
+ return f"**{letter}**"
202
+ elif style == "letter_italic":
203
+ return f"*{letter}*"
204
+ elif style == "number":
205
+ return f"**{ord(letter) - ord('A') + 1}**"
206
+ else:
207
+ return f"**{letter}**"
208
+
209
+ def _add_caption_to_figure(self, fig, caption: str, position: str, width_ratio: float, font_size: Union[str, int]):
210
+ """Add caption text to figure."""
211
+ # Calculate position
212
+ if position == "bottom":
213
+ y_pos = 0.02
214
+ va = 'bottom'
215
+ else: # top
216
+ y_pos = 0.98
217
+ va = 'top'
218
+
219
+ # Add caption text
220
+ fig.text(
221
+ 0.5, y_pos, caption,
222
+ ha='center', va=va,
223
+ fontsize=font_size,
224
+ wrap=True,
225
+ bbox=dict(boxstyle="round,pad=0.5", facecolor='white', alpha=0.8)
226
+ )
227
+
228
+ # Adjust layout to accommodate caption
229
+ if position == "bottom":
230
+ fig.subplots_adjust(bottom=0.15)
231
+ else:
232
+ fig.subplots_adjust(top=0.85)
233
+
234
+ def _add_panel_label_to_axes(self, ax, label: str, position: str, font_size: Union[str, int], offset: Tuple[float, float]):
235
+ """Add panel label to individual axes."""
236
+ # Position mapping
237
+ positions = {
238
+ 'top_left': (offset[0], offset[1]),
239
+ 'top_right': (1 - offset[0], offset[1]),
240
+ 'bottom_left': (offset[0], 1 - offset[1]),
241
+ 'bottom_right': (1 - offset[0], 1 - offset[1])
242
+ }
243
+
244
+ x_pos, y_pos = positions.get(position, (offset[0], offset[1]))
245
+
246
+ # Determine alignment
247
+ ha = 'left' if 'left' in position else 'right'
248
+ va = 'top' if 'top' in position else 'bottom'
249
+
250
+ # Add label
251
+ ax.text(
252
+ x_pos, y_pos, label,
253
+ transform=ax.transAxes,
254
+ fontsize=font_size,
255
+ fontweight='bold',
256
+ ha=ha, va=va,
257
+ bbox=dict(boxstyle="round,pad=0.3", facecolor='white', alpha=0.9)
258
+ )
259
+
260
+ def _combine_panel_and_main_captions(self, panel_dict: Dict[str, str], main_caption: str) -> str:
261
+ """Combine panel captions with main caption."""
262
+ panel_descriptions = []
263
+ for letter in sorted(panel_dict.keys()):
264
+ panel_descriptions.append(f"({letter}) {panel_dict[letter].split(' ', 1)[1]}") # Remove the bold letter
265
+
266
+ combined = main_caption
267
+ if panel_descriptions:
268
+ combined += " " + " ".join(panel_descriptions)
269
+
270
+ return combined
271
+
272
+ def _save_caption_to_file(self, caption: str, figure_label: str, file_path: str = None):
273
+ """Save caption to a text file."""
274
+ if file_path is None:
275
+ file_path = f"{figure_label.lower().replace(' ', '_')}_caption.txt"
276
+
277
+ with open(file_path, 'w', encoding='utf-8') as f:
278
+ f.write(caption)
279
+
280
+ def export_all_captions(self, file_path: str = "figure_captions.txt", style: str = "scientific"):
281
+ """Export all registered captions to a file."""
282
+ with open(file_path, 'w', encoding='utf-8') as f:
283
+ f.write("Figure Captions\n")
284
+ f.write("=" * 50 + "\n\n")
285
+
286
+ for label, info in self.caption_registry.items():
287
+ f.write(f"{info['formatted']}\n\n")
288
+
289
+ def get_cross_reference(self, figure_label: str) -> str:
290
+ """Get a cross-reference string for a figure."""
291
+ if figure_label in self.caption_registry:
292
+ return f"(see {figure_label})"
293
+ else:
294
+ return f"(see {figure_label} - not found)"
295
+
296
+
297
+ # Global caption manager instance
298
+ caption_manager = ScientificCaption()
299
+
300
+
301
+ # Convenience functions
302
+ def add_figure_caption(fig, caption: str, **kwargs) -> str:
303
+ """Convenience function to add figure caption."""
304
+ return caption_manager.add_figure_caption(fig, caption, **kwargs)
305
+
306
+
307
+ def add_panel_captions(fig, axes, panel_captions, **kwargs) -> Dict[str, str]:
308
+ """Convenience function to add panel captions."""
309
+ return caption_manager.add_panel_captions(fig, axes, panel_captions, **kwargs)
310
+
311
+
312
+ def export_captions(file_path: str = "figure_captions.txt"):
313
+ """Convenience function to export all captions."""
314
+ return caption_manager.export_all_captions(file_path)
315
+
316
+
317
+ def cross_ref(figure_label: str) -> str:
318
+ """Convenience function for cross-references."""
319
+ return caption_manager.get_cross_reference(figure_label)
320
+
321
+
322
+ # Integration with scitex save system
323
+ def save_with_caption(fig, filename: str, caption: str = None, **caption_kwargs):
324
+ """
325
+ Save figure with caption integration.
326
+
327
+ This function saves the figure and optionally creates caption files
328
+ that can be used for manuscript preparation.
329
+ """
330
+ import scitex
331
+
332
+ # Save the figure normally
333
+ scitex.io.save(fig, filename)
334
+
335
+ # Add caption if provided
336
+ if caption:
337
+ # Extract base filename
338
+ base_name = filename.split('.')[0]
339
+
340
+ # Save in multiple formats (like CSV system)
341
+ _save_caption_multiple_formats(caption, base_name, **caption_kwargs)
342
+
343
+ # Add caption to figure
344
+ formatted_caption = add_figure_caption(fig, caption, **caption_kwargs)
345
+
346
+ return formatted_caption
347
+
348
+ return None
349
+
350
+
351
+ def _save_caption_multiple_formats(
352
+ caption: str,
353
+ base_filename: str,
354
+ figure_label: str = None,
355
+ style: str = "scientific",
356
+ save_txt: bool = True,
357
+ save_tex: bool = True,
358
+ save_md: bool = True,
359
+ wrap_width: int = 80
360
+ ):
361
+ """
362
+ Save caption in multiple formats (like how scitex saves CSV data).
363
+
364
+ Parameters
365
+ ----------
366
+ caption : str
367
+ The caption text
368
+ base_filename : str
369
+ Base filename without extension
370
+ figure_label : str, optional
371
+ Figure label (auto-generated if None)
372
+ style : str, optional
373
+ Caption style, by default "scientific"
374
+ save_txt : bool, optional
375
+ Save as plain text, by default True
376
+ save_tex : bool, optional
377
+ Save as LaTeX, by default True
378
+ save_md : bool, optional
379
+ Save as Markdown, by default True
380
+ wrap_width : int, optional
381
+ Text wrapping width, by default 80
382
+ """
383
+ # Generate figure label if not provided
384
+ if figure_label is None:
385
+ caption_manager.figure_counter += 1
386
+ figure_label = f"Figure {caption_manager.figure_counter}"
387
+
388
+ # Create formatted versions
389
+ txt_caption = _format_caption_for_txt(caption, figure_label, style, wrap_width)
390
+ tex_caption = _format_caption_for_tex(caption, figure_label, style, wrap_width)
391
+ md_caption = _format_caption_for_md(caption, figure_label, style, wrap_width)
392
+
393
+ # Save files (following scitex naming convention)
394
+ if save_txt:
395
+ txt_file = f"{base_filename}_caption.txt"
396
+ with open(txt_file, 'w', encoding='utf-8') as f:
397
+ f.write(txt_caption)
398
+ print(f"📝 Caption saved to: {txt_file}")
399
+
400
+ if save_tex:
401
+ tex_file = f"{base_filename}_caption.tex"
402
+ with open(tex_file, 'w', encoding='utf-8') as f:
403
+ f.write(tex_caption)
404
+ print(f"📝 LaTeX caption saved to: {tex_file}")
405
+
406
+ if save_md:
407
+ md_file = f"{base_filename}_caption.md"
408
+ with open(md_file, 'w', encoding='utf-8') as f:
409
+ f.write(md_caption)
410
+ print(f"📝 Markdown caption saved to: {md_file}")
411
+
412
+
413
+ def _format_caption_for_txt(caption: str, figure_label: str, style: str, wrap_width: int) -> str:
414
+ """Format caption for plain text file."""
415
+ wrapped_text = textwrap.fill(caption, width=wrap_width)
416
+
417
+ if style == "scientific":
418
+ return f"{figure_label}. {wrapped_text}"
419
+ elif style == "nature":
420
+ return f"{figure_label} | {wrapped_text}"
421
+ elif style == "ieee":
422
+ return f"{figure_label}. {wrapped_text}"
423
+ elif style == "apa":
424
+ return f"{figure_label}\n{wrapped_text}"
425
+ else:
426
+ return f"{figure_label}. {wrapped_text}"
427
+
428
+
429
+ def _format_caption_for_tex(caption: str, figure_label: str, style: str, wrap_width: int) -> str:
430
+ """Format caption for LaTeX file."""
431
+ # Escape special LaTeX characters
432
+ tex_caption = _escape_latex(caption)
433
+ wrapped_text = textwrap.fill(tex_caption, width=wrap_width)
434
+
435
+ if style == "scientific":
436
+ latex_caption = f"""% {figure_label} caption
437
+ \\begin{{figure}}[htbp]
438
+ \\centering
439
+ % \\includegraphics{{figure_filename}}
440
+ \\caption{{\\textbf{{{figure_label}.}} {wrapped_text}}}
441
+ \\label{{fig:{figure_label.lower().replace(' ', '_')}}}
442
+ \\end{{figure}}
443
+
444
+ % For use in manuscript:
445
+ % \\textbf{{{figure_label}.}} {wrapped_text}
446
+ """
447
+ elif style == "nature":
448
+ latex_caption = f"""% {figure_label} caption (Nature style)
449
+ \\begin{{figure}}[htbp]
450
+ \\centering
451
+ % \\includegraphics{{figure_filename}}
452
+ \\caption{{\\textbf{{{figure_label} |}} {wrapped_text}}}
453
+ \\label{{fig:{figure_label.lower().replace(' ', '_')}}}
454
+ \\end{{figure}}
455
+ """
456
+ else:
457
+ latex_caption = f"""% {figure_label} caption
458
+ \\begin{{figure}}[htbp]
459
+ \\centering
460
+ % \\includegraphics{{figure_filename}}
461
+ \\caption{{{figure_label}. {wrapped_text}}}
462
+ \\label{{fig:{figure_label.lower().replace(' ', '_')}}}
463
+ \\end{{figure}}
464
+ """
465
+
466
+ return latex_caption
467
+
468
+
469
+ def _format_caption_for_md(caption: str, figure_label: str, style: str, wrap_width: int) -> str:
470
+ """Format caption for Markdown file."""
471
+ wrapped_text = textwrap.fill(caption, width=wrap_width)
472
+
473
+ if style == "scientific":
474
+ return f"""# {figure_label}
475
+
476
+ **{figure_label}.** {wrapped_text}
477
+
478
+ ---
479
+
480
+ *Generated by scitex scientific caption system*
481
+ """
482
+ elif style == "nature":
483
+ return f"""# {figure_label}
484
+
485
+ **{figure_label} |** {wrapped_text}
486
+
487
+ ---
488
+
489
+ *Generated by scitex scientific caption system*
490
+ """
491
+ else:
492
+ return f"""# {figure_label}
493
+
494
+ {figure_label}. {wrapped_text}
495
+
496
+ ---
497
+
498
+ *Generated by scitex scientific caption system*
499
+ """
500
+
501
+
502
+ def _escape_latex(text: str) -> str:
503
+ """Escape special LaTeX characters."""
504
+ # Basic LaTeX character escaping
505
+ escapes = {
506
+ '&': r'\&',
507
+ '%': r'\%',
508
+ '$': r'\$',
509
+ '#': r'\#',
510
+ '^': r'\textasciicircum{}',
511
+ '_': r'\_',
512
+ '{': r'\{',
513
+ '}': r'\}',
514
+ '~': r'\textasciitilde{}',
515
+ '\\': r'\textbackslash{}'
516
+ }
517
+
518
+ result = text
519
+ for char, escape in escapes.items():
520
+ result = result.replace(char, escape)
521
+
522
+ return result
523
+
524
+
525
+ # Enhanced integration with scitex.io.save
526
+ def enhance_scitex_save_with_captions():
527
+ """
528
+ Enhance the scitex.io.save system to automatically handle captions.
529
+
530
+ This can be called to monkey-patch scitex.io.save to include caption support.
531
+ """
532
+ import scitex
533
+
534
+ # Store original save function
535
+ original_save = scitex.io.save
536
+
537
+ def enhanced_save(obj, filename, caption=None, **kwargs):
538
+ """Enhanced save function with caption support."""
539
+ # Call original save
540
+ result = original_save(obj, filename, **kwargs)
541
+
542
+ # Handle captions if provided
543
+ if caption is not None and hasattr(obj, 'savefig'): # It's a figure
544
+ base_name = filename.split('.')[0]
545
+ _save_caption_multiple_formats(caption, base_name)
546
+
547
+ return result
548
+
549
+ # Replace the save function
550
+ scitex.io.save = enhanced_save
551
+ print("📝 scitex.io.save enhanced with caption support!")
552
+ print("Usage: scitex.io.save(fig, 'filename.png', caption='Your caption here')")
553
+
554
+
555
+ # Advanced caption utilities
556
+ def create_figure_list(output_file: str = "figure_list.txt", format: str = "txt"):
557
+ """
558
+ Create a comprehensive list of all figures and their captions.
559
+
560
+ Parameters
561
+ ----------
562
+ output_file : str, optional
563
+ Output filename, by default "figure_list.txt"
564
+ format : str, optional
565
+ Output format: "txt", "tex", "md", by default "txt"
566
+ """
567
+ if not caption_manager.caption_registry:
568
+ print("No figures with captions found.")
569
+ return
570
+
571
+ if format == "tex":
572
+ _create_latex_figure_list(output_file)
573
+ elif format == "md":
574
+ _create_markdown_figure_list(output_file)
575
+ else:
576
+ _create_text_figure_list(output_file)
577
+
578
+ print(f"📋 Figure list saved to: {output_file}")
579
+
580
+
581
+ def _create_text_figure_list(output_file: str):
582
+ """Create plain text figure list."""
583
+ with open(output_file, 'w', encoding='utf-8') as f:
584
+ f.write("Figure List\n")
585
+ f.write("=" * 50 + "\n\n")
586
+
587
+ for label, info in caption_manager.caption_registry.items():
588
+ f.write(f"{info['formatted']}\n\n")
589
+
590
+
591
+ def _create_latex_figure_list(output_file: str):
592
+ """Create LaTeX figure list."""
593
+ with open(output_file, 'w', encoding='utf-8') as f:
594
+ f.write("% Figure List - Generated by scitex\n")
595
+ f.write("\\section{List of Figures}\n\n")
596
+
597
+ for label, info in caption_manager.caption_registry.items():
598
+ escaped_caption = _escape_latex(info['text'])
599
+ f.write(f"\\textbf{{{label}.}} {escaped_caption}\\\\\n\n")
600
+
601
+
602
+ def _create_markdown_figure_list(output_file: str):
603
+ """Create Markdown figure list."""
604
+ with open(output_file, 'w', encoding='utf-8') as f:
605
+ f.write("# Figure List\n\n")
606
+ f.write("*Generated by scitex scientific caption system*\n\n")
607
+
608
+ for label, info in caption_manager.caption_registry.items():
609
+ f.write(f"**{label}.** {info['text']}\n\n")
610
+
611
+
612
+ # Convenience function for quick caption addition
613
+ def quick_caption(fig, caption: str, save_path: str = None, **kwargs):
614
+ """
615
+ Quick way to add caption and save all formats.
616
+
617
+ Parameters
618
+ ----------
619
+ fig : matplotlib.figure.Figure
620
+ Figure to caption
621
+ caption : str
622
+ Caption text
623
+ save_path : str, optional
624
+ Base path for saving (uses figure number if None)
625
+ **kwargs
626
+ Additional arguments for caption formatting
627
+ """
628
+ if save_path is None:
629
+ save_path = f"figure_{caption_manager.figure_counter + 1}"
630
+
631
+ # Save in all formats
632
+ _save_caption_multiple_formats(caption, save_path, **kwargs)
633
+
634
+ # Add visual caption to figure
635
+ return add_figure_caption(fig, caption, **kwargs)
636
+
637
+
638
+ # EOF