scitex 2.0.0__py2.py3-none-any.whl → 2.1.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 (704) hide show
  1. scitex/__init__.py +53 -15
  2. scitex/__main__.py +72 -26
  3. scitex/__version__.py +1 -1
  4. scitex/_sh.py +145 -23
  5. scitex/ai/__init__.py +30 -16
  6. scitex/ai/_gen_ai/_Anthropic.py +5 -7
  7. scitex/ai/_gen_ai/_BaseGenAI.py +2 -2
  8. scitex/ai/_gen_ai/_DeepSeek.py +10 -2
  9. scitex/ai/_gen_ai/_Google.py +2 -2
  10. scitex/ai/_gen_ai/_Llama.py +2 -2
  11. scitex/ai/_gen_ai/_OpenAI.py +2 -2
  12. scitex/ai/_gen_ai/_PARAMS.py +51 -65
  13. scitex/ai/_gen_ai/_Perplexity.py +2 -2
  14. scitex/ai/_gen_ai/__init__.py +25 -14
  15. scitex/ai/_gen_ai/_format_output_func.py +4 -4
  16. scitex/ai/classification/{classifier_server.py → Classifier.py} +5 -5
  17. scitex/ai/classification/CrossValidationExperiment.py +374 -0
  18. scitex/ai/classification/__init__.py +43 -4
  19. scitex/ai/classification/reporters/_BaseClassificationReporter.py +281 -0
  20. scitex/ai/classification/reporters/_ClassificationReporter.py +773 -0
  21. scitex/ai/classification/reporters/_MultiClassificationReporter.py +406 -0
  22. scitex/ai/classification/reporters/_SingleClassificationReporter.py +1834 -0
  23. scitex/ai/classification/reporters/__init__.py +11 -0
  24. scitex/ai/classification/reporters/reporter_utils/_Plotter.py +1028 -0
  25. scitex/ai/classification/reporters/reporter_utils/__init__.py +80 -0
  26. scitex/ai/classification/reporters/reporter_utils/aggregation.py +457 -0
  27. scitex/ai/classification/reporters/reporter_utils/data_models.py +313 -0
  28. scitex/ai/classification/reporters/reporter_utils/reporting.py +1056 -0
  29. scitex/ai/classification/reporters/reporter_utils/storage.py +221 -0
  30. scitex/ai/classification/reporters/reporter_utils/validation.py +395 -0
  31. scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
  32. scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
  33. scitex/ai/classification/timeseries/_TimeSeriesMetadata.py +139 -0
  34. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
  35. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
  36. scitex/ai/classification/timeseries/_TimeSeriesStrategy.py +84 -0
  37. scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
  38. scitex/ai/classification/timeseries/__init__.py +39 -0
  39. scitex/ai/classification/timeseries/_normalize_timestamp.py +436 -0
  40. scitex/ai/clustering/_umap.py +2 -2
  41. scitex/ai/feature_extraction/vit.py +1 -0
  42. scitex/ai/feature_selection/__init__.py +30 -0
  43. scitex/ai/feature_selection/feature_selection.py +364 -0
  44. scitex/ai/loss/multi_task_loss.py +1 -1
  45. scitex/ai/metrics/__init__.py +51 -4
  46. scitex/ai/metrics/_calc_bacc.py +61 -0
  47. scitex/ai/metrics/_calc_bacc_from_conf_mat.py +38 -0
  48. scitex/ai/metrics/_calc_clf_report.py +78 -0
  49. scitex/ai/metrics/_calc_conf_mat.py +93 -0
  50. scitex/ai/metrics/_calc_feature_importance.py +183 -0
  51. scitex/ai/metrics/_calc_mcc.py +61 -0
  52. scitex/ai/metrics/_calc_pre_rec_auc.py +116 -0
  53. scitex/ai/metrics/_calc_roc_auc.py +110 -0
  54. scitex/ai/metrics/_calc_seizure_prediction_metrics.py +490 -0
  55. scitex/ai/metrics/{silhoute_score_block.py → _calc_silhouette_score.py} +15 -8
  56. scitex/ai/metrics/_normalize_labels.py +83 -0
  57. scitex/ai/plt/__init__.py +47 -8
  58. scitex/ai/plt/{_conf_mat.py → _plot_conf_mat.py} +158 -87
  59. scitex/ai/plt/_plot_feature_importance.py +323 -0
  60. scitex/ai/plt/_plot_learning_curve.py +345 -0
  61. scitex/ai/plt/_plot_optuna_study.py +225 -0
  62. scitex/ai/plt/_plot_pre_rec_curve.py +290 -0
  63. scitex/ai/plt/_plot_roc_curve.py +255 -0
  64. scitex/ai/training/{learning_curve_logger.py → _LearningCurveLogger.py} +197 -213
  65. scitex/ai/training/__init__.py +2 -2
  66. scitex/ai/utils/grid_search.py +3 -3
  67. scitex/benchmark/__init__.py +52 -0
  68. scitex/benchmark/benchmark.py +400 -0
  69. scitex/benchmark/monitor.py +370 -0
  70. scitex/benchmark/profiler.py +297 -0
  71. scitex/browser/__init__.py +48 -0
  72. scitex/browser/automation/CookieHandler.py +216 -0
  73. scitex/browser/automation/__init__.py +7 -0
  74. scitex/browser/collaboration/__init__.py +55 -0
  75. scitex/browser/collaboration/auth_helpers.py +94 -0
  76. scitex/browser/collaboration/collaborative_agent.py +136 -0
  77. scitex/browser/collaboration/credential_manager.py +188 -0
  78. scitex/browser/collaboration/interactive_panel.py +400 -0
  79. scitex/browser/collaboration/persistent_browser.py +170 -0
  80. scitex/browser/collaboration/shared_session.py +383 -0
  81. scitex/browser/collaboration/standard_interactions.py +246 -0
  82. scitex/browser/collaboration/visual_feedback.py +181 -0
  83. scitex/browser/core/BrowserMixin.py +326 -0
  84. scitex/browser/core/ChromeProfileManager.py +446 -0
  85. scitex/browser/core/__init__.py +9 -0
  86. scitex/browser/debugging/__init__.py +18 -0
  87. scitex/browser/debugging/_browser_logger.py +657 -0
  88. scitex/browser/debugging/_highlight_element.py +143 -0
  89. scitex/browser/debugging/_show_grid.py +154 -0
  90. scitex/browser/interaction/__init__.py +24 -0
  91. scitex/browser/interaction/click_center.py +149 -0
  92. scitex/browser/interaction/click_with_fallbacks.py +206 -0
  93. scitex/browser/interaction/close_popups.py +498 -0
  94. scitex/browser/interaction/fill_with_fallbacks.py +209 -0
  95. scitex/browser/pdf/__init__.py +14 -0
  96. scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +200 -0
  97. scitex/browser/pdf/detect_chrome_pdf_viewer.py +198 -0
  98. scitex/browser/remote/CaptchaHandler.py +434 -0
  99. scitex/browser/remote/ZenRowsAPIClient.py +347 -0
  100. scitex/browser/remote/ZenRowsBrowserManager.py +570 -0
  101. scitex/browser/remote/__init__.py +11 -0
  102. scitex/browser/stealth/HumanBehavior.py +344 -0
  103. scitex/browser/stealth/StealthManager.py +1008 -0
  104. scitex/browser/stealth/__init__.py +9 -0
  105. scitex/browser/template.py +122 -0
  106. scitex/capture/__init__.py +110 -0
  107. scitex/capture/__main__.py +25 -0
  108. scitex/capture/capture.py +848 -0
  109. scitex/capture/cli.py +233 -0
  110. scitex/capture/gif.py +344 -0
  111. scitex/capture/mcp_server.py +961 -0
  112. scitex/capture/session.py +70 -0
  113. scitex/capture/utils.py +705 -0
  114. scitex/cli/__init__.py +17 -0
  115. scitex/cli/cloud.py +447 -0
  116. scitex/cli/main.py +42 -0
  117. scitex/cli/scholar.py +280 -0
  118. scitex/context/_suppress_output.py +5 -3
  119. scitex/db/__init__.py +30 -3
  120. scitex/db/__main__.py +75 -0
  121. scitex/db/_check_health.py +381 -0
  122. scitex/db/_delete_duplicates.py +25 -386
  123. scitex/db/_inspect.py +335 -114
  124. scitex/db/_inspect_optimized.py +301 -0
  125. scitex/db/{_PostgreSQL.py → _postgresql/_PostgreSQL.py} +3 -3
  126. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BackupMixin.py +1 -1
  127. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BatchMixin.py +1 -1
  128. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BlobMixin.py +1 -1
  129. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ConnectionMixin.py +1 -1
  130. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_MaintenanceMixin.py +1 -1
  131. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_QueryMixin.py +1 -1
  132. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_SchemaMixin.py +1 -1
  133. scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TransactionMixin.py +1 -1
  134. scitex/db/_postgresql/__init__.py +6 -0
  135. scitex/db/_sqlite3/_SQLite3.py +210 -0
  136. scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin.py +581 -0
  137. scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin_v01-need-_hash-col.py +517 -0
  138. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_BatchMixin.py +1 -1
  139. scitex/db/_sqlite3/_SQLite3Mixins/_BlobMixin.py +281 -0
  140. scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin.py +548 -0
  141. scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin_v01-indentation-issues.py +583 -0
  142. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ConnectionMixin.py +29 -13
  143. scitex/db/_sqlite3/_SQLite3Mixins/_GitMixin.py +583 -0
  144. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ImportExportMixin.py +1 -1
  145. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_IndexMixin.py +1 -1
  146. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_MaintenanceMixin.py +2 -1
  147. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_QueryMixin.py +37 -10
  148. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_RowMixin.py +46 -6
  149. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TableMixin.py +56 -10
  150. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TransactionMixin.py +1 -1
  151. scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/__init__.py +14 -2
  152. scitex/db/_sqlite3/__init__.py +7 -0
  153. scitex/db/_sqlite3/_delete_duplicates.py +274 -0
  154. scitex/decorators/__init__.py +2 -0
  155. scitex/decorators/_cache_disk.py +13 -5
  156. scitex/decorators/_cache_disk_async.py +49 -0
  157. scitex/decorators/_deprecated.py +175 -10
  158. scitex/decorators/_timeout.py +1 -1
  159. scitex/dev/_analyze_code_flow.py +2 -2
  160. scitex/dict/_DotDict.py +73 -15
  161. scitex/dict/_DotDict_v01-not-handling-recursive-instantiations.py +442 -0
  162. scitex/dict/_DotDict_v02-not-serializing-Path-object.py +446 -0
  163. scitex/dict/__init__.py +2 -0
  164. scitex/dict/_flatten.py +27 -0
  165. scitex/dsp/_crop.py +2 -2
  166. scitex/dsp/_demo_sig.py +2 -2
  167. scitex/dsp/_detect_ripples.py +2 -2
  168. scitex/dsp/_hilbert.py +2 -2
  169. scitex/dsp/_listen.py +6 -6
  170. scitex/dsp/_modulation_index.py +2 -2
  171. scitex/dsp/_pac.py +1 -1
  172. scitex/dsp/_psd.py +2 -2
  173. scitex/dsp/_resample.py +2 -1
  174. scitex/dsp/_time.py +3 -2
  175. scitex/dsp/_wavelet.py +3 -2
  176. scitex/dsp/add_noise.py +2 -2
  177. scitex/dsp/example.py +1 -0
  178. scitex/dsp/filt.py +10 -9
  179. scitex/dsp/template.py +3 -2
  180. scitex/dsp/utils/_differential_bandpass_filters.py +1 -1
  181. scitex/dsp/utils/pac.py +2 -2
  182. scitex/dt/_normalize_timestamp.py +432 -0
  183. scitex/errors.py +572 -0
  184. scitex/gen/_DimHandler.py +2 -2
  185. scitex/gen/__init__.py +37 -7
  186. scitex/gen/_deprecated_close.py +80 -0
  187. scitex/gen/_deprecated_start.py +26 -0
  188. scitex/gen/_detect_environment.py +152 -0
  189. scitex/gen/_detect_notebook_path.py +169 -0
  190. scitex/gen/_embed.py +6 -2
  191. scitex/gen/_get_notebook_path.py +257 -0
  192. scitex/gen/_less.py +1 -1
  193. scitex/gen/_list_packages.py +2 -2
  194. scitex/gen/_norm.py +44 -9
  195. scitex/gen/_norm_cache.py +269 -0
  196. scitex/gen/_src.py +3 -5
  197. scitex/gen/_title_case.py +3 -3
  198. scitex/io/__init__.py +28 -6
  199. scitex/io/_glob.py +13 -7
  200. scitex/io/_load.py +108 -21
  201. scitex/io/_load_cache.py +303 -0
  202. scitex/io/_load_configs.py +40 -15
  203. scitex/io/{_H5Explorer.py → _load_modules/_H5Explorer.py} +80 -17
  204. scitex/io/_load_modules/_ZarrExplorer.py +114 -0
  205. scitex/io/_load_modules/_bibtex.py +207 -0
  206. scitex/io/_load_modules/_hdf5.py +53 -178
  207. scitex/io/_load_modules/_json.py +5 -3
  208. scitex/io/_load_modules/_pdf.py +871 -16
  209. scitex/io/_load_modules/_sqlite3.py +15 -0
  210. scitex/io/_load_modules/_txt.py +41 -12
  211. scitex/io/_load_modules/_yaml.py +4 -3
  212. scitex/io/_load_modules/_zarr.py +126 -0
  213. scitex/io/_save.py +429 -171
  214. scitex/io/_save_modules/__init__.py +6 -0
  215. scitex/io/_save_modules/_bibtex.py +194 -0
  216. scitex/io/_save_modules/_csv.py +8 -4
  217. scitex/io/_save_modules/_excel.py +174 -15
  218. scitex/io/_save_modules/_hdf5.py +251 -226
  219. scitex/io/_save_modules/_image.py +1 -3
  220. scitex/io/_save_modules/_json.py +49 -4
  221. scitex/io/_save_modules/_listed_dfs_as_csv.py +1 -3
  222. scitex/io/_save_modules/_listed_scalars_as_csv.py +1 -3
  223. scitex/io/_save_modules/_tex.py +277 -0
  224. scitex/io/_save_modules/_yaml.py +42 -3
  225. scitex/io/_save_modules/_zarr.py +160 -0
  226. scitex/io/utils/__init__.py +20 -0
  227. scitex/io/utils/h5_to_zarr.py +616 -0
  228. scitex/linalg/_geometric_median.py +6 -2
  229. scitex/{gen/_tee.py → logging/_Tee.py} +43 -84
  230. scitex/logging/__init__.py +122 -0
  231. scitex/logging/_config.py +158 -0
  232. scitex/logging/_context.py +103 -0
  233. scitex/logging/_formatters.py +128 -0
  234. scitex/logging/_handlers.py +64 -0
  235. scitex/logging/_levels.py +35 -0
  236. scitex/logging/_logger.py +163 -0
  237. scitex/logging/_print_capture.py +95 -0
  238. scitex/ml/__init__.py +69 -0
  239. scitex/{ai/genai/anthropic.py → ml/_gen_ai/_Anthropic.py} +13 -19
  240. scitex/{ai/genai/base_genai.py → ml/_gen_ai/_BaseGenAI.py} +5 -5
  241. scitex/{ai/genai/deepseek.py → ml/_gen_ai/_DeepSeek.py} +11 -16
  242. scitex/{ai/genai/google.py → ml/_gen_ai/_Google.py} +7 -15
  243. scitex/{ai/genai/groq.py → ml/_gen_ai/_Groq.py} +1 -8
  244. scitex/{ai/genai/llama.py → ml/_gen_ai/_Llama.py} +3 -16
  245. scitex/{ai/genai/openai.py → ml/_gen_ai/_OpenAI.py} +3 -3
  246. scitex/{ai/genai/params.py → ml/_gen_ai/_PARAMS.py} +51 -65
  247. scitex/{ai/genai/perplexity.py → ml/_gen_ai/_Perplexity.py} +3 -14
  248. scitex/ml/_gen_ai/__init__.py +43 -0
  249. scitex/{ai/genai/calc_cost.py → ml/_gen_ai/_calc_cost.py} +1 -1
  250. scitex/{ai/genai/format_output_func.py → ml/_gen_ai/_format_output_func.py} +4 -4
  251. scitex/{ai/genai/genai_factory.py → ml/_gen_ai/_genai_factory.py} +8 -8
  252. scitex/ml/activation/__init__.py +8 -0
  253. scitex/ml/activation/_define.py +11 -0
  254. scitex/{ai/classifier_server.py → ml/classification/Classifier.py} +5 -5
  255. scitex/ml/classification/CrossValidationExperiment.py +374 -0
  256. scitex/ml/classification/__init__.py +46 -0
  257. scitex/ml/classification/reporters/_BaseClassificationReporter.py +281 -0
  258. scitex/ml/classification/reporters/_ClassificationReporter.py +773 -0
  259. scitex/ml/classification/reporters/_MultiClassificationReporter.py +406 -0
  260. scitex/ml/classification/reporters/_SingleClassificationReporter.py +1834 -0
  261. scitex/ml/classification/reporters/__init__.py +11 -0
  262. scitex/ml/classification/reporters/reporter_utils/_Plotter.py +1028 -0
  263. scitex/ml/classification/reporters/reporter_utils/__init__.py +80 -0
  264. scitex/ml/classification/reporters/reporter_utils/aggregation.py +457 -0
  265. scitex/ml/classification/reporters/reporter_utils/data_models.py +313 -0
  266. scitex/ml/classification/reporters/reporter_utils/reporting.py +1056 -0
  267. scitex/ml/classification/reporters/reporter_utils/storage.py +221 -0
  268. scitex/ml/classification/reporters/reporter_utils/validation.py +395 -0
  269. scitex/ml/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
  270. scitex/ml/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
  271. scitex/ml/classification/timeseries/_TimeSeriesMetadata.py +139 -0
  272. scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
  273. scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
  274. scitex/ml/classification/timeseries/_TimeSeriesStrategy.py +84 -0
  275. scitex/ml/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
  276. scitex/ml/classification/timeseries/__init__.py +39 -0
  277. scitex/ml/classification/timeseries/_normalize_timestamp.py +436 -0
  278. scitex/ml/clustering/__init__.py +11 -0
  279. scitex/ml/clustering/_pca.py +115 -0
  280. scitex/ml/clustering/_umap.py +376 -0
  281. scitex/ml/feature_extraction/__init__.py +56 -0
  282. scitex/ml/feature_extraction/vit.py +149 -0
  283. scitex/ml/feature_selection/__init__.py +30 -0
  284. scitex/ml/feature_selection/feature_selection.py +364 -0
  285. scitex/ml/loss/_L1L2Losses.py +34 -0
  286. scitex/ml/loss/__init__.py +12 -0
  287. scitex/ml/loss/multi_task_loss.py +47 -0
  288. scitex/ml/metrics/__init__.py +56 -0
  289. scitex/ml/metrics/_calc_bacc.py +61 -0
  290. scitex/ml/metrics/_calc_bacc_from_conf_mat.py +38 -0
  291. scitex/ml/metrics/_calc_clf_report.py +78 -0
  292. scitex/ml/metrics/_calc_conf_mat.py +93 -0
  293. scitex/ml/metrics/_calc_feature_importance.py +183 -0
  294. scitex/ml/metrics/_calc_mcc.py +61 -0
  295. scitex/ml/metrics/_calc_pre_rec_auc.py +116 -0
  296. scitex/ml/metrics/_calc_roc_auc.py +110 -0
  297. scitex/ml/metrics/_calc_seizure_prediction_metrics.py +490 -0
  298. scitex/ml/metrics/_calc_silhouette_score.py +503 -0
  299. scitex/ml/metrics/_normalize_labels.py +83 -0
  300. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
  301. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
  302. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
  303. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
  304. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
  305. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
  306. scitex/ml/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
  307. scitex/ml/optim/__init__.py +13 -0
  308. scitex/ml/optim/_get_set.py +31 -0
  309. scitex/ml/optim/_optimizers.py +71 -0
  310. scitex/ml/plt/__init__.py +60 -0
  311. scitex/ml/plt/_plot_conf_mat.py +663 -0
  312. scitex/ml/plt/_plot_feature_importance.py +323 -0
  313. scitex/ml/plt/_plot_learning_curve.py +345 -0
  314. scitex/ml/plt/_plot_optuna_study.py +225 -0
  315. scitex/ml/plt/_plot_pre_rec_curve.py +290 -0
  316. scitex/ml/plt/_plot_roc_curve.py +255 -0
  317. scitex/ml/sk/__init__.py +11 -0
  318. scitex/ml/sk/_clf.py +58 -0
  319. scitex/ml/sk/_to_sktime.py +100 -0
  320. scitex/ml/sklearn/__init__.py +26 -0
  321. scitex/ml/sklearn/clf.py +58 -0
  322. scitex/ml/sklearn/to_sktime.py +100 -0
  323. scitex/{ai/training/early_stopping.py → ml/training/_EarlyStopping.py} +1 -2
  324. scitex/{ai → ml/training}/_LearningCurveLogger.py +198 -242
  325. scitex/ml/training/__init__.py +7 -0
  326. scitex/ml/utils/__init__.py +22 -0
  327. scitex/ml/utils/_check_params.py +50 -0
  328. scitex/ml/utils/_default_dataset.py +46 -0
  329. scitex/ml/utils/_format_samples_for_sktime.py +26 -0
  330. scitex/ml/utils/_label_encoder.py +134 -0
  331. scitex/ml/utils/_merge_labels.py +22 -0
  332. scitex/ml/utils/_sliding_window_data_augmentation.py +11 -0
  333. scitex/ml/utils/_under_sample.py +51 -0
  334. scitex/ml/utils/_verify_n_gpus.py +16 -0
  335. scitex/ml/utils/grid_search.py +148 -0
  336. scitex/nn/_BNet.py +15 -9
  337. scitex/nn/_Filters.py +2 -2
  338. scitex/nn/_ModulationIndex.py +2 -2
  339. scitex/nn/_PAC.py +1 -1
  340. scitex/nn/_Spectrogram.py +12 -3
  341. scitex/nn/__init__.py +9 -10
  342. scitex/path/__init__.py +18 -0
  343. scitex/path/_clean.py +4 -0
  344. scitex/path/_find.py +9 -4
  345. scitex/path/_symlink.py +348 -0
  346. scitex/path/_version.py +4 -3
  347. scitex/pd/__init__.py +2 -0
  348. scitex/pd/_get_unique.py +99 -0
  349. scitex/plt/__init__.py +114 -5
  350. scitex/plt/_subplots/_AxesWrapper.py +1 -3
  351. scitex/plt/_subplots/_AxisWrapper.py +7 -3
  352. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +47 -13
  353. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +160 -2
  354. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +26 -4
  355. scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +322 -0
  356. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +1 -0
  357. scitex/plt/_subplots/_FigWrapper.py +62 -6
  358. scitex/plt/_subplots/_export_as_csv.py +43 -27
  359. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +5 -4
  360. scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +81 -0
  361. scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +1 -3
  362. scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +20 -5
  363. scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +1 -3
  364. scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +1 -3
  365. scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +35 -18
  366. scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +1 -3
  367. scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +1 -3
  368. scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +1 -3
  369. scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +1 -3
  370. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +1 -3
  371. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +1 -3
  372. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +15 -3
  373. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +1 -3
  374. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +1 -3
  375. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +1 -3
  376. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +1 -3
  377. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +1 -3
  378. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +1 -3
  379. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +1 -3
  380. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +1 -3
  381. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +1 -3
  382. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +1 -3
  383. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +1 -3
  384. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +1 -3
  385. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +1 -3
  386. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +1 -3
  387. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +35 -0
  388. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +1 -3
  389. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +1 -3
  390. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +1 -3
  391. scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +6 -4
  392. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +1 -3
  393. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +1 -3
  394. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +1 -3
  395. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +1 -3
  396. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +1 -3
  397. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +1 -3
  398. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +1 -3
  399. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +1 -3
  400. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +1 -3
  401. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +1 -3
  402. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +1 -3
  403. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +1 -3
  404. scitex/plt/_subplots/_export_as_csv_formatters/_format_text.py +60 -0
  405. scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +1 -3
  406. scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +1 -3
  407. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +1 -3
  408. scitex/plt/_subplots/_export_as_csv_formatters.py +56 -59
  409. scitex/plt/ax/_style/_hide_spines.py +1 -3
  410. scitex/plt/ax/_style/_rotate_labels.py +180 -76
  411. scitex/plt/ax/_style/_rotate_labels_v01.py +248 -0
  412. scitex/plt/ax/_style/_set_meta.py +11 -4
  413. scitex/plt/ax/_style/_set_supxyt.py +3 -3
  414. scitex/plt/ax/_style/_set_xyt.py +3 -3
  415. scitex/plt/ax/_style/_share_axes.py +2 -2
  416. scitex/plt/color/__init__.py +4 -4
  417. scitex/plt/color/{_get_colors_from_cmap.py → _get_colors_from_conf_matap.py} +7 -7
  418. scitex/plt/utils/_configure_mpl.py +99 -86
  419. scitex/plt/utils/_histogram_utils.py +1 -3
  420. scitex/plt/utils/_is_valid_axis.py +1 -3
  421. scitex/plt/utils/_scitex_config.py +1 -0
  422. scitex/repro/__init__.py +75 -0
  423. scitex/{reproduce → repro}/_gen_ID.py +1 -1
  424. scitex/{reproduce → repro}/_gen_timestamp.py +1 -1
  425. scitex/repro_rng/_RandomStateManager.py +590 -0
  426. scitex/repro_rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
  427. scitex/repro_rng/__init__.py +39 -0
  428. scitex/reproduce/__init__.py +25 -13
  429. scitex/reproduce/_hash_array.py +22 -0
  430. scitex/resource/_get_processor_usages.py +4 -4
  431. scitex/resource/_get_specs.py +2 -2
  432. scitex/resource/_log_processor_usages.py +2 -2
  433. scitex/rng/_RandomStateManager.py +590 -0
  434. scitex/rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
  435. scitex/rng/__init__.py +39 -0
  436. scitex/scholar/__init__.py +309 -19
  437. scitex/scholar/__main__.py +319 -0
  438. scitex/scholar/auth/ScholarAuthManager.py +308 -0
  439. scitex/scholar/auth/__init__.py +12 -0
  440. scitex/scholar/auth/core/AuthenticationGateway.py +473 -0
  441. scitex/scholar/auth/core/BrowserAuthenticator.py +386 -0
  442. scitex/scholar/auth/core/StrategyResolver.py +309 -0
  443. scitex/scholar/auth/core/__init__.py +16 -0
  444. scitex/scholar/auth/gateway/_OpenURLLinkFinder.py +120 -0
  445. scitex/scholar/auth/gateway/_OpenURLResolver.py +209 -0
  446. scitex/scholar/auth/gateway/__init__.py +38 -0
  447. scitex/scholar/auth/gateway/_resolve_functions.py +101 -0
  448. scitex/scholar/auth/providers/BaseAuthenticator.py +166 -0
  449. scitex/scholar/auth/providers/EZProxyAuthenticator.py +484 -0
  450. scitex/scholar/auth/providers/OpenAthensAuthenticator.py +619 -0
  451. scitex/scholar/auth/providers/ShibbolethAuthenticator.py +686 -0
  452. scitex/scholar/auth/providers/__init__.py +18 -0
  453. scitex/scholar/auth/session/AuthCacheManager.py +189 -0
  454. scitex/scholar/auth/session/SessionManager.py +159 -0
  455. scitex/scholar/auth/session/__init__.py +11 -0
  456. scitex/scholar/auth/sso/BaseSSOAutomator.py +373 -0
  457. scitex/scholar/auth/sso/OpenAthensSSOAutomator.py +378 -0
  458. scitex/scholar/auth/sso/SSOAutomator.py +180 -0
  459. scitex/scholar/auth/sso/UniversityOfMelbourneSSOAutomator.py +380 -0
  460. scitex/scholar/auth/sso/__init__.py +15 -0
  461. scitex/scholar/browser/ScholarBrowserManager.py +705 -0
  462. scitex/scholar/browser/__init__.py +38 -0
  463. scitex/scholar/browser/utils/__init__.py +13 -0
  464. scitex/scholar/browser/utils/click_and_wait.py +205 -0
  465. scitex/scholar/browser/utils/close_unwanted_pages.py +140 -0
  466. scitex/scholar/browser/utils/wait_redirects.py +732 -0
  467. scitex/scholar/config/PublisherRules.py +132 -0
  468. scitex/scholar/config/ScholarConfig.py +126 -0
  469. scitex/scholar/config/__init__.py +17 -0
  470. scitex/scholar/core/Paper.py +627 -0
  471. scitex/scholar/core/Papers.py +722 -0
  472. scitex/scholar/core/Scholar.py +1975 -0
  473. scitex/scholar/core/__init__.py +9 -0
  474. scitex/scholar/impact_factor/ImpactFactorEngine.py +204 -0
  475. scitex/scholar/impact_factor/__init__.py +20 -0
  476. scitex/scholar/impact_factor/estimation/ImpactFactorEstimationEngine.py +0 -0
  477. scitex/scholar/impact_factor/estimation/__init__.py +40 -0
  478. scitex/scholar/impact_factor/estimation/build_database.py +0 -0
  479. scitex/scholar/impact_factor/estimation/core/__init__.py +28 -0
  480. scitex/scholar/impact_factor/estimation/core/cache_manager.py +523 -0
  481. scitex/scholar/impact_factor/estimation/core/calculator.py +355 -0
  482. scitex/scholar/impact_factor/estimation/core/journal_matcher.py +428 -0
  483. scitex/scholar/integration/__init__.py +59 -0
  484. scitex/scholar/integration/base.py +502 -0
  485. scitex/scholar/integration/mendeley/__init__.py +22 -0
  486. scitex/scholar/integration/mendeley/exporter.py +166 -0
  487. scitex/scholar/integration/mendeley/importer.py +236 -0
  488. scitex/scholar/integration/mendeley/linker.py +79 -0
  489. scitex/scholar/integration/mendeley/mapper.py +212 -0
  490. scitex/scholar/integration/zotero/__init__.py +27 -0
  491. scitex/scholar/integration/zotero/__main__.py +264 -0
  492. scitex/scholar/integration/zotero/exporter.py +351 -0
  493. scitex/scholar/integration/zotero/importer.py +372 -0
  494. scitex/scholar/integration/zotero/linker.py +415 -0
  495. scitex/scholar/integration/zotero/mapper.py +286 -0
  496. scitex/scholar/metadata_engines/ScholarEngine.py +588 -0
  497. scitex/scholar/metadata_engines/__init__.py +21 -0
  498. scitex/scholar/metadata_engines/individual/ArXivEngine.py +397 -0
  499. scitex/scholar/metadata_engines/individual/CrossRefEngine.py +274 -0
  500. scitex/scholar/metadata_engines/individual/CrossRefLocalEngine.py +263 -0
  501. scitex/scholar/metadata_engines/individual/OpenAlexEngine.py +350 -0
  502. scitex/scholar/metadata_engines/individual/PubMedEngine.py +329 -0
  503. scitex/scholar/metadata_engines/individual/SemanticScholarEngine.py +438 -0
  504. scitex/scholar/metadata_engines/individual/URLDOIEngine.py +410 -0
  505. scitex/scholar/metadata_engines/individual/_BaseDOIEngine.py +487 -0
  506. scitex/scholar/metadata_engines/individual/__init__.py +7 -0
  507. scitex/scholar/metadata_engines/utils/_PubMedConverter.py +469 -0
  508. scitex/scholar/metadata_engines/utils/_URLDOIExtractor.py +283 -0
  509. scitex/scholar/metadata_engines/utils/__init__.py +30 -0
  510. scitex/scholar/metadata_engines/utils/_metadata2bibtex.py +103 -0
  511. scitex/scholar/metadata_engines/utils/_standardize_metadata.py +376 -0
  512. scitex/scholar/pdf_download/ScholarPDFDownloader.py +579 -0
  513. scitex/scholar/pdf_download/__init__.py +5 -0
  514. scitex/scholar/pdf_download/strategies/__init__.py +38 -0
  515. scitex/scholar/pdf_download/strategies/chrome_pdf_viewer.py +376 -0
  516. scitex/scholar/pdf_download/strategies/direct_download.py +131 -0
  517. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +167 -0
  518. scitex/scholar/pdf_download/strategies/manual_download_utils.py +996 -0
  519. scitex/scholar/pdf_download/strategies/response_body.py +207 -0
  520. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +364 -0
  521. scitex/scholar/pipelines/ScholarPipelineParallel.py +478 -0
  522. scitex/scholar/pipelines/ScholarPipelineSingle.py +767 -0
  523. scitex/scholar/pipelines/__init__.py +49 -0
  524. scitex/scholar/storage/BibTeXHandler.py +1018 -0
  525. scitex/scholar/storage/PaperIO.py +468 -0
  526. scitex/scholar/storage/ScholarLibrary.py +182 -0
  527. scitex/scholar/storage/_DeduplicationManager.py +548 -0
  528. scitex/scholar/storage/_LibraryCacheManager.py +724 -0
  529. scitex/scholar/storage/_LibraryManager.py +1835 -0
  530. scitex/scholar/storage/__init__.py +28 -0
  531. scitex/scholar/url_finder/ScholarURLFinder.py +379 -0
  532. scitex/scholar/url_finder/__init__.py +7 -0
  533. scitex/scholar/url_finder/strategies/__init__.py +33 -0
  534. scitex/scholar/url_finder/strategies/find_pdf_urls_by_direct_links.py +261 -0
  535. scitex/scholar/url_finder/strategies/find_pdf_urls_by_dropdown.py +67 -0
  536. scitex/scholar/url_finder/strategies/find_pdf_urls_by_href.py +204 -0
  537. scitex/scholar/url_finder/strategies/find_pdf_urls_by_navigation.py +256 -0
  538. scitex/scholar/url_finder/strategies/find_pdf_urls_by_publisher_patterns.py +165 -0
  539. scitex/scholar/url_finder/strategies/find_pdf_urls_by_zotero_translators.py +163 -0
  540. scitex/scholar/url_finder/strategies/find_supplementary_urls_by_href.py +70 -0
  541. scitex/scholar/utils/__init__.py +22 -0
  542. scitex/scholar/utils/bibtex/__init__.py +9 -0
  543. scitex/scholar/utils/bibtex/_parse_bibtex.py +71 -0
  544. scitex/scholar/utils/cleanup/__init__.py +8 -0
  545. scitex/scholar/utils/cleanup/_cleanup_scholar_processes.py +96 -0
  546. scitex/scholar/utils/cleanup/cleanup_old_extractions.py +117 -0
  547. scitex/scholar/utils/text/_TextNormalizer.py +407 -0
  548. scitex/scholar/utils/text/__init__.py +9 -0
  549. scitex/scholar/zotero/__init__.py +38 -0
  550. scitex/session/__init__.py +51 -0
  551. scitex/session/_lifecycle.py +736 -0
  552. scitex/session/_manager.py +102 -0
  553. scitex/session/template.py +122 -0
  554. scitex/stats/__init__.py +30 -26
  555. scitex/stats/correct/__init__.py +21 -0
  556. scitex/stats/correct/_correct_bonferroni.py +551 -0
  557. scitex/stats/correct/_correct_fdr.py +634 -0
  558. scitex/stats/correct/_correct_holm.py +548 -0
  559. scitex/stats/correct/_correct_sidak.py +499 -0
  560. scitex/stats/descriptive/__init__.py +85 -0
  561. scitex/stats/descriptive/_circular.py +540 -0
  562. scitex/stats/descriptive/_describe.py +219 -0
  563. scitex/stats/descriptive/_nan.py +518 -0
  564. scitex/stats/descriptive/_real.py +189 -0
  565. scitex/stats/effect_sizes/__init__.py +41 -0
  566. scitex/stats/effect_sizes/_cliffs_delta.py +325 -0
  567. scitex/stats/effect_sizes/_cohens_d.py +342 -0
  568. scitex/stats/effect_sizes/_epsilon_squared.py +315 -0
  569. scitex/stats/effect_sizes/_eta_squared.py +302 -0
  570. scitex/stats/effect_sizes/_prob_superiority.py +296 -0
  571. scitex/stats/posthoc/__init__.py +19 -0
  572. scitex/stats/posthoc/_dunnett.py +463 -0
  573. scitex/stats/posthoc/_games_howell.py +383 -0
  574. scitex/stats/posthoc/_tukey_hsd.py +367 -0
  575. scitex/stats/power/__init__.py +19 -0
  576. scitex/stats/power/_power.py +433 -0
  577. scitex/stats/template.py +119 -0
  578. scitex/stats/utils/__init__.py +62 -0
  579. scitex/stats/utils/_effect_size.py +985 -0
  580. scitex/stats/utils/_formatters.py +270 -0
  581. scitex/stats/utils/_normalizers.py +927 -0
  582. scitex/stats/utils/_power.py +433 -0
  583. scitex/stats_v01/_EffectSizeCalculator.py +488 -0
  584. scitex/stats_v01/_StatisticalValidator.py +411 -0
  585. scitex/stats_v01/__init__.py +60 -0
  586. scitex/stats_v01/_additional_tests.py +415 -0
  587. scitex/{stats → stats_v01}/_p2stars.py +19 -5
  588. scitex/stats_v01/_two_sample_tests.py +141 -0
  589. scitex/stats_v01/desc/__init__.py +83 -0
  590. scitex/stats_v01/desc/_circular.py +540 -0
  591. scitex/stats_v01/desc/_describe.py +219 -0
  592. scitex/stats_v01/desc/_nan.py +518 -0
  593. scitex/{stats/desc/_nan.py → stats_v01/desc/_nan_v01-20250920_145731.py} +23 -12
  594. scitex/stats_v01/desc/_real.py +189 -0
  595. scitex/stats_v01/tests/__corr_test_optimized.py +221 -0
  596. scitex/stats_v01/tests/_corr_test_optimized.py +179 -0
  597. scitex/str/__init__.py +1 -3
  598. scitex/str/_clean_path.py +6 -2
  599. scitex/str/_latex_fallback.py +267 -160
  600. scitex/str/_parse.py +44 -36
  601. scitex/str/_printc.py +1 -3
  602. scitex/template/__init__.py +87 -0
  603. scitex/template/_create_project.py +267 -0
  604. scitex/template/create_pip_project.py +80 -0
  605. scitex/template/create_research.py +80 -0
  606. scitex/template/create_singularity.py +80 -0
  607. scitex/units.py +291 -0
  608. scitex/utils/_compress_hdf5.py +14 -3
  609. scitex/utils/_email.py +21 -2
  610. scitex/utils/_grid.py +6 -4
  611. scitex/utils/_notify.py +13 -10
  612. scitex/utils/_verify_scitex_format.py +589 -0
  613. scitex/utils/_verify_scitex_format_v01.py +370 -0
  614. scitex/utils/template.py +122 -0
  615. scitex/web/_search_pubmed.py +62 -16
  616. scitex-2.1.0.dist-info/LICENSE +21 -0
  617. scitex-2.1.0.dist-info/METADATA +677 -0
  618. scitex-2.1.0.dist-info/RECORD +919 -0
  619. {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/WHEEL +1 -1
  620. scitex-2.1.0.dist-info/entry_points.txt +3 -0
  621. scitex/ai/__Classifiers.py +0 -101
  622. scitex/ai/classification/classification_reporter.py +0 -1137
  623. scitex/ai/classification/classifiers.py +0 -101
  624. scitex/ai/classification_reporter.py +0 -1161
  625. scitex/ai/genai/__init__.py +0 -277
  626. scitex/ai/genai/anthropic_provider.py +0 -320
  627. scitex/ai/genai/anthropic_refactored.py +0 -109
  628. scitex/ai/genai/auth_manager.py +0 -200
  629. scitex/ai/genai/base_provider.py +0 -291
  630. scitex/ai/genai/chat_history.py +0 -307
  631. scitex/ai/genai/cost_tracker.py +0 -276
  632. scitex/ai/genai/deepseek_provider.py +0 -251
  633. scitex/ai/genai/google_provider.py +0 -228
  634. scitex/ai/genai/groq_provider.py +0 -248
  635. scitex/ai/genai/image_processor.py +0 -250
  636. scitex/ai/genai/llama_provider.py +0 -214
  637. scitex/ai/genai/mock_provider.py +0 -127
  638. scitex/ai/genai/model_registry.py +0 -304
  639. scitex/ai/genai/openai_provider.py +0 -293
  640. scitex/ai/genai/perplexity_provider.py +0 -205
  641. scitex/ai/genai/provider_base.py +0 -302
  642. scitex/ai/genai/provider_factory.py +0 -370
  643. scitex/ai/genai/response_handler.py +0 -235
  644. scitex/ai/layer/_Pass.py +0 -21
  645. scitex/ai/layer/__init__.py +0 -10
  646. scitex/ai/layer/_switch.py +0 -8
  647. scitex/ai/metrics/_bACC.py +0 -51
  648. scitex/ai/plt/_learning_curve.py +0 -194
  649. scitex/ai/plt/_optuna_study.py +0 -111
  650. scitex/ai/plt/aucs/__init__.py +0 -2
  651. scitex/ai/plt/aucs/example.py +0 -60
  652. scitex/ai/plt/aucs/pre_rec_auc.py +0 -223
  653. scitex/ai/plt/aucs/roc_auc.py +0 -246
  654. scitex/ai/sampling/undersample.py +0 -29
  655. scitex/db/_SQLite3.py +0 -2136
  656. scitex/db/_SQLite3Mixins/_BlobMixin.py +0 -229
  657. scitex/gen/_close.py +0 -222
  658. scitex/gen/_start.py +0 -451
  659. scitex/general/__init__.py +0 -5
  660. scitex/io/_load_modules/_db.py +0 -24
  661. scitex/life/__init__.py +0 -10
  662. scitex/life/_monitor_rain.py +0 -49
  663. scitex/reproduce/_fix_seeds.py +0 -45
  664. scitex/res/__init__.py +0 -5
  665. scitex/scholar/_local_search.py +0 -454
  666. scitex/scholar/_paper.py +0 -244
  667. scitex/scholar/_pdf_downloader.py +0 -325
  668. scitex/scholar/_search.py +0 -393
  669. scitex/scholar/_vector_search.py +0 -370
  670. scitex/scholar/_web_sources.py +0 -457
  671. scitex/stats/desc/__init__.py +0 -40
  672. scitex-2.0.0.dist-info/METADATA +0 -307
  673. scitex-2.0.0.dist-info/RECORD +0 -572
  674. scitex-2.0.0.dist-info/licenses/LICENSE +0 -7
  675. /scitex/ai/{act → activation}/__init__.py +0 -0
  676. /scitex/ai/{act → activation}/_define.py +0 -0
  677. /scitex/ai/{early_stopping.py → training/_EarlyStopping.py} +0 -0
  678. /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ImportExportMixin.py +0 -0
  679. /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_IndexMixin.py +0 -0
  680. /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_RowMixin.py +0 -0
  681. /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TableMixin.py +0 -0
  682. /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/__init__.py +0 -0
  683. /scitex/{stats → stats_v01}/_calc_partial_corr.py +0 -0
  684. /scitex/{stats → stats_v01}/_corr_test_multi.py +0 -0
  685. /scitex/{stats → stats_v01}/_corr_test_wrapper.py +0 -0
  686. /scitex/{stats → stats_v01}/_describe_wrapper.py +0 -0
  687. /scitex/{stats → stats_v01}/_multiple_corrections.py +0 -0
  688. /scitex/{stats → stats_v01}/_nan_stats.py +0 -0
  689. /scitex/{stats → stats_v01}/_p2stars_wrapper.py +0 -0
  690. /scitex/{stats → stats_v01}/_statistical_tests.py +0 -0
  691. /scitex/{stats/desc/_describe.py → stats_v01/desc/_describe_v01-20250920_145731.py} +0 -0
  692. /scitex/{stats/desc/_real.py → stats_v01/desc/_real_v01-20250920_145731.py} +0 -0
  693. /scitex/{stats → stats_v01}/multiple/__init__.py +0 -0
  694. /scitex/{stats → stats_v01}/multiple/_bonferroni_correction.py +0 -0
  695. /scitex/{stats → stats_v01}/multiple/_fdr_correction.py +0 -0
  696. /scitex/{stats → stats_v01}/multiple/_multicompair.py +0 -0
  697. /scitex/{stats → stats_v01}/tests/__corr_test.py +0 -0
  698. /scitex/{stats → stats_v01}/tests/__corr_test_multi.py +0 -0
  699. /scitex/{stats → stats_v01}/tests/__corr_test_single.py +0 -0
  700. /scitex/{stats → stats_v01}/tests/__init__.py +0 -0
  701. /scitex/{stats → stats_v01}/tests/_brunner_munzel_test.py +0 -0
  702. /scitex/{stats → stats_v01}/tests/_nocorrelation_test.py +0 -0
  703. /scitex/{stats → stats_v01}/tests/_smirnov_grubbs.py +0 -0
  704. {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,490 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-10-03 01:56:15 (ywatanabe)"
4
+ # File: /ssh:sp:/home/ywatanabe/proj/scitex_repo/src/scitex/ml/metrics/_calc_seizure_prediction_metrics.py
5
+ """Calculate clinical seizure prediction metrics.
6
+
7
+ This module provides both window-based and event-based seizure prediction metrics
8
+ following FDA/clinical guidelines.
9
+
10
+ Two Approaches:
11
+ 1. Window-based: Measures % of seizure time windows detected
12
+ 2. Event-based: Measures % of seizure events detected (≥1 alarm per event)
13
+
14
+ Key Metrics:
15
+ - seizure_sensitivity: % detected (interpretation depends on window vs event-based)
16
+ - fp_per_hour: False positives per hour during interictal periods
17
+ - time_in_warning: % of total time in alarm state
18
+
19
+ Clinical Targets (FDA guidelines):
20
+ - Sensitivity ≥ 90%
21
+ - FP/h ≤ 0.2
22
+ - Time in warning ≤ 20%
23
+ """
24
+ from __future__ import annotations
25
+ from typing import Dict
26
+ import numpy as np
27
+ import pandas as pd
28
+
29
+
30
+ def calc_seizure_window_prediction_metrics(
31
+ y_true: np.ndarray,
32
+ y_pred: np.ndarray,
33
+ metadata: pd.DataFrame,
34
+ window_duration_min: float = 1.0,
35
+ ) -> Dict[str, float]:
36
+ """Calculate clinical seizure prediction metrics (window-based).
37
+
38
+ This function calculates window-based sensitivity, meaning it measures
39
+ the percentage of seizure time windows that were correctly identified.
40
+ This is NOT event-based sensitivity (which would measure % of seizure
41
+ events detected regardless of how many windows within each event).
42
+
43
+ Parameters
44
+ ----------
45
+ y_true : np.ndarray
46
+ True labels (string: 'seizure' or 'interictal_control')
47
+ y_pred : np.ndarray
48
+ Predicted labels (string: 'seizure' or 'interictal_control')
49
+ metadata : pd.DataFrame
50
+ Metadata with 'seizure_type' column indicating seizure/interictal periods
51
+ window_duration_min : float, optional
52
+ Duration of each time window in minutes (default: 1.0)
53
+
54
+ Returns
55
+ -------
56
+ Dict[str, float]
57
+ Dictionary containing:
58
+ - seizure_sensitivity: % of seizure *time windows* detected (NOT event-based)
59
+ - fp_per_hour: False positives per hour during interictal periods
60
+ - time_in_warning: % of total time in alarm state
61
+ - n_seizure_windows: Number of seizure windows
62
+ - n_interictal_windows: Number of interictal windows
63
+ - n_true_positives: Correctly predicted seizure windows
64
+ - n_false_positives: Incorrectly predicted as seizure
65
+ - n_false_negatives: Missed seizure windows
66
+ - n_true_negatives: Correctly predicted as interictal
67
+ - meets_sensitivity_target: Whether sensitivity ≥ 90%
68
+ - meets_fp_target: Whether FP/h ≤ 0.2
69
+ - meets_tiw_target: Whether time in warning ≤ 20%
70
+
71
+ Notes
72
+ -----
73
+ - False positives are calculated only during interictal periods
74
+ - True positives/false negatives are calculated only during seizure periods
75
+ - Clinical targets based on FDA guidance for seizure prediction devices
76
+ - For event-based sensitivity, use calc_seizure_event_prediction_metrics instead
77
+
78
+ Example
79
+ -------
80
+ >>> # 1 seizure spanning 20 windows, detect 5 windows
81
+ >>> # Window-based sensitivity: 5/20 = 25%
82
+ >>> # This measures temporal coverage of the seizure
83
+
84
+ References
85
+ ----------
86
+ FDA guidance on seizure prediction devices
87
+ """
88
+ # Create masks for seizure and interictal periods
89
+ seizure_mask = metadata["seizure_type"] == "seizure"
90
+ interictal_mask = metadata["seizure_type"] == "interictal_control"
91
+
92
+ # Convert string labels to binary for calculations
93
+ y_true_bin = (y_true == "seizure").astype(int)
94
+ y_pred_bin = (y_pred == "seizure").astype(int)
95
+
96
+ # True positives (seizure windows correctly identified)
97
+ tp = np.sum((y_true_bin == 1) & (y_pred_bin == 1) & seizure_mask)
98
+
99
+ # False negatives (seizure windows missed)
100
+ fn = np.sum((y_true_bin == 1) & (y_pred_bin == 0) & seizure_mask)
101
+
102
+ # False positives (interictal windows incorrectly alarmed)
103
+ fp = np.sum((y_true_bin == 0) & (y_pred_bin == 1) & interictal_mask)
104
+
105
+ # True negatives (interictal windows correctly identified)
106
+ tn = np.sum((y_true_bin == 0) & (y_pred_bin == 0) & interictal_mask)
107
+
108
+ # Sensitivity (seizure detection rate) - WINDOW-BASED
109
+ n_seizures = seizure_mask.sum()
110
+ seizure_sensitivity = (tp / n_seizures * 100) if n_seizures > 0 else 0.0
111
+
112
+ # False positives per hour
113
+ n_interictal = interictal_mask.sum()
114
+ total_interictal_hours = (n_interictal * window_duration_min) / 60.0
115
+ fp_per_hour = (
116
+ fp / total_interictal_hours if total_interictal_hours > 0 else 0.0
117
+ )
118
+
119
+ # Time in warning (% of total time in alarm state)
120
+ total_windows = len(y_pred)
121
+ alarm_windows = np.sum(y_pred_bin == 1)
122
+ time_in_warning = (
123
+ (alarm_windows / total_windows * 100) if total_windows > 0 else 0.0
124
+ )
125
+
126
+ metrics = {
127
+ # Primary prediction metrics
128
+ "seizure_sensitivity": round(seizure_sensitivity, 3),
129
+ "fp_per_hour": round(fp_per_hour, 3),
130
+ "time_in_warning": round(time_in_warning, 3),
131
+ # Counts (time windows, not events)
132
+ "n_seizure_windows": int(n_seizures),
133
+ "n_interictal_windows": int(n_interictal),
134
+ "n_true_positives": int(tp),
135
+ "n_false_positives": int(fp),
136
+ "n_false_negatives": int(fn),
137
+ "n_true_negatives": int(tn),
138
+ # Clinical targets (FDA/clinical guidelines)
139
+ "meets_sensitivity_target": bool(seizure_sensitivity >= 90.0),
140
+ "meets_fp_target": bool(fp_per_hour <= 0.2),
141
+ "meets_tiw_target": bool(time_in_warning <= 20.0),
142
+ }
143
+
144
+ return metrics
145
+
146
+
147
+ def calc_seizure_event_prediction_metrics(
148
+ y_true: np.ndarray,
149
+ y_pred: np.ndarray,
150
+ metadata: pd.DataFrame,
151
+ window_duration_min: float = 1.0,
152
+ ) -> Dict[str, float]:
153
+ """Calculate clinical seizure prediction metrics (event-based).
154
+
155
+ This function calculates event-based sensitivity, meaning it measures
156
+ whether each seizure EVENT was detected (at least one alarm raised),
157
+ regardless of how many windows within that event were predicted.
158
+
159
+ This is clinically more relevant as one timely alarm per seizure event
160
+ is sufficient for intervention, matching the clinical requirement:
161
+ "Did the system raise an alarm for this seizure?"
162
+
163
+ Parameters
164
+ ----------
165
+ y_true : np.ndarray
166
+ True labels (string: 'seizure' or 'interictal_control')
167
+ y_pred : np.ndarray
168
+ Predicted labels (string: 'seizure' or 'interictal_control')
169
+ metadata : pd.DataFrame
170
+ Metadata with 'seizure_type' and 'seizure_id' columns.
171
+ seizure_id: Unique identifier for each seizure event (e.g., 'sz_001', 'sz_002')
172
+ Should be NaN or empty for interictal periods
173
+ window_duration_min : float, optional
174
+ Duration of each time window in minutes (default: 1.0)
175
+
176
+ Returns
177
+ -------
178
+ Dict[str, float]
179
+ Dictionary containing:
180
+ - seizure_sensitivity: % of seizure *events* detected (event-based)
181
+ - fp_per_hour: False positives per hour during interictal periods
182
+ - time_in_warning: % of total time in alarm state
183
+ - n_seizure_events: Number of unique seizure events
184
+ - n_detected_events: Number of events with at least one alarm
185
+ - n_missed_events: Number of events with zero alarms
186
+ - n_interictal_windows: Number of interictal windows
187
+ - n_false_positives: Incorrectly predicted as seizure
188
+ - n_true_negatives: Correctly predicted as interictal
189
+ - meets_sensitivity_target: Whether sensitivity ≥ 90%
190
+ - meets_fp_target: Whether FP/h ≤ 0.2
191
+ - meets_tiw_target: Whether time in warning ≤ 20%
192
+
193
+ Notes
194
+ -----
195
+ - Requires 'seizure_id' column in metadata to group windows by event
196
+ - False positives are calculated only during interictal periods
197
+ - Event detection requires at least one window predicted as seizure
198
+ - Clinical targets based on FDA guidance for seizure prediction devices
199
+ - For window-based sensitivity, use calc_seizure_window_prediction_metrics instead
200
+
201
+ Example
202
+ -------
203
+ >>> # 1 seizure spanning 20 windows, detect just 1 window
204
+ >>> # Event-based sensitivity: 1/1 = 100% (event was detected!)
205
+ >>> # This measures "did we catch the seizure at all?"
206
+
207
+ References
208
+ ----------
209
+ FDA guidance on seizure prediction devices
210
+ """
211
+ # Validate required column
212
+ if "seizure_id" not in metadata.columns:
213
+ raise ValueError(
214
+ "metadata must contain 'seizure_id' column for event-based metrics. "
215
+ "Use calc_seizure_window_prediction_metrics for window-based metrics."
216
+ )
217
+
218
+ # Create masks
219
+ seizure_mask = metadata["seizure_type"] == "seizure"
220
+ interictal_mask = metadata["seizure_type"] == "interictal_control"
221
+
222
+ # Convert string labels to binary
223
+ y_true_bin = (y_true == "seizure").astype(int)
224
+ y_pred_bin = (y_pred == "seizure").astype(int)
225
+
226
+ # Event-based sensitivity calculation
227
+ # Group by seizure_id and check if any window in that event was predicted
228
+ seizure_events = metadata[seizure_mask]["seizure_id"].unique()
229
+ n_seizure_events = len(seizure_events)
230
+
231
+ detected_events = 0
232
+ for event_id in seizure_events:
233
+ event_mask = (metadata["seizure_id"] == event_id).values
234
+ # Check if at least one window in this event was predicted as seizure
235
+ event_predictions = y_pred_bin[event_mask]
236
+ if np.any(event_predictions == 1):
237
+ detected_events += 1
238
+
239
+ missed_events = n_seizure_events - detected_events
240
+
241
+ # Event-based sensitivity: % of events detected
242
+ seizure_sensitivity = (
243
+ (detected_events / n_seizure_events * 100) if n_seizure_events > 0 else 0.0
244
+ )
245
+
246
+ # False positives (interictal windows incorrectly alarmed)
247
+ fp = np.sum((y_true_bin == 0) & (y_pred_bin == 1) & interictal_mask)
248
+
249
+ # True negatives (interictal windows correctly identified)
250
+ tn = np.sum((y_true_bin == 0) & (y_pred_bin == 0) & interictal_mask)
251
+
252
+ # False positives per hour
253
+ n_interictal = interictal_mask.sum()
254
+ total_interictal_hours = (n_interictal * window_duration_min) / 60.0
255
+ fp_per_hour = (
256
+ fp / total_interictal_hours if total_interictal_hours > 0 else 0.0
257
+ )
258
+
259
+ # Time in warning (% of total time in alarm state)
260
+ total_windows = len(y_pred)
261
+ alarm_windows = np.sum(y_pred_bin == 1)
262
+ time_in_warning = (
263
+ (alarm_windows / total_windows * 100) if total_windows > 0 else 0.0
264
+ )
265
+
266
+ metrics = {
267
+ # Primary prediction metrics
268
+ "seizure_sensitivity": round(seizure_sensitivity, 3),
269
+ "fp_per_hour": round(fp_per_hour, 3),
270
+ "time_in_warning": round(time_in_warning, 3),
271
+ # Counts (events, not windows)
272
+ "n_seizure_events": int(n_seizure_events),
273
+ "n_detected_events": int(detected_events),
274
+ "n_missed_events": int(missed_events),
275
+ "n_interictal_windows": int(n_interictal),
276
+ "n_false_positives": int(fp),
277
+ "n_true_negatives": int(tn),
278
+ # Clinical targets (FDA/clinical guidelines)
279
+ "meets_sensitivity_target": bool(seizure_sensitivity >= 90.0),
280
+ "meets_fp_target": bool(fp_per_hour <= 0.2),
281
+ "meets_tiw_target": bool(time_in_warning <= 20.0),
282
+ }
283
+
284
+ return metrics
285
+
286
+
287
+ # Backward compatibility aliases
288
+ calc_seizure_prediction_metrics = calc_seizure_window_prediction_metrics
289
+ calculate_seizure_prediction_metrics = calc_seizure_window_prediction_metrics
290
+
291
+
292
+ def parse_args():
293
+ """Parse command line arguments."""
294
+ import argparse
295
+
296
+ parser = argparse.ArgumentParser(
297
+ description="Demonstrate seizure prediction metrics calculation"
298
+ )
299
+ parser.add_argument(
300
+ "--n-windows",
301
+ type=int,
302
+ default=1000,
303
+ help="Number of time windows to simulate (default: %(default)s)",
304
+ )
305
+ parser.add_argument(
306
+ "--window-duration",
307
+ type=float,
308
+ default=1.0,
309
+ help="Duration of each window in minutes (default: %(default)s)",
310
+ )
311
+ parser.add_argument(
312
+ "--sensitivity",
313
+ type=float,
314
+ default=0.9,
315
+ help="Target sensitivity to simulate (default: %(default)s)",
316
+ )
317
+ args = parser.parse_args()
318
+ return args
319
+
320
+
321
+ def main(args):
322
+ """Demonstrate seizure prediction metrics with synthetic data."""
323
+ from scitex import logging
324
+
325
+ logger = logging.getLogger(__name__)
326
+
327
+ logger.info("Creating synthetic seizure prediction data")
328
+ logger.info(f" n_windows: {args.n_windows}")
329
+ logger.info(f" window_duration: {args.window_duration} min")
330
+ logger.info(f" target_sensitivity: {args.sensitivity * 100}%")
331
+
332
+ # Create synthetic test data
333
+ n_windows = args.n_windows
334
+ window_duration_min = args.window_duration
335
+
336
+ # Create labels and metadata with seizure_id for event-based metrics
337
+ y_true = np.array(["interictal_control"] * n_windows)
338
+ y_pred = np.array(["interictal_control"] * n_windows)
339
+ metadata = pd.DataFrame({
340
+ "seizure_type": ["interictal_control"] * n_windows,
341
+ "seizure_id": [None] * n_windows # seizure_id for event-based metrics
342
+ })
343
+
344
+ # Add TWO seizure events (event 1: 100-119, event 2: 500-529)
345
+ event1_indices = list(range(100, 120)) # 20 windows
346
+ event2_indices = list(range(500, 530)) # 30 windows
347
+ seizure_indices = event1_indices + event2_indices
348
+
349
+ y_true[event1_indices] = "seizure"
350
+ y_true[event2_indices] = "seizure"
351
+ metadata.loc[event1_indices, "seizure_type"] = "seizure"
352
+ metadata.loc[event1_indices, "seizure_id"] = "sz_001"
353
+ metadata.loc[event2_indices, "seizure_type"] = "seizure"
354
+ metadata.loc[event2_indices, "seizure_id"] = "sz_002"
355
+
356
+ logger.info(f"Created 2 seizure events spanning {len(seizure_indices)} windows total")
357
+ logger.info(f" Event 1 (sz_001): 20 windows")
358
+ logger.info(f" Event 2 (sz_002): 30 windows")
359
+
360
+ # Predict some seizures correctly based on target sensitivity
361
+ # For event-based demo: detect only 1 window from event 1, most of event 2
362
+ n_detect = int(len(seizure_indices) * args.sensitivity)
363
+ # Detect 1 window from event 1, rest from event 2
364
+ detected_indices = [event1_indices[0]] + event2_indices[:n_detect-1]
365
+ y_pred[detected_indices] = "seizure"
366
+
367
+ logger.info(f"Simulating detection of {n_detect}/{len(seizure_indices)} seizure windows")
368
+ logger.info(f" Event 1: 1/20 windows detected")
369
+ logger.info(f" Event 2: {n_detect-1}/30 windows detected")
370
+
371
+ # Add some false positives
372
+ fp_indices = [200, 300, 400, 600, 700]
373
+ y_pred[fp_indices] = "seizure"
374
+
375
+ logger.info(f"Added {len(fp_indices)} false positive alarms")
376
+
377
+ # Calculate WINDOW-BASED metrics
378
+ logger.info("")
379
+ logger.info("Calculating WINDOW-BASED seizure prediction metrics")
380
+ metrics_window = calc_seizure_window_prediction_metrics(
381
+ y_true, y_pred, metadata, window_duration_min
382
+ )
383
+
384
+ # Print window-based results
385
+ logger.info("=" * 70)
386
+ logger.info("WINDOW-BASED Metrics (How well did we cover seizure duration?)")
387
+ logger.info("=" * 70)
388
+ logger.info(f"Seizure Sensitivity: {metrics_window['seizure_sensitivity']:.1f}%")
389
+ logger.info(f"False Positives/Hour: {metrics_window['fp_per_hour']:.3f}")
390
+ logger.info(f"Time in Warning: {metrics_window['time_in_warning']:.1f}%")
391
+ logger.info("")
392
+ logger.info("Counts:")
393
+ logger.info(f" Seizure windows: {metrics_window['n_seizure_windows']}")
394
+ logger.info(f" Interictal windows: {metrics_window['n_interictal_windows']}")
395
+ logger.info(f" True positives: {metrics_window['n_true_positives']}")
396
+ logger.info(f" False positives: {metrics_window['n_false_positives']}")
397
+ logger.info(f" False negatives: {metrics_window['n_false_negatives']}")
398
+ logger.info(f" True negatives: {metrics_window['n_true_negatives']}")
399
+ logger.info("")
400
+ logger.info("Clinical Targets (FDA Guidelines):")
401
+ logger.info(
402
+ f" Meets sensitivity target (≥90%): {metrics_window['meets_sensitivity_target']}"
403
+ )
404
+ logger.info(f" Meets FP/h target (≤0.2): {metrics_window['meets_fp_target']}")
405
+ logger.info(f" Meets time in warning target (≤20%): {metrics_window['meets_tiw_target']}")
406
+ logger.info("=" * 70)
407
+
408
+ # Calculate EVENT-BASED metrics
409
+ logger.info("")
410
+ logger.info("Calculating EVENT-BASED seizure prediction metrics")
411
+ metrics_event = calc_seizure_event_prediction_metrics(
412
+ y_true, y_pred, metadata, window_duration_min
413
+ )
414
+
415
+ # Print event-based results
416
+ logger.info("=" * 70)
417
+ logger.info("EVENT-BASED Metrics (Did we detect each seizure event?)")
418
+ logger.info("=" * 70)
419
+ logger.info(f"Seizure Sensitivity: {metrics_event['seizure_sensitivity']:.1f}%")
420
+ logger.info(f"False Positives/Hour: {metrics_event['fp_per_hour']:.3f}")
421
+ logger.info(f"Time in Warning: {metrics_event['time_in_warning']:.1f}%")
422
+ logger.info("")
423
+ logger.info("Counts:")
424
+ logger.info(f" Seizure events: {metrics_event['n_seizure_events']}")
425
+ logger.info(f" Detected events: {metrics_event['n_detected_events']}")
426
+ logger.info(f" Missed events: {metrics_event['n_missed_events']}")
427
+ logger.info(f" Interictal windows: {metrics_event['n_interictal_windows']}")
428
+ logger.info(f" False positives: {metrics_event['n_false_positives']}")
429
+ logger.info(f" True negatives: {metrics_event['n_true_negatives']}")
430
+ logger.info("")
431
+ logger.info("Clinical Targets (FDA Guidelines):")
432
+ logger.info(
433
+ f" Meets sensitivity target (≥90%): {metrics_event['meets_sensitivity_target']}"
434
+ )
435
+ logger.info(f" Meets FP/h target (≤0.2): {metrics_event['meets_fp_target']}")
436
+ logger.info(f" Meets time in warning target (≤20%): {metrics_event['meets_tiw_target']}")
437
+ logger.info("=" * 70)
438
+
439
+ # Comparison summary
440
+ logger.info("")
441
+ logger.info("=" * 70)
442
+ logger.info("KEY DIFFERENCE DEMONSTRATION")
443
+ logger.info("=" * 70)
444
+ logger.info(f"Window-based sensitivity: {metrics_window['seizure_sensitivity']:.1f}% (detected {metrics_window['n_true_positives']}/{metrics_window['n_seizure_windows']} windows)")
445
+ logger.info(f"Event-based sensitivity: {metrics_event['seizure_sensitivity']:.1f}% (detected {metrics_event['n_detected_events']}/{metrics_event['n_seizure_events']} events)")
446
+ logger.info("")
447
+ logger.info("Interpretation:")
448
+ logger.info(" - Window-based: Detected only 1 window from Event 1 → Low sensitivity")
449
+ logger.info(" - Event-based: Detected at least 1 window from BOTH events → 100% sensitivity!")
450
+ logger.info(" - Clinical relevance: One timely alarm per seizure is sufficient")
451
+ logger.info("=" * 70)
452
+
453
+ return 0
454
+
455
+
456
+ def run_main():
457
+ """Initialize scitex framework, run main function, and cleanup."""
458
+ global CONFIG, CC, sys, plt, rng
459
+
460
+ import sys
461
+ import matplotlib.pyplot as plt
462
+ import scitex as stx
463
+
464
+ args = parse_args()
465
+
466
+ CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
467
+ sys,
468
+ plt,
469
+ args=args,
470
+ file=__file__,
471
+ sdir_suffix=None,
472
+ verbose=False,
473
+ agg=True,
474
+ )
475
+
476
+ exit_status = main(args)
477
+
478
+ stx.session.close(
479
+ CONFIG,
480
+ verbose=False,
481
+ notify=False,
482
+ message="",
483
+ exit_status=exit_status,
484
+ )
485
+
486
+
487
+ if __name__ == "__main__":
488
+ run_main()
489
+
490
+ # EOF
@@ -28,7 +28,7 @@ from sklearn.metrics.pairwise import pairwise_distances as _pairwise_distances
28
28
  from sklearn.utils import check_random_state as _check_random_state
29
29
 
30
30
 
31
- def silhouette_score_slow(
31
+ def calc_silhouette_score_slow(
32
32
  X, labels, metric="euclidean", sample_size=None, random_state=None, **kwds
33
33
  ):
34
34
  """Compute the mean Silhouette Coefficient of all samples.
@@ -98,10 +98,10 @@ def silhouette_score_slow(
98
98
  raise ValueError("Distance matrix cannot be precomputed")
99
99
  else:
100
100
  X, labels = X[indices], labels[indices]
101
- return _np.mean(silhouette_samples_slow(X, labels, metric=metric, **kwds))
101
+ return _np.mean(calc_silhouette_samples_slow(X, labels, metric=metric, **kwds))
102
102
 
103
103
 
104
- def silhouette_samples_slow(X, labels, metric="euclidean", **kwds):
104
+ def calc_silhouette_samples_slow(X, labels, metric="euclidean", **kwds):
105
105
  """Compute the Silhouette Coefficient for each sample.
106
106
 
107
107
  The Silhoeutte Coefficient is a measure of how well samples are clustered
@@ -230,7 +230,7 @@ def _nearest_cluster_distance_slow(X, labels, metric, i):
230
230
  return b
231
231
 
232
232
 
233
- def silhouette_score_block(
233
+ def calc_silhouette_score_block(
234
234
  X, labels, metric="euclidean", sample_size=None, random_state=None, n_jobs=1, **kwds
235
235
  ):
236
236
  """Compute the mean Silhouette Coefficient of all samples.
@@ -299,11 +299,11 @@ def silhouette_score_block(
299
299
  else:
300
300
  X, labels = X[indices], labels[indices]
301
301
  return _np.mean(
302
- silhouette_samples_block(X, labels, metric=metric, n_jobs=n_jobs, **kwds)
302
+ calc_silhouette_samples_block(X, labels, metric=metric, n_jobs=n_jobs, **kwds)
303
303
  )
304
304
 
305
305
 
306
- def silhouette_samples_block(X, labels, metric="euclidean", n_jobs=1, **kwds):
306
+ def calc_silhouette_samples_block(X, labels, metric="euclidean", n_jobs=1, **kwds):
307
307
  """Compute the Silhouette Coefficient for each sample.
308
308
 
309
309
  The Silhoeutte Coefficient is a measure of how well samples are clustered
@@ -484,13 +484,20 @@ if __name__ == "__main__":
484
484
  t = time.time() - t0
485
485
  print("Scikit silhouette (%fs): %f" % (t, s))
486
486
  t0 = time.time()
487
- s = silhouette_score_block(X, y)
487
+ s = calc_silhouette_score_block(X, y)
488
488
  t = time.time() - t0
489
489
  print("Block silhouette (%fs): %f" % (t, s))
490
490
  t0 = time.time()
491
- s = silhouette_score_block(X, y, n_jobs=2)
491
+ s = calc_silhouette_score_block(X, y, n_jobs=2)
492
492
  t = time.time() - t0
493
493
  print("Block silhouette parallel (%fs): %f" % (t, s))
494
494
 
495
495
 
496
+
497
+ # Backward compatibility aliases (deprecated, will be removed in future)
498
+ silhouette_score_slow = calc_silhouette_score_slow
499
+ silhouette_samples_slow = calc_silhouette_samples_slow
500
+ silhouette_score_block = calc_silhouette_score_block
501
+ silhouette_samples_block = calc_silhouette_samples_block
502
+
496
503
  # EOF
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-10-02 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex_repo/src/scitex/ml/metrics/_normalize_labels.py
5
+
6
+ """Label normalization utility for classification metrics."""
7
+
8
+ __FILE__ = __file__
9
+
10
+ from typing import List, Optional, Tuple
11
+ import numpy as np
12
+ from sklearn.preprocessing import LabelEncoder
13
+
14
+
15
+ def normalize_labels(
16
+ y_true: np.ndarray,
17
+ y_pred: np.ndarray,
18
+ labels: Optional[List] = None,
19
+ ) -> Tuple[np.ndarray, np.ndarray, List, LabelEncoder]:
20
+ """
21
+ Normalize labels using sklearn.preprocessing.LabelEncoder.
22
+
23
+ Parameters
24
+ ----------
25
+ y_true : np.ndarray
26
+ True labels (can be str or int)
27
+ y_pred : np.ndarray
28
+ Predicted labels (can be str or int)
29
+ labels : List, optional
30
+ Expected label list. If provided, will be used as display names.
31
+
32
+ Returns
33
+ -------
34
+ y_true_norm : np.ndarray
35
+ Normalized true labels (integers 0, 1, 2, ...)
36
+ y_pred_norm : np.ndarray
37
+ Normalized predicted labels (integers 0, 1, 2, ...)
38
+ label_names : List
39
+ List of label names in order
40
+ encoder : LabelEncoder
41
+ Fitted encoder for inverse transform
42
+
43
+ Notes
44
+ -----
45
+ Uses sklearn.preprocessing.LabelEncoder for robust label handling.
46
+ Handles the edge case where data contains integers but labels are strings
47
+ (e.g., y_true=[0,1,0,1] with labels=['Negative', 'Positive']).
48
+ """
49
+ # Get unique values from data
50
+ all_data_labels = np.unique(np.concatenate([y_true, y_pred]))
51
+
52
+ # Create encoder
53
+ le = LabelEncoder()
54
+
55
+ # Handle edge case: integer data with string label names
56
+ if labels is not None:
57
+ # Check if data is integers but labels are strings
58
+ data_is_int = isinstance(all_data_labels[0], (int, np.integer))
59
+ labels_are_str = isinstance(labels[0], str)
60
+
61
+ if data_is_int and labels_are_str:
62
+ # Data: [0, 1], labels: ['Negative', 'Positive']
63
+ # Fit encoder on the integer data
64
+ le.fit(all_data_labels)
65
+ # But use provided labels as names for display
66
+ label_names = labels
67
+ else:
68
+ # Normal case: fit on provided labels
69
+ le.fit(labels)
70
+ label_names = list(le.classes_)
71
+ else:
72
+ # No labels provided: fit on observed data
73
+ le.fit(all_data_labels)
74
+ label_names = list(le.classes_)
75
+
76
+ # Transform to integers
77
+ y_true_norm = le.transform(y_true)
78
+ y_pred_norm = le.transform(y_pred)
79
+
80
+ return y_true_norm, y_pred_norm, label_names, le
81
+
82
+
83
+ # EOF