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,634 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-10-01 20:48:08 (ywatanabe)"
4
+ # File: /ssh:sp:/home/ywatanabe/proj/scitex_repo/src/scitex/stats/correct/_correct_fdr.py
5
+ # ----------------------------------------
6
+ from __future__ import annotations
7
+ import os
8
+ __FILE__ = __file__
9
+ __DIR__ = os.path.dirname(__FILE__)
10
+ # ----------------------------------------
11
+
12
+ """
13
+ Functionalities:
14
+ - Apply False Discovery Rate (FDR) correction for multiple comparisons
15
+ - Implement Benjamini-Hochberg and Benjamini-Yekutieli procedures
16
+ - Support both dict and DataFrame inputs
17
+ - Maintain full result information with adjusted values
18
+
19
+ Dependencies:
20
+ - packages: numpy, pandas
21
+
22
+ IO:
23
+ - input: Test results with p-values (dict, list of dicts, or DataFrame)
24
+ - output: Results with adjusted p-values and significance (same format as input)
25
+ """
26
+
27
+ """Imports"""
28
+ import argparse
29
+ from typing import Any, Dict, List, Literal, Optional, Union
30
+
31
+ import matplotlib
32
+ import matplotlib.axes
33
+ import numpy as np
34
+ import pandas as pd
35
+ import scitex as stx
36
+ from scitex.logging import getLogger
37
+
38
+ logger = getLogger(__name__)
39
+
40
+ """Functions"""
41
+
42
+
43
+ def correct_fdr(
44
+ results: Union[Dict[str, Any], List[Dict[str, Any]], pd.DataFrame],
45
+ alpha: float = 0.05,
46
+ method: Literal["bh", "by"] = "bh",
47
+ return_as: str = None,
48
+ verbose: bool = True,
49
+ plot: bool = False,
50
+ ax: Optional[matplotlib.axes.Axes] = None,
51
+ ) -> Union[Dict[str, Any], List[Dict[str, Any]], pd.DataFrame]:
52
+ """
53
+ Apply False Discovery Rate (FDR) correction for multiple comparisons.
54
+
55
+ Parameters
56
+ ----------
57
+ results : dict, list of dict, or DataFrame
58
+ Test results containing 'pvalue' field(s)
59
+ - Single dict: one test result
60
+ - List of dicts: multiple test results
61
+ - DataFrame: multiple test results (one per row)
62
+ alpha : float, default 0.05
63
+ False discovery rate to control
64
+ method : {'bh', 'by'}, default 'bh'
65
+ FDR control method:
66
+ - 'bh': Benjamini-Hochberg (assumes independence or positive dependence)
67
+ - 'by': Benjamini-Yekutieli (valid under arbitrary dependence)
68
+ return_as : {'dict', 'dataframe', None}, optional
69
+ Force specific return format. If None, matches input format.
70
+ verbose : bool, default True
71
+ Whether to log progress information
72
+ plot : bool, default False
73
+ Whether to generate visualization
74
+ ax : matplotlib.axes.Axes, optional
75
+ Axes object to plot on. If None and plot=True, creates new figure.
76
+ If provided, automatically enables plotting.
77
+
78
+ Returns
79
+ -------
80
+ results : dict, list of dict, or DataFrame
81
+ Results with added fields:
82
+ - pvalue_adjusted: FDR-adjusted p-value (q-value)
83
+ - alpha_adjusted: Effective alpha threshold for each test
84
+ - rejected: Whether null hypothesis is rejected
85
+ - pstars: Significance stars (using adjusted p-value)
86
+
87
+ Notes
88
+ -----
89
+ **Benjamini-Hochberg (BH) Procedure:**
90
+
91
+ For m tests with p-values p₁ ≤ p₂ ≤ ... ≤ pₘ:
92
+
93
+ 1. Order p-values from smallest to largest
94
+ 2. Find largest i such that: p_i ≤ (i/m) × α
95
+ 3. Reject H₀ for tests 1, 2, ..., i
96
+
97
+ Adjusted p-values (q-values):
98
+
99
+ .. math::
100
+ q_i = \\min_{j \\geq i} \\left( \\frac{m \\cdot p_j}{j} \\right)
101
+
102
+ **Benjamini-Yekutieli (BY) Procedure:**
103
+
104
+ More conservative, valid under arbitrary dependence:
105
+
106
+ .. math::
107
+ q_i = c(m) \\cdot \\min_{j \\geq i} \\left( \\frac{m \\cdot p_j}{j} \\right)
108
+
109
+ where :math:`c(m) = \\sum_{i=1}^{m} \\frac{1}{i} \\approx \\ln(m) + 0.5772`
110
+
111
+ **FDR vs FWER:**
112
+
113
+ - FWER (Bonferroni): Controls probability of ANY false positive
114
+ - FDR: Controls expected proportion of false positives among rejections
115
+
116
+ .. math::
117
+ FDR = E\\left[\\frac{\\text{False Positives}}{\\text{Total Rejections}}\\right]
118
+
119
+ **Advantages:**
120
+ - More powerful than Bonferroni (especially with many tests)
121
+ - Scales well to large m
122
+ - Balances Type I and Type II errors
123
+
124
+ **Disadvantages:**
125
+ - Weaker control than FWER methods
126
+ - May allow some false positives
127
+ - BH requires independence assumption
128
+
129
+ **When to use:**
130
+ - Large number of tests (m > 10)
131
+ - Exploratory analysis
132
+ - Can tolerate some false positives
133
+ - Need higher power than Bonferroni
134
+
135
+ References
136
+ ----------
137
+ .. [1] Benjamini, Y., & Hochberg, Y. (1995). "Controlling the false
138
+ discovery rate: a practical and powerful approach to multiple
139
+ testing". Journal of the Royal Statistical Society, Series B, 57(1), 289-300.
140
+ .. [2] Benjamini, Y., & Yekutieli, D. (2001). "The control of the false
141
+ discovery rate in multiple testing under dependency". Annals of
142
+ Statistics, 29(4), 1165-1188.
143
+
144
+ Examples
145
+ --------
146
+ >>> # Multiple tests
147
+ >>> results = [
148
+ ... {'pvalue': 0.001, 'var_x': 'A', 'var_y': 'B'},
149
+ ... {'pvalue': 0.010, 'var_x': 'A', 'var_y': 'C'},
150
+ ... {'pvalue': 0.050, 'var_x': 'B', 'var_y': 'C'},
151
+ ... {'pvalue': 0.100, 'var_x': 'A', 'var_y': 'D'}
152
+ ... ]
153
+ >>> corrected = correct_fdr(results)
154
+ >>> [r['pvalue_adjusted'] for r in corrected]
155
+ [0.004, 0.02, 0.0666..., 0.1]
156
+
157
+ >>> # BH vs BY comparison
158
+ >>> corrected_bh = correct_fdr(results, method='bh')
159
+ >>> corrected_by = correct_fdr(results, method='by')
160
+ >>> corrected_bh[0]['pvalue_adjusted'] < corrected_by[0]['pvalue_adjusted']
161
+ True
162
+ """
163
+ from ..utils._formatters import p2stars
164
+ from ..utils._normalizers import force_dataframe, to_dict
165
+
166
+ if verbose:
167
+ method_name = (
168
+ "Benjamini-Hochberg" if method == "bh" else "Benjamini-Yekutieli"
169
+ )
170
+ logger.info(f"Applying FDR correction ({method_name})")
171
+
172
+ # Store original input type
173
+ input_type = type(results)
174
+ is_single_dict = isinstance(results, dict)
175
+
176
+ # Convert to DataFrame for processing
177
+ if isinstance(results, dict):
178
+ results_list = [results]
179
+ elif isinstance(results, list):
180
+ results_list = results
181
+ else: # DataFrame
182
+ results_list = None
183
+
184
+ if results_list is not None:
185
+ df = force_dataframe(results_list, fill_na=False, enforce_types=False)
186
+ else:
187
+ df = results.copy()
188
+
189
+ # Store original order
190
+ df["_original_order"] = np.arange(len(df))
191
+
192
+ # Number of tests
193
+ m = len(df)
194
+ if verbose:
195
+ logger.info(f"Number of tests: {m}, alpha: {alpha}")
196
+
197
+ # Sort by p-value
198
+ df_sorted = df.sort_values("pvalue").copy()
199
+ pvalues = df_sorted["pvalue"].values
200
+
201
+ # Compute adjusted p-values (q-values)
202
+ if method == "bh":
203
+ # Benjamini-Hochberg
204
+ ranks = np.arange(1, m + 1)
205
+ q_values = np.minimum.accumulate((pvalues * m / ranks)[::-1])[::-1]
206
+ q_values = np.minimum(q_values, 1.0)
207
+
208
+ elif method == "by":
209
+ # Benjamini-Yekutieli
210
+ # c(m) = sum(1/i) for i in 1:m ≈ ln(m) + γ (Euler-Mascheroni constant)
211
+ c_m = np.sum(1.0 / np.arange(1, m + 1))
212
+ ranks = np.arange(1, m + 1)
213
+ q_values = np.minimum.accumulate((pvalues * m * c_m / ranks)[::-1])[
214
+ ::-1
215
+ ]
216
+ q_values = np.minimum(q_values, 1.0)
217
+
218
+ else:
219
+ raise ValueError(f"Unknown method: {method}. Use 'bh' or 'by'.")
220
+
221
+ df_sorted["pvalue_adjusted"] = q_values
222
+
223
+ # Compute adjusted alpha threshold for each test
224
+ if "alpha" in df.columns:
225
+ alpha_values = df_sorted["alpha"].fillna(alpha)
226
+ else:
227
+ alpha_values = alpha
228
+
229
+ # For FDR, the effective alpha threshold varies by rank
230
+ ranks = np.arange(1, m + 1)
231
+ if method == "bh":
232
+ alpha_adj = alpha_values * ranks / m
233
+ else: # by
234
+ c_m = np.sum(1.0 / np.arange(1, m + 1))
235
+ alpha_adj = alpha_values * ranks / (m * c_m)
236
+
237
+ df_sorted["alpha_adjusted"] = alpha_adj
238
+
239
+ # Determine rejections using BH/BY procedure
240
+ # Find largest i where p_i <= (i/m) * alpha
241
+ if method == "bh":
242
+ threshold = alpha * ranks / m
243
+ else:
244
+ c_m = np.sum(1.0 / np.arange(1, m + 1))
245
+ threshold = alpha * ranks / (m * c_m)
246
+
247
+ # Find the largest rank where p-value is below threshold
248
+ significant = pvalues <= threshold
249
+ if np.any(significant):
250
+ max_significant_rank = np.max(np.where(significant)[0]) + 1
251
+ df_sorted["rejected"] = np.arange(1, m + 1) <= max_significant_rank
252
+ else:
253
+ df_sorted["rejected"] = False
254
+
255
+ # Update significance stars based on adjusted p-values
256
+ df_sorted["pstars"] = df_sorted["pvalue_adjusted"].apply(p2stars)
257
+
258
+ # Restore original order
259
+ df_result = df_sorted.sort_values("_original_order").drop(
260
+ columns=["_original_order"]
261
+ )
262
+
263
+ # Log results summary
264
+ if verbose:
265
+ rejections = df_result["rejected"].sum()
266
+ logger.info(
267
+ f"FDR correction complete: {rejections}/{m} hypotheses rejected"
268
+ )
269
+
270
+ # Log detailed results if not too many tests
271
+ if m <= 10:
272
+ logger.info("\nDetailed results:")
273
+ for idx, row in df_result.iterrows():
274
+ comparison = ""
275
+ if "var_x" in row and "var_y" in row:
276
+ comparison = f"{row['var_x']} vs {row['var_y']}: "
277
+ elif "test_method" in row:
278
+ comparison = f"{row['test_method']}: "
279
+ elif "comparison" in row:
280
+ comparison = f"{row['comparison']}: "
281
+
282
+ logger.info(
283
+ f" {comparison}"
284
+ f"p = {row['pvalue']:.4f} → q = {row['pvalue_adjusted']:.4f} "
285
+ f"{row['pstars']}, rejected = {row['rejected']}"
286
+ )
287
+
288
+ # Auto-enable plotting if ax is provided
289
+ if ax is not None:
290
+ plot = True
291
+
292
+ # Generate plot if requested
293
+ if plot:
294
+ if ax is None:
295
+ import matplotlib.pyplot as plt
296
+ fig, ax = plt.subplots(figsize=(10, 6))
297
+ _plot_fdr(df_result, alpha, method, ax)
298
+
299
+ # Determine return format
300
+ if return_as == "dataframe":
301
+ return df_result
302
+ elif return_as == "dict":
303
+ if is_single_dict:
304
+ return to_dict(df_result, row=0)
305
+ else:
306
+ return df_result.to_dict("records")
307
+ else:
308
+ # Match input format
309
+ if input_type == dict:
310
+ return to_dict(df_result, row=0)
311
+ elif input_type == list:
312
+ return df_result.to_dict("records")
313
+ else: # DataFrame
314
+ return df_result
315
+
316
+
317
+ def _plot_fdr(df, alpha, method, ax):
318
+ """Create visualization for FDR correction on given axes."""
319
+ m = len(df)
320
+ x = np.arange(m)
321
+
322
+ # Plot original p-values and q-values
323
+ ax.scatter(x, df["pvalue"], label="Original p-values", alpha=0.7, s=100, color="C0")
324
+ ax.scatter(x, df["pvalue_adjusted"], label="Q-values (FDR-adjusted)", alpha=0.7, s=100, color="C1", marker="s")
325
+
326
+ # Connect original to adjusted with lines
327
+ for i in range(m):
328
+ ax.plot([i, i], [df["pvalue"].iloc[i], df["pvalue_adjusted"].iloc[i]],
329
+ "k-", alpha=0.3, linewidth=0.5)
330
+
331
+ # Add significance threshold
332
+ ax.axhline(alpha, color="red", linestyle="--", linewidth=2, alpha=0.5, label=f"α = {alpha}")
333
+
334
+ # Formatting
335
+ method_name = "Benjamini-Hochberg" if method == "bh" else "Benjamini-Yekutieli"
336
+ ax.set_xlabel("Test Index")
337
+ ax.set_ylabel("P-value / Q-value")
338
+ rejections = df["rejected"].sum()
339
+ ax.set_title(f"FDR Correction ({method_name}, m={m} tests)\n"
340
+ f"{rejections}/{m} hypotheses rejected")
341
+ ax.set_yscale("log")
342
+ ax.grid(True, alpha=0.3)
343
+ ax.legend()
344
+
345
+ # Set x-axis labels if there are comparison names
346
+ if m <= 20:
347
+ labels = []
348
+ for idx, row in df.iterrows():
349
+ if "var_x" in row and "var_y" in row:
350
+ labels.append(f"{row['var_x']}\nvs\n{row['var_y']}")
351
+ elif "test_method" in row:
352
+ labels.append(row["test_method"])
353
+ elif "comparison" in row:
354
+ labels.append(row["comparison"])
355
+ else:
356
+ labels.append(f"Test {len(labels)+1}")
357
+ ax.set_xticks(x)
358
+ ax.set_xticklabels(labels, rotation=45, ha="right", fontsize=8)
359
+ else:
360
+ ax.set_xlabel(f"Test Index (1-{m})")
361
+
362
+
363
+ """Main function"""
364
+
365
+
366
+ def main(args):
367
+ """Demonstrate FDR correction."""
368
+ logger.info("Demonstrating False Discovery Rate correction")
369
+
370
+ # Example 1: Single test (no correction needed)
371
+ logger.info("\n=== Example 1: Single test ===")
372
+
373
+ single_result = {
374
+ "var_x": "Control",
375
+ "var_y": "Treatment",
376
+ "pvalue": 0.04,
377
+ "alpha": 0.05,
378
+ }
379
+
380
+ corrected_single = correct_fdr(single_result, verbose=args.verbose)
381
+
382
+ # Example 2: Multiple tests - BH method
383
+ logger.info("\n=== Example 2: Multiple tests (Benjamini-Hochberg) ===")
384
+
385
+ multiple_results = [
386
+ {"var_x": "A", "var_y": "B", "pvalue": 0.001},
387
+ {"var_x": "A", "var_y": "C", "pvalue": 0.010},
388
+ {"var_x": "A", "var_y": "D", "pvalue": 0.050},
389
+ {"var_x": "B", "var_y": "C", "pvalue": 0.100},
390
+ {"var_x": "B", "var_y": "D", "pvalue": 0.200},
391
+ ]
392
+
393
+ corrected_bh = correct_fdr(
394
+ multiple_results, method="bh", alpha=0.05, verbose=args.verbose
395
+ )
396
+
397
+ # Example 3: BH vs BY comparison
398
+ logger.info("\n=== Example 3: BH vs BY comparison ===")
399
+
400
+ corrected_by = correct_fdr(
401
+ multiple_results, method="by", alpha=0.05, verbose=args.verbose
402
+ )
403
+
404
+ # Example 4: Bonferroni vs FDR
405
+ logger.info("\n=== Example 4: Bonferroni vs FDR comparison ===")
406
+
407
+ from ._correct_bonferroni import correct_bonferroni
408
+
409
+ corrected_bonf = correct_bonferroni(
410
+ multiple_results, alpha=0.05, verbose=False
411
+ )
412
+
413
+ n_rejected_bonf = sum(r["rejected"] for r in corrected_bonf)
414
+ n_rejected_fdr = sum(r["rejected"] for r in corrected_bh)
415
+
416
+ logger.info(f"Bonferroni rejections: {n_rejected_bonf}")
417
+ logger.info(f"FDR (BH) rejections: {n_rejected_fdr}")
418
+ logger.info(f"FDR is more powerful (rejects more tests)")
419
+
420
+ # Example 5: Many tests
421
+ logger.info("\n=== Example 5: Large scale comparison (m=100) ===")
422
+
423
+ np.random.seed(42)
424
+
425
+ # Simulate 100 tests: 20 true positives, 80 true negatives
426
+ many_results = []
427
+
428
+ # True positives (small p-values)
429
+ for i in range(20):
430
+ p = np.random.beta(1, 50) # Small p-values
431
+ many_results.append(
432
+ {
433
+ "var_x": f"Var_{i}",
434
+ "var_y": "Control",
435
+ "pvalue": p,
436
+ "truth": "positive",
437
+ }
438
+ )
439
+
440
+ # True negatives (large p-values)
441
+ for i in range(20, 100):
442
+ p = np.random.uniform(0.1, 1.0) # Large p-values
443
+ many_results.append(
444
+ {
445
+ "var_x": f"Var_{i}",
446
+ "var_y": "Control",
447
+ "pvalue": p,
448
+ "truth": "negative",
449
+ }
450
+ )
451
+
452
+ corrected_fdr_many = correct_fdr(many_results, method="bh", verbose=False)
453
+ corrected_bonf_many = correct_bonferroni(many_results, verbose=False)
454
+
455
+ # Calculate confusion metrics
456
+ def calc_metrics(corrected, truth_col="truth"):
457
+ tp = sum(
458
+ 1
459
+ for r in corrected
460
+ if r["rejected"] and r.get(truth_col) == "positive"
461
+ )
462
+ fp = sum(
463
+ 1
464
+ for r in corrected
465
+ if r["rejected"] and r.get(truth_col) == "negative"
466
+ )
467
+ fn = sum(
468
+ 1
469
+ for r in corrected
470
+ if not r["rejected"] and r.get(truth_col) == "positive"
471
+ )
472
+ tn = sum(
473
+ 1
474
+ for r in corrected
475
+ if not r["rejected"] and r.get(truth_col) == "negative"
476
+ )
477
+ return tp, fp, fn, tn
478
+
479
+ tp_fdr, fp_fdr, fn_fdr, tn_fdr = calc_metrics(corrected_fdr_many)
480
+ tp_bonf, fp_bonf, fn_bonf, tn_bonf = calc_metrics(corrected_bonf_many)
481
+
482
+ logger.info("FDR (BH) Performance:")
483
+ logger.info(f" True Positives: {tp_fdr} / 20")
484
+ logger.info(f" False Positives: {fp_fdr}")
485
+ logger.info(f" Power: {tp_fdr / 20:.2%}")
486
+ if tp_fdr + fp_fdr > 0:
487
+ logger.info(f" FDR: {fp_fdr / (tp_fdr + fp_fdr):.2%}")
488
+
489
+ logger.info("\nBonferroni Performance:")
490
+ logger.info(f" True Positives: {tp_bonf} / 20")
491
+ logger.info(f" False Positives: {fp_bonf}")
492
+ logger.info(f" Power: {tp_bonf / 20:.2%}")
493
+ if tp_bonf + fp_bonf > 0:
494
+ logger.info(f" FDR: {fp_bonf / (tp_bonf + fp_bonf):.2%}")
495
+
496
+ # Create visualization
497
+ logger.info("\n=== Creating visualization ===")
498
+
499
+ fig, axes = stx.plt.subplots(2, 2, figsize=(12, 10))
500
+
501
+ # Plot 1: Q-values vs P-values
502
+ ax = axes[0, 0]
503
+
504
+ test_pvalues = np.array([r["pvalue"] for r in corrected_bh])
505
+ test_qvalues = np.array([r["pvalue_adjusted"] for r in corrected_bh])
506
+
507
+ ax.scatter(test_pvalues, test_qvalues, s=100, alpha=0.6)
508
+ ax.plot([0, 1], [0, 1], "k--", alpha=0.3, label="y = x")
509
+ ax.set_xlabel("Original P-value")
510
+ ax.set_ylabel("Adjusted P-value (Q-value)")
511
+ ax.set_title("FDR: P-values vs Q-values")
512
+ ax.legend()
513
+ ax.grid(True, alpha=0.3)
514
+
515
+ # Plot 2: BH vs BY
516
+ ax = axes[0, 1]
517
+
518
+ bh_qvalues = np.array([r["pvalue_adjusted"] for r in corrected_bh])
519
+ by_qvalues = np.array([r["pvalue_adjusted"] for r in corrected_by])
520
+
521
+ ax.scatter(bh_qvalues, by_qvalues, s=100, alpha=0.6)
522
+ ax.plot([0, 1], [0, 1], "k--", alpha=0.3, label="y = x")
523
+ ax.set_xlabel("BH Q-value")
524
+ ax.set_ylabel("BY Q-value")
525
+ ax.set_title("BH vs BY (BY is more conservative)")
526
+ ax.legend()
527
+ ax.grid(True, alpha=0.3)
528
+
529
+ # Plot 3: Power comparison across m
530
+ ax = axes[1, 0]
531
+
532
+ m_vals = np.arange(5, 101, 5)
533
+ alpha = 0.05
534
+ alpha_bonf = alpha / m_vals
535
+ alpha_fdr = alpha # FDR maintains similar threshold
536
+
537
+ ax.plot(m_vals, alpha_bonf, label="Bonferroni", linewidth=2)
538
+ ax.axhline(
539
+ alpha_fdr, color="green", linestyle="--", linewidth=2, label="FDR (BH)"
540
+ )
541
+ ax.set_xlabel("Number of Tests (m)")
542
+ ax.set_ylabel("Effective α")
543
+ ax.set_title("FDR Maintains Power vs Bonferroni")
544
+ ax.legend()
545
+ ax.grid(True, alpha=0.3)
546
+ ax.set_yscale("log")
547
+
548
+ # Plot 4: ROC-like comparison
549
+ ax = axes[1, 1]
550
+
551
+ # Vary alpha and compute rejections
552
+ alphas = [0.001, 0.01, 0.05, 0.10, 0.20]
553
+ bonf_tps = []
554
+ bonf_fps = []
555
+ fdr_tps = []
556
+ fdr_fps = []
557
+
558
+ for a in alphas:
559
+ corr_bonf = correct_bonferroni(many_results, alpha=a, verbose=False)
560
+ corr_fdr = correct_fdr(
561
+ many_results, alpha=a, method="bh", verbose=False
562
+ )
563
+
564
+ tp_b, fp_b, _, _ = calc_metrics(corr_bonf)
565
+ tp_f, fp_f, _, _ = calc_metrics(corr_fdr)
566
+
567
+ bonf_tps.append(tp_b / 20) # Sensitivity
568
+ bonf_fps.append(fp_b / 80) # FPR
569
+ fdr_tps.append(tp_f / 20)
570
+ fdr_fps.append(fp_f / 80)
571
+
572
+ ax.plot(
573
+ bonf_fps, bonf_tps, "o-", linewidth=2, markersize=8, label="Bonferroni"
574
+ )
575
+ ax.plot(
576
+ fdr_fps, fdr_tps, "s-", linewidth=2, markersize=8, label="FDR (BH)"
577
+ )
578
+ ax.plot([0, 1], [0, 1], "k--", alpha=0.3)
579
+ ax.set_xlabel("False Positive Rate")
580
+ ax.set_ylabel("True Positive Rate (Power)")
581
+ ax.set_title("Power vs FPR Trade-off")
582
+ ax.legend()
583
+ ax.grid(True, alpha=0.3)
584
+
585
+ plt.tight_layout()
586
+
587
+ # Save
588
+ stx.io.save(fig, "./fdr_demo.jpg")
589
+ logger.info("Visualization saved")
590
+
591
+ return 0
592
+
593
+
594
+ def parse_args():
595
+ """Parse command line arguments."""
596
+ parser = argparse.ArgumentParser(description="Demonstrate FDR correction")
597
+ parser.add_argument(
598
+ "--verbose", action="store_true", help="Enable verbose output"
599
+ )
600
+ return parser.parse_args()
601
+
602
+
603
+ def run_main():
604
+ """Initialize SciTeX framework and run main."""
605
+ global CONFIG, sys, plt, rng
606
+
607
+ import sys
608
+
609
+ import matplotlib.pyplot as plt
610
+
611
+ args = parse_args()
612
+
613
+ CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
614
+ sys,
615
+ plt,
616
+ args=args,
617
+ file=__file__,
618
+ verbose=args.verbose,
619
+ agg=True,
620
+ )
621
+
622
+ exit_status = main(args)
623
+
624
+ stx.session.close(
625
+ CONFIG,
626
+ verbose=args.verbose,
627
+ exit_status=exit_status,
628
+ )
629
+
630
+
631
+ if __name__ == "__main__":
632
+ run_main()
633
+
634
+ # EOF