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.
- scitex/__init__.py +53 -15
- scitex/__main__.py +72 -26
- scitex/__version__.py +1 -1
- scitex/_sh.py +145 -23
- scitex/ai/__init__.py +30 -16
- scitex/ai/_gen_ai/_Anthropic.py +5 -7
- scitex/ai/_gen_ai/_BaseGenAI.py +2 -2
- scitex/ai/_gen_ai/_DeepSeek.py +10 -2
- scitex/ai/_gen_ai/_Google.py +2 -2
- scitex/ai/_gen_ai/_Llama.py +2 -2
- scitex/ai/_gen_ai/_OpenAI.py +2 -2
- scitex/ai/_gen_ai/_PARAMS.py +51 -65
- scitex/ai/_gen_ai/_Perplexity.py +2 -2
- scitex/ai/_gen_ai/__init__.py +25 -14
- scitex/ai/_gen_ai/_format_output_func.py +4 -4
- scitex/ai/classification/{classifier_server.py → Classifier.py} +5 -5
- scitex/ai/classification/CrossValidationExperiment.py +374 -0
- scitex/ai/classification/__init__.py +43 -4
- scitex/ai/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ai/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ai/classification/reporters/__init__.py +11 -0
- scitex/ai/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ai/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ai/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ai/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ai/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ai/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ai/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ai/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ai/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ai/classification/timeseries/__init__.py +39 -0
- scitex/ai/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ai/clustering/_umap.py +2 -2
- scitex/ai/feature_extraction/vit.py +1 -0
- scitex/ai/feature_selection/__init__.py +30 -0
- scitex/ai/feature_selection/feature_selection.py +364 -0
- scitex/ai/loss/multi_task_loss.py +1 -1
- scitex/ai/metrics/__init__.py +51 -4
- scitex/ai/metrics/_calc_bacc.py +61 -0
- scitex/ai/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ai/metrics/_calc_clf_report.py +78 -0
- scitex/ai/metrics/_calc_conf_mat.py +93 -0
- scitex/ai/metrics/_calc_feature_importance.py +183 -0
- scitex/ai/metrics/_calc_mcc.py +61 -0
- scitex/ai/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ai/metrics/_calc_roc_auc.py +110 -0
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ai/metrics/{silhoute_score_block.py → _calc_silhouette_score.py} +15 -8
- scitex/ai/metrics/_normalize_labels.py +83 -0
- scitex/ai/plt/__init__.py +47 -8
- scitex/ai/plt/{_conf_mat.py → _plot_conf_mat.py} +158 -87
- scitex/ai/plt/_plot_feature_importance.py +323 -0
- scitex/ai/plt/_plot_learning_curve.py +345 -0
- scitex/ai/plt/_plot_optuna_study.py +225 -0
- scitex/ai/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ai/plt/_plot_roc_curve.py +255 -0
- scitex/ai/training/{learning_curve_logger.py → _LearningCurveLogger.py} +197 -213
- scitex/ai/training/__init__.py +2 -2
- scitex/ai/utils/grid_search.py +3 -3
- scitex/benchmark/__init__.py +52 -0
- scitex/benchmark/benchmark.py +400 -0
- scitex/benchmark/monitor.py +370 -0
- scitex/benchmark/profiler.py +297 -0
- scitex/browser/__init__.py +48 -0
- scitex/browser/automation/CookieHandler.py +216 -0
- scitex/browser/automation/__init__.py +7 -0
- scitex/browser/collaboration/__init__.py +55 -0
- scitex/browser/collaboration/auth_helpers.py +94 -0
- scitex/browser/collaboration/collaborative_agent.py +136 -0
- scitex/browser/collaboration/credential_manager.py +188 -0
- scitex/browser/collaboration/interactive_panel.py +400 -0
- scitex/browser/collaboration/persistent_browser.py +170 -0
- scitex/browser/collaboration/shared_session.py +383 -0
- scitex/browser/collaboration/standard_interactions.py +246 -0
- scitex/browser/collaboration/visual_feedback.py +181 -0
- scitex/browser/core/BrowserMixin.py +326 -0
- scitex/browser/core/ChromeProfileManager.py +446 -0
- scitex/browser/core/__init__.py +9 -0
- scitex/browser/debugging/__init__.py +18 -0
- scitex/browser/debugging/_browser_logger.py +657 -0
- scitex/browser/debugging/_highlight_element.py +143 -0
- scitex/browser/debugging/_show_grid.py +154 -0
- scitex/browser/interaction/__init__.py +24 -0
- scitex/browser/interaction/click_center.py +149 -0
- scitex/browser/interaction/click_with_fallbacks.py +206 -0
- scitex/browser/interaction/close_popups.py +498 -0
- scitex/browser/interaction/fill_with_fallbacks.py +209 -0
- scitex/browser/pdf/__init__.py +14 -0
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +200 -0
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +198 -0
- scitex/browser/remote/CaptchaHandler.py +434 -0
- scitex/browser/remote/ZenRowsAPIClient.py +347 -0
- scitex/browser/remote/ZenRowsBrowserManager.py +570 -0
- scitex/browser/remote/__init__.py +11 -0
- scitex/browser/stealth/HumanBehavior.py +344 -0
- scitex/browser/stealth/StealthManager.py +1008 -0
- scitex/browser/stealth/__init__.py +9 -0
- scitex/browser/template.py +122 -0
- scitex/capture/__init__.py +110 -0
- scitex/capture/__main__.py +25 -0
- scitex/capture/capture.py +848 -0
- scitex/capture/cli.py +233 -0
- scitex/capture/gif.py +344 -0
- scitex/capture/mcp_server.py +961 -0
- scitex/capture/session.py +70 -0
- scitex/capture/utils.py +705 -0
- scitex/cli/__init__.py +17 -0
- scitex/cli/cloud.py +447 -0
- scitex/cli/main.py +42 -0
- scitex/cli/scholar.py +280 -0
- scitex/context/_suppress_output.py +5 -3
- scitex/db/__init__.py +30 -3
- scitex/db/__main__.py +75 -0
- scitex/db/_check_health.py +381 -0
- scitex/db/_delete_duplicates.py +25 -386
- scitex/db/_inspect.py +335 -114
- scitex/db/_inspect_optimized.py +301 -0
- scitex/db/{_PostgreSQL.py → _postgresql/_PostgreSQL.py} +3 -3
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BackupMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BatchMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BlobMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ConnectionMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_MaintenanceMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_QueryMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_SchemaMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TransactionMixin.py +1 -1
- scitex/db/_postgresql/__init__.py +6 -0
- scitex/db/_sqlite3/_SQLite3.py +210 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin.py +581 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin_v01-need-_hash-col.py +517 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_BatchMixin.py +1 -1
- scitex/db/_sqlite3/_SQLite3Mixins/_BlobMixin.py +281 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin.py +548 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin_v01-indentation-issues.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ConnectionMixin.py +29 -13
- scitex/db/_sqlite3/_SQLite3Mixins/_GitMixin.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ImportExportMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_IndexMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_MaintenanceMixin.py +2 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_QueryMixin.py +37 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_RowMixin.py +46 -6
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TableMixin.py +56 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TransactionMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/__init__.py +14 -2
- scitex/db/_sqlite3/__init__.py +7 -0
- scitex/db/_sqlite3/_delete_duplicates.py +274 -0
- scitex/decorators/__init__.py +2 -0
- scitex/decorators/_cache_disk.py +13 -5
- scitex/decorators/_cache_disk_async.py +49 -0
- scitex/decorators/_deprecated.py +175 -10
- scitex/decorators/_timeout.py +1 -1
- scitex/dev/_analyze_code_flow.py +2 -2
- scitex/dict/_DotDict.py +73 -15
- scitex/dict/_DotDict_v01-not-handling-recursive-instantiations.py +442 -0
- scitex/dict/_DotDict_v02-not-serializing-Path-object.py +446 -0
- scitex/dict/__init__.py +2 -0
- scitex/dict/_flatten.py +27 -0
- scitex/dsp/_crop.py +2 -2
- scitex/dsp/_demo_sig.py +2 -2
- scitex/dsp/_detect_ripples.py +2 -2
- scitex/dsp/_hilbert.py +2 -2
- scitex/dsp/_listen.py +6 -6
- scitex/dsp/_modulation_index.py +2 -2
- scitex/dsp/_pac.py +1 -1
- scitex/dsp/_psd.py +2 -2
- scitex/dsp/_resample.py +2 -1
- scitex/dsp/_time.py +3 -2
- scitex/dsp/_wavelet.py +3 -2
- scitex/dsp/add_noise.py +2 -2
- scitex/dsp/example.py +1 -0
- scitex/dsp/filt.py +10 -9
- scitex/dsp/template.py +3 -2
- scitex/dsp/utils/_differential_bandpass_filters.py +1 -1
- scitex/dsp/utils/pac.py +2 -2
- scitex/dt/_normalize_timestamp.py +432 -0
- scitex/errors.py +572 -0
- scitex/gen/_DimHandler.py +2 -2
- scitex/gen/__init__.py +37 -7
- scitex/gen/_deprecated_close.py +80 -0
- scitex/gen/_deprecated_start.py +26 -0
- scitex/gen/_detect_environment.py +152 -0
- scitex/gen/_detect_notebook_path.py +169 -0
- scitex/gen/_embed.py +6 -2
- scitex/gen/_get_notebook_path.py +257 -0
- scitex/gen/_less.py +1 -1
- scitex/gen/_list_packages.py +2 -2
- scitex/gen/_norm.py +44 -9
- scitex/gen/_norm_cache.py +269 -0
- scitex/gen/_src.py +3 -5
- scitex/gen/_title_case.py +3 -3
- scitex/io/__init__.py +28 -6
- scitex/io/_glob.py +13 -7
- scitex/io/_load.py +108 -21
- scitex/io/_load_cache.py +303 -0
- scitex/io/_load_configs.py +40 -15
- scitex/io/{_H5Explorer.py → _load_modules/_H5Explorer.py} +80 -17
- scitex/io/_load_modules/_ZarrExplorer.py +114 -0
- scitex/io/_load_modules/_bibtex.py +207 -0
- scitex/io/_load_modules/_hdf5.py +53 -178
- scitex/io/_load_modules/_json.py +5 -3
- scitex/io/_load_modules/_pdf.py +871 -16
- scitex/io/_load_modules/_sqlite3.py +15 -0
- scitex/io/_load_modules/_txt.py +41 -12
- scitex/io/_load_modules/_yaml.py +4 -3
- scitex/io/_load_modules/_zarr.py +126 -0
- scitex/io/_save.py +429 -171
- scitex/io/_save_modules/__init__.py +6 -0
- scitex/io/_save_modules/_bibtex.py +194 -0
- scitex/io/_save_modules/_csv.py +8 -4
- scitex/io/_save_modules/_excel.py +174 -15
- scitex/io/_save_modules/_hdf5.py +251 -226
- scitex/io/_save_modules/_image.py +1 -3
- scitex/io/_save_modules/_json.py +49 -4
- scitex/io/_save_modules/_listed_dfs_as_csv.py +1 -3
- scitex/io/_save_modules/_listed_scalars_as_csv.py +1 -3
- scitex/io/_save_modules/_tex.py +277 -0
- scitex/io/_save_modules/_yaml.py +42 -3
- scitex/io/_save_modules/_zarr.py +160 -0
- scitex/io/utils/__init__.py +20 -0
- scitex/io/utils/h5_to_zarr.py +616 -0
- scitex/linalg/_geometric_median.py +6 -2
- scitex/{gen/_tee.py → logging/_Tee.py} +43 -84
- scitex/logging/__init__.py +122 -0
- scitex/logging/_config.py +158 -0
- scitex/logging/_context.py +103 -0
- scitex/logging/_formatters.py +128 -0
- scitex/logging/_handlers.py +64 -0
- scitex/logging/_levels.py +35 -0
- scitex/logging/_logger.py +163 -0
- scitex/logging/_print_capture.py +95 -0
- scitex/ml/__init__.py +69 -0
- scitex/{ai/genai/anthropic.py → ml/_gen_ai/_Anthropic.py} +13 -19
- scitex/{ai/genai/base_genai.py → ml/_gen_ai/_BaseGenAI.py} +5 -5
- scitex/{ai/genai/deepseek.py → ml/_gen_ai/_DeepSeek.py} +11 -16
- scitex/{ai/genai/google.py → ml/_gen_ai/_Google.py} +7 -15
- scitex/{ai/genai/groq.py → ml/_gen_ai/_Groq.py} +1 -8
- scitex/{ai/genai/llama.py → ml/_gen_ai/_Llama.py} +3 -16
- scitex/{ai/genai/openai.py → ml/_gen_ai/_OpenAI.py} +3 -3
- scitex/{ai/genai/params.py → ml/_gen_ai/_PARAMS.py} +51 -65
- scitex/{ai/genai/perplexity.py → ml/_gen_ai/_Perplexity.py} +3 -14
- scitex/ml/_gen_ai/__init__.py +43 -0
- scitex/{ai/genai/calc_cost.py → ml/_gen_ai/_calc_cost.py} +1 -1
- scitex/{ai/genai/format_output_func.py → ml/_gen_ai/_format_output_func.py} +4 -4
- scitex/{ai/genai/genai_factory.py → ml/_gen_ai/_genai_factory.py} +8 -8
- scitex/ml/activation/__init__.py +8 -0
- scitex/ml/activation/_define.py +11 -0
- scitex/{ai/classifier_server.py → ml/classification/Classifier.py} +5 -5
- scitex/ml/classification/CrossValidationExperiment.py +374 -0
- scitex/ml/classification/__init__.py +46 -0
- scitex/ml/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ml/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ml/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ml/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ml/classification/reporters/__init__.py +11 -0
- scitex/ml/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ml/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ml/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ml/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ml/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ml/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ml/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ml/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ml/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ml/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ml/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ml/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ml/classification/timeseries/__init__.py +39 -0
- scitex/ml/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ml/clustering/__init__.py +11 -0
- scitex/ml/clustering/_pca.py +115 -0
- scitex/ml/clustering/_umap.py +376 -0
- scitex/ml/feature_extraction/__init__.py +56 -0
- scitex/ml/feature_extraction/vit.py +149 -0
- scitex/ml/feature_selection/__init__.py +30 -0
- scitex/ml/feature_selection/feature_selection.py +364 -0
- scitex/ml/loss/_L1L2Losses.py +34 -0
- scitex/ml/loss/__init__.py +12 -0
- scitex/ml/loss/multi_task_loss.py +47 -0
- scitex/ml/metrics/__init__.py +56 -0
- scitex/ml/metrics/_calc_bacc.py +61 -0
- scitex/ml/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ml/metrics/_calc_clf_report.py +78 -0
- scitex/ml/metrics/_calc_conf_mat.py +93 -0
- scitex/ml/metrics/_calc_feature_importance.py +183 -0
- scitex/ml/metrics/_calc_mcc.py +61 -0
- scitex/ml/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ml/metrics/_calc_roc_auc.py +110 -0
- scitex/ml/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ml/metrics/_calc_silhouette_score.py +503 -0
- scitex/ml/metrics/_normalize_labels.py +83 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
- scitex/ml/optim/__init__.py +13 -0
- scitex/ml/optim/_get_set.py +31 -0
- scitex/ml/optim/_optimizers.py +71 -0
- scitex/ml/plt/__init__.py +60 -0
- scitex/ml/plt/_plot_conf_mat.py +663 -0
- scitex/ml/plt/_plot_feature_importance.py +323 -0
- scitex/ml/plt/_plot_learning_curve.py +345 -0
- scitex/ml/plt/_plot_optuna_study.py +225 -0
- scitex/ml/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ml/plt/_plot_roc_curve.py +255 -0
- scitex/ml/sk/__init__.py +11 -0
- scitex/ml/sk/_clf.py +58 -0
- scitex/ml/sk/_to_sktime.py +100 -0
- scitex/ml/sklearn/__init__.py +26 -0
- scitex/ml/sklearn/clf.py +58 -0
- scitex/ml/sklearn/to_sktime.py +100 -0
- scitex/{ai/training/early_stopping.py → ml/training/_EarlyStopping.py} +1 -2
- scitex/{ai → ml/training}/_LearningCurveLogger.py +198 -242
- scitex/ml/training/__init__.py +7 -0
- scitex/ml/utils/__init__.py +22 -0
- scitex/ml/utils/_check_params.py +50 -0
- scitex/ml/utils/_default_dataset.py +46 -0
- scitex/ml/utils/_format_samples_for_sktime.py +26 -0
- scitex/ml/utils/_label_encoder.py +134 -0
- scitex/ml/utils/_merge_labels.py +22 -0
- scitex/ml/utils/_sliding_window_data_augmentation.py +11 -0
- scitex/ml/utils/_under_sample.py +51 -0
- scitex/ml/utils/_verify_n_gpus.py +16 -0
- scitex/ml/utils/grid_search.py +148 -0
- scitex/nn/_BNet.py +15 -9
- scitex/nn/_Filters.py +2 -2
- scitex/nn/_ModulationIndex.py +2 -2
- scitex/nn/_PAC.py +1 -1
- scitex/nn/_Spectrogram.py +12 -3
- scitex/nn/__init__.py +9 -10
- scitex/path/__init__.py +18 -0
- scitex/path/_clean.py +4 -0
- scitex/path/_find.py +9 -4
- scitex/path/_symlink.py +348 -0
- scitex/path/_version.py +4 -3
- scitex/pd/__init__.py +2 -0
- scitex/pd/_get_unique.py +99 -0
- scitex/plt/__init__.py +114 -5
- scitex/plt/_subplots/_AxesWrapper.py +1 -3
- scitex/plt/_subplots/_AxisWrapper.py +7 -3
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +47 -13
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +160 -2
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +26 -4
- scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +322 -0
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +1 -0
- scitex/plt/_subplots/_FigWrapper.py +62 -6
- scitex/plt/_subplots/_export_as_csv.py +43 -27
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +5 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +81 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +20 -5
- scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +35 -18
- scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +15 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +35 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +6 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_text.py +60 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters.py +56 -59
- scitex/plt/ax/_style/_hide_spines.py +1 -3
- scitex/plt/ax/_style/_rotate_labels.py +180 -76
- scitex/plt/ax/_style/_rotate_labels_v01.py +248 -0
- scitex/plt/ax/_style/_set_meta.py +11 -4
- scitex/plt/ax/_style/_set_supxyt.py +3 -3
- scitex/plt/ax/_style/_set_xyt.py +3 -3
- scitex/plt/ax/_style/_share_axes.py +2 -2
- scitex/plt/color/__init__.py +4 -4
- scitex/plt/color/{_get_colors_from_cmap.py → _get_colors_from_conf_matap.py} +7 -7
- scitex/plt/utils/_configure_mpl.py +99 -86
- scitex/plt/utils/_histogram_utils.py +1 -3
- scitex/plt/utils/_is_valid_axis.py +1 -3
- scitex/plt/utils/_scitex_config.py +1 -0
- scitex/repro/__init__.py +75 -0
- scitex/{reproduce → repro}/_gen_ID.py +1 -1
- scitex/{reproduce → repro}/_gen_timestamp.py +1 -1
- scitex/repro_rng/_RandomStateManager.py +590 -0
- scitex/repro_rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/repro_rng/__init__.py +39 -0
- scitex/reproduce/__init__.py +25 -13
- scitex/reproduce/_hash_array.py +22 -0
- scitex/resource/_get_processor_usages.py +4 -4
- scitex/resource/_get_specs.py +2 -2
- scitex/resource/_log_processor_usages.py +2 -2
- scitex/rng/_RandomStateManager.py +590 -0
- scitex/rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/rng/__init__.py +39 -0
- scitex/scholar/__init__.py +309 -19
- scitex/scholar/__main__.py +319 -0
- scitex/scholar/auth/ScholarAuthManager.py +308 -0
- scitex/scholar/auth/__init__.py +12 -0
- scitex/scholar/auth/core/AuthenticationGateway.py +473 -0
- scitex/scholar/auth/core/BrowserAuthenticator.py +386 -0
- scitex/scholar/auth/core/StrategyResolver.py +309 -0
- scitex/scholar/auth/core/__init__.py +16 -0
- scitex/scholar/auth/gateway/_OpenURLLinkFinder.py +120 -0
- scitex/scholar/auth/gateway/_OpenURLResolver.py +209 -0
- scitex/scholar/auth/gateway/__init__.py +38 -0
- scitex/scholar/auth/gateway/_resolve_functions.py +101 -0
- scitex/scholar/auth/providers/BaseAuthenticator.py +166 -0
- scitex/scholar/auth/providers/EZProxyAuthenticator.py +484 -0
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +619 -0
- scitex/scholar/auth/providers/ShibbolethAuthenticator.py +686 -0
- scitex/scholar/auth/providers/__init__.py +18 -0
- scitex/scholar/auth/session/AuthCacheManager.py +189 -0
- scitex/scholar/auth/session/SessionManager.py +159 -0
- scitex/scholar/auth/session/__init__.py +11 -0
- scitex/scholar/auth/sso/BaseSSOAutomator.py +373 -0
- scitex/scholar/auth/sso/OpenAthensSSOAutomator.py +378 -0
- scitex/scholar/auth/sso/SSOAutomator.py +180 -0
- scitex/scholar/auth/sso/UniversityOfMelbourneSSOAutomator.py +380 -0
- scitex/scholar/auth/sso/__init__.py +15 -0
- scitex/scholar/browser/ScholarBrowserManager.py +705 -0
- scitex/scholar/browser/__init__.py +38 -0
- scitex/scholar/browser/utils/__init__.py +13 -0
- scitex/scholar/browser/utils/click_and_wait.py +205 -0
- scitex/scholar/browser/utils/close_unwanted_pages.py +140 -0
- scitex/scholar/browser/utils/wait_redirects.py +732 -0
- scitex/scholar/config/PublisherRules.py +132 -0
- scitex/scholar/config/ScholarConfig.py +126 -0
- scitex/scholar/config/__init__.py +17 -0
- scitex/scholar/core/Paper.py +627 -0
- scitex/scholar/core/Papers.py +722 -0
- scitex/scholar/core/Scholar.py +1975 -0
- scitex/scholar/core/__init__.py +9 -0
- scitex/scholar/impact_factor/ImpactFactorEngine.py +204 -0
- scitex/scholar/impact_factor/__init__.py +20 -0
- scitex/scholar/impact_factor/estimation/ImpactFactorEstimationEngine.py +0 -0
- scitex/scholar/impact_factor/estimation/__init__.py +40 -0
- scitex/scholar/impact_factor/estimation/build_database.py +0 -0
- scitex/scholar/impact_factor/estimation/core/__init__.py +28 -0
- scitex/scholar/impact_factor/estimation/core/cache_manager.py +523 -0
- scitex/scholar/impact_factor/estimation/core/calculator.py +355 -0
- scitex/scholar/impact_factor/estimation/core/journal_matcher.py +428 -0
- scitex/scholar/integration/__init__.py +59 -0
- scitex/scholar/integration/base.py +502 -0
- scitex/scholar/integration/mendeley/__init__.py +22 -0
- scitex/scholar/integration/mendeley/exporter.py +166 -0
- scitex/scholar/integration/mendeley/importer.py +236 -0
- scitex/scholar/integration/mendeley/linker.py +79 -0
- scitex/scholar/integration/mendeley/mapper.py +212 -0
- scitex/scholar/integration/zotero/__init__.py +27 -0
- scitex/scholar/integration/zotero/__main__.py +264 -0
- scitex/scholar/integration/zotero/exporter.py +351 -0
- scitex/scholar/integration/zotero/importer.py +372 -0
- scitex/scholar/integration/zotero/linker.py +415 -0
- scitex/scholar/integration/zotero/mapper.py +286 -0
- scitex/scholar/metadata_engines/ScholarEngine.py +588 -0
- scitex/scholar/metadata_engines/__init__.py +21 -0
- scitex/scholar/metadata_engines/individual/ArXivEngine.py +397 -0
- scitex/scholar/metadata_engines/individual/CrossRefEngine.py +274 -0
- scitex/scholar/metadata_engines/individual/CrossRefLocalEngine.py +263 -0
- scitex/scholar/metadata_engines/individual/OpenAlexEngine.py +350 -0
- scitex/scholar/metadata_engines/individual/PubMedEngine.py +329 -0
- scitex/scholar/metadata_engines/individual/SemanticScholarEngine.py +438 -0
- scitex/scholar/metadata_engines/individual/URLDOIEngine.py +410 -0
- scitex/scholar/metadata_engines/individual/_BaseDOIEngine.py +487 -0
- scitex/scholar/metadata_engines/individual/__init__.py +7 -0
- scitex/scholar/metadata_engines/utils/_PubMedConverter.py +469 -0
- scitex/scholar/metadata_engines/utils/_URLDOIExtractor.py +283 -0
- scitex/scholar/metadata_engines/utils/__init__.py +30 -0
- scitex/scholar/metadata_engines/utils/_metadata2bibtex.py +103 -0
- scitex/scholar/metadata_engines/utils/_standardize_metadata.py +376 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +579 -0
- scitex/scholar/pdf_download/__init__.py +5 -0
- scitex/scholar/pdf_download/strategies/__init__.py +38 -0
- scitex/scholar/pdf_download/strategies/chrome_pdf_viewer.py +376 -0
- scitex/scholar/pdf_download/strategies/direct_download.py +131 -0
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +167 -0
- scitex/scholar/pdf_download/strategies/manual_download_utils.py +996 -0
- scitex/scholar/pdf_download/strategies/response_body.py +207 -0
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +364 -0
- scitex/scholar/pipelines/ScholarPipelineParallel.py +478 -0
- scitex/scholar/pipelines/ScholarPipelineSingle.py +767 -0
- scitex/scholar/pipelines/__init__.py +49 -0
- scitex/scholar/storage/BibTeXHandler.py +1018 -0
- scitex/scholar/storage/PaperIO.py +468 -0
- scitex/scholar/storage/ScholarLibrary.py +182 -0
- scitex/scholar/storage/_DeduplicationManager.py +548 -0
- scitex/scholar/storage/_LibraryCacheManager.py +724 -0
- scitex/scholar/storage/_LibraryManager.py +1835 -0
- scitex/scholar/storage/__init__.py +28 -0
- scitex/scholar/url_finder/ScholarURLFinder.py +379 -0
- scitex/scholar/url_finder/__init__.py +7 -0
- scitex/scholar/url_finder/strategies/__init__.py +33 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_direct_links.py +261 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_dropdown.py +67 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_href.py +204 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_navigation.py +256 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_publisher_patterns.py +165 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_zotero_translators.py +163 -0
- scitex/scholar/url_finder/strategies/find_supplementary_urls_by_href.py +70 -0
- scitex/scholar/utils/__init__.py +22 -0
- scitex/scholar/utils/bibtex/__init__.py +9 -0
- scitex/scholar/utils/bibtex/_parse_bibtex.py +71 -0
- scitex/scholar/utils/cleanup/__init__.py +8 -0
- scitex/scholar/utils/cleanup/_cleanup_scholar_processes.py +96 -0
- scitex/scholar/utils/cleanup/cleanup_old_extractions.py +117 -0
- scitex/scholar/utils/text/_TextNormalizer.py +407 -0
- scitex/scholar/utils/text/__init__.py +9 -0
- scitex/scholar/zotero/__init__.py +38 -0
- scitex/session/__init__.py +51 -0
- scitex/session/_lifecycle.py +736 -0
- scitex/session/_manager.py +102 -0
- scitex/session/template.py +122 -0
- scitex/stats/__init__.py +30 -26
- scitex/stats/correct/__init__.py +21 -0
- scitex/stats/correct/_correct_bonferroni.py +551 -0
- scitex/stats/correct/_correct_fdr.py +634 -0
- scitex/stats/correct/_correct_holm.py +548 -0
- scitex/stats/correct/_correct_sidak.py +499 -0
- scitex/stats/descriptive/__init__.py +85 -0
- scitex/stats/descriptive/_circular.py +540 -0
- scitex/stats/descriptive/_describe.py +219 -0
- scitex/stats/descriptive/_nan.py +518 -0
- scitex/stats/descriptive/_real.py +189 -0
- scitex/stats/effect_sizes/__init__.py +41 -0
- scitex/stats/effect_sizes/_cliffs_delta.py +325 -0
- scitex/stats/effect_sizes/_cohens_d.py +342 -0
- scitex/stats/effect_sizes/_epsilon_squared.py +315 -0
- scitex/stats/effect_sizes/_eta_squared.py +302 -0
- scitex/stats/effect_sizes/_prob_superiority.py +296 -0
- scitex/stats/posthoc/__init__.py +19 -0
- scitex/stats/posthoc/_dunnett.py +463 -0
- scitex/stats/posthoc/_games_howell.py +383 -0
- scitex/stats/posthoc/_tukey_hsd.py +367 -0
- scitex/stats/power/__init__.py +19 -0
- scitex/stats/power/_power.py +433 -0
- scitex/stats/template.py +119 -0
- scitex/stats/utils/__init__.py +62 -0
- scitex/stats/utils/_effect_size.py +985 -0
- scitex/stats/utils/_formatters.py +270 -0
- scitex/stats/utils/_normalizers.py +927 -0
- scitex/stats/utils/_power.py +433 -0
- scitex/stats_v01/_EffectSizeCalculator.py +488 -0
- scitex/stats_v01/_StatisticalValidator.py +411 -0
- scitex/stats_v01/__init__.py +60 -0
- scitex/stats_v01/_additional_tests.py +415 -0
- scitex/{stats → stats_v01}/_p2stars.py +19 -5
- scitex/stats_v01/_two_sample_tests.py +141 -0
- scitex/stats_v01/desc/__init__.py +83 -0
- scitex/stats_v01/desc/_circular.py +540 -0
- scitex/stats_v01/desc/_describe.py +219 -0
- scitex/stats_v01/desc/_nan.py +518 -0
- scitex/{stats/desc/_nan.py → stats_v01/desc/_nan_v01-20250920_145731.py} +23 -12
- scitex/stats_v01/desc/_real.py +189 -0
- scitex/stats_v01/tests/__corr_test_optimized.py +221 -0
- scitex/stats_v01/tests/_corr_test_optimized.py +179 -0
- scitex/str/__init__.py +1 -3
- scitex/str/_clean_path.py +6 -2
- scitex/str/_latex_fallback.py +267 -160
- scitex/str/_parse.py +44 -36
- scitex/str/_printc.py +1 -3
- scitex/template/__init__.py +87 -0
- scitex/template/_create_project.py +267 -0
- scitex/template/create_pip_project.py +80 -0
- scitex/template/create_research.py +80 -0
- scitex/template/create_singularity.py +80 -0
- scitex/units.py +291 -0
- scitex/utils/_compress_hdf5.py +14 -3
- scitex/utils/_email.py +21 -2
- scitex/utils/_grid.py +6 -4
- scitex/utils/_notify.py +13 -10
- scitex/utils/_verify_scitex_format.py +589 -0
- scitex/utils/_verify_scitex_format_v01.py +370 -0
- scitex/utils/template.py +122 -0
- scitex/web/_search_pubmed.py +62 -16
- scitex-2.1.0.dist-info/LICENSE +21 -0
- scitex-2.1.0.dist-info/METADATA +677 -0
- scitex-2.1.0.dist-info/RECORD +919 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/WHEEL +1 -1
- scitex-2.1.0.dist-info/entry_points.txt +3 -0
- scitex/ai/__Classifiers.py +0 -101
- scitex/ai/classification/classification_reporter.py +0 -1137
- scitex/ai/classification/classifiers.py +0 -101
- scitex/ai/classification_reporter.py +0 -1161
- scitex/ai/genai/__init__.py +0 -277
- scitex/ai/genai/anthropic_provider.py +0 -320
- scitex/ai/genai/anthropic_refactored.py +0 -109
- scitex/ai/genai/auth_manager.py +0 -200
- scitex/ai/genai/base_provider.py +0 -291
- scitex/ai/genai/chat_history.py +0 -307
- scitex/ai/genai/cost_tracker.py +0 -276
- scitex/ai/genai/deepseek_provider.py +0 -251
- scitex/ai/genai/google_provider.py +0 -228
- scitex/ai/genai/groq_provider.py +0 -248
- scitex/ai/genai/image_processor.py +0 -250
- scitex/ai/genai/llama_provider.py +0 -214
- scitex/ai/genai/mock_provider.py +0 -127
- scitex/ai/genai/model_registry.py +0 -304
- scitex/ai/genai/openai_provider.py +0 -293
- scitex/ai/genai/perplexity_provider.py +0 -205
- scitex/ai/genai/provider_base.py +0 -302
- scitex/ai/genai/provider_factory.py +0 -370
- scitex/ai/genai/response_handler.py +0 -235
- scitex/ai/layer/_Pass.py +0 -21
- scitex/ai/layer/__init__.py +0 -10
- scitex/ai/layer/_switch.py +0 -8
- scitex/ai/metrics/_bACC.py +0 -51
- scitex/ai/plt/_learning_curve.py +0 -194
- scitex/ai/plt/_optuna_study.py +0 -111
- scitex/ai/plt/aucs/__init__.py +0 -2
- scitex/ai/plt/aucs/example.py +0 -60
- scitex/ai/plt/aucs/pre_rec_auc.py +0 -223
- scitex/ai/plt/aucs/roc_auc.py +0 -246
- scitex/ai/sampling/undersample.py +0 -29
- scitex/db/_SQLite3.py +0 -2136
- scitex/db/_SQLite3Mixins/_BlobMixin.py +0 -229
- scitex/gen/_close.py +0 -222
- scitex/gen/_start.py +0 -451
- scitex/general/__init__.py +0 -5
- scitex/io/_load_modules/_db.py +0 -24
- scitex/life/__init__.py +0 -10
- scitex/life/_monitor_rain.py +0 -49
- scitex/reproduce/_fix_seeds.py +0 -45
- scitex/res/__init__.py +0 -5
- scitex/scholar/_local_search.py +0 -454
- scitex/scholar/_paper.py +0 -244
- scitex/scholar/_pdf_downloader.py +0 -325
- scitex/scholar/_search.py +0 -393
- scitex/scholar/_vector_search.py +0 -370
- scitex/scholar/_web_sources.py +0 -457
- scitex/stats/desc/__init__.py +0 -40
- scitex-2.0.0.dist-info/METADATA +0 -307
- scitex-2.0.0.dist-info/RECORD +0 -572
- scitex-2.0.0.dist-info/licenses/LICENSE +0 -7
- /scitex/ai/{act → activation}/__init__.py +0 -0
- /scitex/ai/{act → activation}/_define.py +0 -0
- /scitex/ai/{early_stopping.py → training/_EarlyStopping.py} +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ImportExportMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_IndexMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_RowMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TableMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/__init__.py +0 -0
- /scitex/{stats → stats_v01}/_calc_partial_corr.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_describe_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_multiple_corrections.py +0 -0
- /scitex/{stats → stats_v01}/_nan_stats.py +0 -0
- /scitex/{stats → stats_v01}/_p2stars_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_statistical_tests.py +0 -0
- /scitex/{stats/desc/_describe.py → stats_v01/desc/_describe_v01-20250920_145731.py} +0 -0
- /scitex/{stats/desc/_real.py → stats_v01/desc/_real_v01-20250920_145731.py} +0 -0
- /scitex/{stats → stats_v01}/multiple/__init__.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_bonferroni_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_fdr_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_multicompair.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_single.py +0 -0
- /scitex/{stats → stats_v01}/tests/__init__.py +0 -0
- /scitex/{stats → stats_v01}/tests/_brunner_munzel_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_nocorrelation_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_smirnov_grubbs.py +0 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,985 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-10-01 14:50:00 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/stats/utils/_effect_size.py
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Functionalities:
|
|
8
|
+
- Compute Cohen's d effect size for t-tests
|
|
9
|
+
- Support both independent and paired samples
|
|
10
|
+
- Handle various pooling methods
|
|
11
|
+
- Provide interpretation guidelines
|
|
12
|
+
|
|
13
|
+
Dependencies:
|
|
14
|
+
- packages: numpy, pandas, scipy
|
|
15
|
+
|
|
16
|
+
IO:
|
|
17
|
+
- input: Two samples (arrays or Series)
|
|
18
|
+
- output: Effect size value (float)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
"""Imports"""
|
|
22
|
+
import sys
|
|
23
|
+
import argparse
|
|
24
|
+
import numpy as np
|
|
25
|
+
import pandas as pd
|
|
26
|
+
from typing import Union, Optional, Literal, List
|
|
27
|
+
import scitex as stx
|
|
28
|
+
from scitex.logging import getLogger
|
|
29
|
+
|
|
30
|
+
logger = getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
"""Functions"""
|
|
33
|
+
def cohens_d(
|
|
34
|
+
x: Union[np.ndarray, pd.Series],
|
|
35
|
+
y: Optional[Union[np.ndarray, pd.Series]] = None,
|
|
36
|
+
paired: bool = False,
|
|
37
|
+
correction: Literal['hedges', 'glass', None] = None
|
|
38
|
+
) -> float:
|
|
39
|
+
"""
|
|
40
|
+
Compute Cohen's d effect size.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
x : array or Series
|
|
45
|
+
First sample
|
|
46
|
+
y : array or Series, optional
|
|
47
|
+
Second sample. If None, computes one-sample effect size against zero.
|
|
48
|
+
paired : bool, default False
|
|
49
|
+
Whether samples are paired
|
|
50
|
+
correction : {'hedges', 'glass', None}, default None
|
|
51
|
+
Correction method:
|
|
52
|
+
- None: Standard Cohen's d
|
|
53
|
+
- 'hedges': Hedges' g (corrected for small samples)
|
|
54
|
+
- 'glass': Glass's delta (uses only control group SD)
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
float
|
|
59
|
+
Effect size value
|
|
60
|
+
|
|
61
|
+
Notes
|
|
62
|
+
-----
|
|
63
|
+
Cohen's d is calculated as:
|
|
64
|
+
|
|
65
|
+
.. math::
|
|
66
|
+
d = \\frac{\\bar{x}_1 - \\bar{x}_2}{s_{pooled}}
|
|
67
|
+
|
|
68
|
+
where :math:`s_{pooled}` is the pooled standard deviation:
|
|
69
|
+
|
|
70
|
+
.. math::
|
|
71
|
+
s_{pooled} = \\sqrt{\\frac{(n_1-1)s_1^2 + (n_2-1)s_2^2}{n_1 + n_2 - 2}}
|
|
72
|
+
|
|
73
|
+
Interpretation guidelines (Cohen, 1988):
|
|
74
|
+
- Small effect: d = 0.2
|
|
75
|
+
- Medium effect: d = 0.5
|
|
76
|
+
- Large effect: d = 0.8
|
|
77
|
+
|
|
78
|
+
For paired samples, d is computed as:
|
|
79
|
+
|
|
80
|
+
.. math::
|
|
81
|
+
d = \\frac{\\bar{d}}{s_d}
|
|
82
|
+
|
|
83
|
+
where :math:`\\bar{d}` is the mean difference and :math:`s_d` is the
|
|
84
|
+
standard deviation of differences.
|
|
85
|
+
|
|
86
|
+
References
|
|
87
|
+
----------
|
|
88
|
+
.. [1] Cohen, J. (1988). Statistical Power Analysis for the Behavioral
|
|
89
|
+
Sciences (2nd ed.). Routledge.
|
|
90
|
+
|
|
91
|
+
Examples
|
|
92
|
+
--------
|
|
93
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
94
|
+
>>> y = np.array([2, 3, 4, 5, 6])
|
|
95
|
+
>>> cohens_d(x, y)
|
|
96
|
+
-1.0
|
|
97
|
+
|
|
98
|
+
>>> # Paired samples
|
|
99
|
+
>>> cohens_d(x, y, paired=True)
|
|
100
|
+
-1.58...
|
|
101
|
+
|
|
102
|
+
>>> # With Hedges' correction
|
|
103
|
+
>>> cohens_d(x, y, correction='hedges')
|
|
104
|
+
-0.95...
|
|
105
|
+
"""
|
|
106
|
+
# Convert to numpy arrays
|
|
107
|
+
x = np.asarray(x)
|
|
108
|
+
if y is not None:
|
|
109
|
+
y = np.asarray(y)
|
|
110
|
+
|
|
111
|
+
# Remove NaN values
|
|
112
|
+
x = x[~np.isnan(x)]
|
|
113
|
+
if y is not None:
|
|
114
|
+
y = y[~np.isnan(y)]
|
|
115
|
+
|
|
116
|
+
# Compute effect size
|
|
117
|
+
if y is None:
|
|
118
|
+
# One-sample: compare to zero
|
|
119
|
+
d = np.mean(x) / np.std(x, ddof=1)
|
|
120
|
+
elif paired:
|
|
121
|
+
# Paired samples
|
|
122
|
+
if len(x) != len(y):
|
|
123
|
+
raise ValueError("Paired samples must have same length")
|
|
124
|
+
diff = x - y
|
|
125
|
+
d = np.mean(diff) / np.std(diff, ddof=1)
|
|
126
|
+
else:
|
|
127
|
+
# Independent samples
|
|
128
|
+
n1, n2 = len(x), len(y)
|
|
129
|
+
mean_diff = np.mean(x) - np.mean(y)
|
|
130
|
+
|
|
131
|
+
if correction == 'glass':
|
|
132
|
+
# Glass's delta: use only control group (y) SD
|
|
133
|
+
d = mean_diff / np.std(y, ddof=1)
|
|
134
|
+
else:
|
|
135
|
+
# Pooled standard deviation
|
|
136
|
+
var1 = np.var(x, ddof=1)
|
|
137
|
+
var2 = np.var(y, ddof=1)
|
|
138
|
+
pooled_std = np.sqrt(((n1 - 1) * var1 + (n2 - 1) * var2) / (n1 + n2 - 2))
|
|
139
|
+
d = mean_diff / pooled_std
|
|
140
|
+
|
|
141
|
+
# Apply Hedges' correction for small samples
|
|
142
|
+
if correction == 'hedges':
|
|
143
|
+
# Hedges' g correction factor
|
|
144
|
+
correction_factor = 1 - (3 / (4 * (n1 + n2) - 9))
|
|
145
|
+
d = d * correction_factor
|
|
146
|
+
|
|
147
|
+
return float(d)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def cliffs_delta(
|
|
151
|
+
x: Union[np.ndarray, pd.Series],
|
|
152
|
+
y: Union[np.ndarray, pd.Series]
|
|
153
|
+
) -> float:
|
|
154
|
+
"""
|
|
155
|
+
Compute Cliff's delta non-parametric effect size.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
x : array or Series
|
|
160
|
+
First sample
|
|
161
|
+
y : array or Series
|
|
162
|
+
Second sample
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
float
|
|
167
|
+
Cliff's delta value (ranges from -1 to 1)
|
|
168
|
+
|
|
169
|
+
Notes
|
|
170
|
+
-----
|
|
171
|
+
Cliff's delta is a non-parametric effect size measure that quantifies
|
|
172
|
+
the degree of dominance of one distribution over another.
|
|
173
|
+
|
|
174
|
+
It is calculated as:
|
|
175
|
+
|
|
176
|
+
.. math::
|
|
177
|
+
\\delta = \\frac{\\#(x_i > y_j) - \\#(x_i < y_j)}{n_x \\cdot n_y}
|
|
178
|
+
|
|
179
|
+
Where:
|
|
180
|
+
- #(x_i > y_j) is the number of times values in x are greater than values in y
|
|
181
|
+
- #(x_i < y_j) is the number of times values in x are less than values in y
|
|
182
|
+
|
|
183
|
+
Interpretation:
|
|
184
|
+
- |δ| < 0.147: negligible
|
|
185
|
+
- |δ| < 0.33: small
|
|
186
|
+
- |δ| < 0.474: medium
|
|
187
|
+
- |δ| ≥ 0.474: large
|
|
188
|
+
|
|
189
|
+
Advantages:
|
|
190
|
+
- Non-parametric (no assumptions about distributions)
|
|
191
|
+
- Robust to outliers
|
|
192
|
+
- Easy to interpret (probability-based)
|
|
193
|
+
- Related to Mann-Whitney U statistic
|
|
194
|
+
|
|
195
|
+
The relation to Mann-Whitney U is:
|
|
196
|
+
|
|
197
|
+
.. math::
|
|
198
|
+
\\delta = 2 \\cdot \\frac{U}{n_x \\cdot n_y} - 1
|
|
199
|
+
|
|
200
|
+
References
|
|
201
|
+
----------
|
|
202
|
+
.. [1] Cliff, N. (1993). "Dominance statistics: Ordinal analyses to answer
|
|
203
|
+
ordinal questions". Psychological Bulletin, 114(3), 494-509.
|
|
204
|
+
.. [2] Romano, J., Kromrey, J. D., Coraggio, J., & Skowronek, J. (2006).
|
|
205
|
+
"Appropriate statistics for ordinal level data: Should we really be
|
|
206
|
+
using t-test and Cohen's d for evaluating group differences on the
|
|
207
|
+
NSSE and other surveys?" Florida Association of Institutional Research.
|
|
208
|
+
|
|
209
|
+
Examples
|
|
210
|
+
--------
|
|
211
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
212
|
+
>>> y = np.array([2, 3, 4, 5, 6])
|
|
213
|
+
>>> cliffs_delta(x, y)
|
|
214
|
+
-0.6
|
|
215
|
+
|
|
216
|
+
>>> # No difference
|
|
217
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
218
|
+
>>> y = np.array([1, 2, 3, 4, 5])
|
|
219
|
+
>>> cliffs_delta(x, y)
|
|
220
|
+
0.0
|
|
221
|
+
|
|
222
|
+
>>> # Complete dominance
|
|
223
|
+
>>> x = np.array([6, 7, 8, 9, 10])
|
|
224
|
+
>>> y = np.array([1, 2, 3, 4, 5])
|
|
225
|
+
>>> cliffs_delta(x, y)
|
|
226
|
+
1.0
|
|
227
|
+
"""
|
|
228
|
+
# Convert to numpy arrays
|
|
229
|
+
x = np.asarray(x)
|
|
230
|
+
y = np.asarray(y)
|
|
231
|
+
|
|
232
|
+
# Remove NaN values
|
|
233
|
+
x = x[~np.isnan(x)]
|
|
234
|
+
y = y[~np.isnan(y)]
|
|
235
|
+
|
|
236
|
+
nx = len(x)
|
|
237
|
+
ny = len(y)
|
|
238
|
+
|
|
239
|
+
# Count comparisons
|
|
240
|
+
# Vectorized computation: create all pairwise comparisons
|
|
241
|
+
# x[:, None] creates column vector, y creates row vector
|
|
242
|
+
# Broadcasting creates matrix of all pairwise comparisons
|
|
243
|
+
more = np.sum(x[:, None] > y)
|
|
244
|
+
less = np.sum(x[:, None] < y)
|
|
245
|
+
|
|
246
|
+
# Compute Cliff's delta
|
|
247
|
+
delta = (more - less) / (nx * ny)
|
|
248
|
+
|
|
249
|
+
return float(delta)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def prob_superiority(
|
|
253
|
+
x: Union[np.ndarray, pd.Series],
|
|
254
|
+
y: Union[np.ndarray, pd.Series]
|
|
255
|
+
) -> float:
|
|
256
|
+
"""
|
|
257
|
+
Compute probability of superiority P(X > Y).
|
|
258
|
+
|
|
259
|
+
Also known as the common language effect size or probabilistic index.
|
|
260
|
+
|
|
261
|
+
Parameters
|
|
262
|
+
----------
|
|
263
|
+
x : array or Series
|
|
264
|
+
First sample
|
|
265
|
+
y : array or Series
|
|
266
|
+
Second sample
|
|
267
|
+
|
|
268
|
+
Returns
|
|
269
|
+
-------
|
|
270
|
+
float
|
|
271
|
+
Probability that a random value from X is greater than a random value from Y
|
|
272
|
+
(ranges from 0 to 1)
|
|
273
|
+
|
|
274
|
+
Notes
|
|
275
|
+
-----
|
|
276
|
+
The probability of superiority is defined as:
|
|
277
|
+
|
|
278
|
+
.. math::
|
|
279
|
+
P(X > Y) = \\frac{\\#(x_i > y_j)}{n_x \\cdot n_y}
|
|
280
|
+
|
|
281
|
+
This is the probabilistic interpretation of effect size and is directly
|
|
282
|
+
related to the Brunner-Munzel statistic and Cliff's delta:
|
|
283
|
+
|
|
284
|
+
.. math::
|
|
285
|
+
P(X > Y) = \\frac{1 + \\delta}{2}
|
|
286
|
+
|
|
287
|
+
Where δ is Cliff's delta.
|
|
288
|
+
|
|
289
|
+
Interpretation:
|
|
290
|
+
- P(X > Y) = 0.50: No effect (chance level)
|
|
291
|
+
- P(X > Y) = 0.56: Small effect (McGraw & Wong, 1992)
|
|
292
|
+
- P(X > Y) = 0.64: Medium effect
|
|
293
|
+
- P(X > Y) = 0.71: Large effect
|
|
294
|
+
|
|
295
|
+
Advantages:
|
|
296
|
+
- Intuitive probabilistic interpretation
|
|
297
|
+
- Non-parametric (distribution-free)
|
|
298
|
+
- Directly comparable across studies
|
|
299
|
+
- Used in Brunner-Munzel test
|
|
300
|
+
|
|
301
|
+
This is also called:
|
|
302
|
+
- Common Language Effect Size (CLES)
|
|
303
|
+
- Area Under the Curve (AUC) in ROC analysis
|
|
304
|
+
- Mann-Whitney U / (nx * ny)
|
|
305
|
+
|
|
306
|
+
References
|
|
307
|
+
----------
|
|
308
|
+
.. [1] McGraw, K. O., & Wong, S. P. (1992). "A common language effect size
|
|
309
|
+
statistic". Psychological Bulletin, 111(2), 361-365.
|
|
310
|
+
.. [2] Brunner, E., & Munzel, U. (2000). "The nonparametric Behrens-Fisher
|
|
311
|
+
problem: Asymptotic theory and a small-sample approximation".
|
|
312
|
+
Biometrical Journal, 42(1), 17-25.
|
|
313
|
+
|
|
314
|
+
Examples
|
|
315
|
+
--------
|
|
316
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
317
|
+
>>> y = np.array([2, 3, 4, 5, 6])
|
|
318
|
+
>>> prob_superiority(x, y)
|
|
319
|
+
0.2
|
|
320
|
+
|
|
321
|
+
>>> # 20% chance a random X value exceeds a random Y value
|
|
322
|
+
|
|
323
|
+
>>> # No difference (chance level)
|
|
324
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
325
|
+
>>> y = np.array([1, 2, 3, 4, 5])
|
|
326
|
+
>>> prob_superiority(x, y)
|
|
327
|
+
0.5
|
|
328
|
+
|
|
329
|
+
>>> # Complete dominance
|
|
330
|
+
>>> x = np.array([6, 7, 8, 9, 10])
|
|
331
|
+
>>> y = np.array([1, 2, 3, 4, 5])
|
|
332
|
+
>>> prob_superiority(x, y)
|
|
333
|
+
1.0
|
|
334
|
+
"""
|
|
335
|
+
# Convert to numpy arrays
|
|
336
|
+
x = np.asarray(x)
|
|
337
|
+
y = np.asarray(y)
|
|
338
|
+
|
|
339
|
+
# Remove NaN values
|
|
340
|
+
x = x[~np.isnan(x)]
|
|
341
|
+
y = y[~np.isnan(y)]
|
|
342
|
+
|
|
343
|
+
nx = len(x)
|
|
344
|
+
ny = len(y)
|
|
345
|
+
|
|
346
|
+
# Count how many times x > y
|
|
347
|
+
more = np.sum(x[:, None] > y)
|
|
348
|
+
|
|
349
|
+
# Compute probability
|
|
350
|
+
prob = more / (nx * ny)
|
|
351
|
+
|
|
352
|
+
return float(prob)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def interpret_prob_superiority(prob: float) -> str:
|
|
356
|
+
"""
|
|
357
|
+
Interpret probability of superiority effect size.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
prob : float
|
|
362
|
+
Probability of superiority P(X > Y)
|
|
363
|
+
|
|
364
|
+
Returns
|
|
365
|
+
-------
|
|
366
|
+
str
|
|
367
|
+
Interpretation string
|
|
368
|
+
|
|
369
|
+
Examples
|
|
370
|
+
--------
|
|
371
|
+
>>> interpret_prob_superiority(0.51)
|
|
372
|
+
'negligible'
|
|
373
|
+
>>> interpret_prob_superiority(0.60)
|
|
374
|
+
'small'
|
|
375
|
+
>>> interpret_prob_superiority(0.68)
|
|
376
|
+
'medium'
|
|
377
|
+
>>> interpret_prob_superiority(0.75)
|
|
378
|
+
'large'
|
|
379
|
+
"""
|
|
380
|
+
# Convert to distance from 0.5 (chance)
|
|
381
|
+
distance = abs(prob - 0.5)
|
|
382
|
+
|
|
383
|
+
if distance < 0.06:
|
|
384
|
+
return 'negligible'
|
|
385
|
+
elif distance < 0.14:
|
|
386
|
+
return 'small'
|
|
387
|
+
elif distance < 0.21:
|
|
388
|
+
return 'medium'
|
|
389
|
+
else:
|
|
390
|
+
return 'large'
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def interpret_cliffs_delta(delta: float) -> str:
|
|
394
|
+
"""
|
|
395
|
+
Interpret Cliff's delta effect size.
|
|
396
|
+
|
|
397
|
+
Parameters
|
|
398
|
+
----------
|
|
399
|
+
delta : float
|
|
400
|
+
Cliff's delta value
|
|
401
|
+
|
|
402
|
+
Returns
|
|
403
|
+
-------
|
|
404
|
+
str
|
|
405
|
+
Interpretation string
|
|
406
|
+
|
|
407
|
+
Examples
|
|
408
|
+
--------
|
|
409
|
+
>>> interpret_cliffs_delta(0.1)
|
|
410
|
+
'negligible'
|
|
411
|
+
>>> interpret_cliffs_delta(0.25)
|
|
412
|
+
'small'
|
|
413
|
+
>>> interpret_cliffs_delta(0.4)
|
|
414
|
+
'medium'
|
|
415
|
+
>>> interpret_cliffs_delta(0.6)
|
|
416
|
+
'large'
|
|
417
|
+
"""
|
|
418
|
+
delta_abs = abs(delta)
|
|
419
|
+
|
|
420
|
+
if delta_abs < 0.147:
|
|
421
|
+
return 'negligible'
|
|
422
|
+
elif delta_abs < 0.33:
|
|
423
|
+
return 'small'
|
|
424
|
+
elif delta_abs < 0.474:
|
|
425
|
+
return 'medium'
|
|
426
|
+
else:
|
|
427
|
+
return 'large'
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def eta_squared(
|
|
431
|
+
groups: List[Union[np.ndarray, pd.Series]],
|
|
432
|
+
ddof: int = 1
|
|
433
|
+
) -> float:
|
|
434
|
+
"""
|
|
435
|
+
Compute eta-squared (η²) effect size for ANOVA.
|
|
436
|
+
|
|
437
|
+
Parameters
|
|
438
|
+
----------
|
|
439
|
+
groups : list of arrays or Series
|
|
440
|
+
List of samples, one per group
|
|
441
|
+
ddof : int, default 1
|
|
442
|
+
Degrees of freedom correction for variance
|
|
443
|
+
|
|
444
|
+
Returns
|
|
445
|
+
-------
|
|
446
|
+
float
|
|
447
|
+
Eta-squared value (ranges from 0 to 1)
|
|
448
|
+
|
|
449
|
+
Notes
|
|
450
|
+
-----
|
|
451
|
+
Eta-squared (η²) measures the proportion of total variance explained
|
|
452
|
+
by group membership in ANOVA designs.
|
|
453
|
+
|
|
454
|
+
.. math::
|
|
455
|
+
\\eta^2 = \\frac{SS_{between}}{SS_{total}}
|
|
456
|
+
|
|
457
|
+
Where:
|
|
458
|
+
- SS_between: Sum of squares between groups
|
|
459
|
+
- SS_total: Total sum of squares
|
|
460
|
+
|
|
461
|
+
Interpretation (Cohen, 1988):
|
|
462
|
+
- η² < 0.01: negligible
|
|
463
|
+
- η² < 0.06: small
|
|
464
|
+
- η² < 0.14: medium
|
|
465
|
+
- η² ≥ 0.14: large
|
|
466
|
+
|
|
467
|
+
**Variants:**
|
|
468
|
+
- η²: Biased, overestimates population effect
|
|
469
|
+
- ω² (omega-squared): Less biased estimate
|
|
470
|
+
- partial η²: Used in factorial designs
|
|
471
|
+
|
|
472
|
+
Relationship to F-statistic:
|
|
473
|
+
|
|
474
|
+
.. math::
|
|
475
|
+
\\eta^2 = \\frac{F \\cdot df_{between}}{F \\cdot df_{between} + df_{within}}
|
|
476
|
+
|
|
477
|
+
References
|
|
478
|
+
----------
|
|
479
|
+
.. [1] Cohen, J. (1988). Statistical Power Analysis for the Behavioral
|
|
480
|
+
Sciences (2nd ed.). Routledge.
|
|
481
|
+
.. [2] Richardson, J. T. E. (2011). "Eta squared and partial eta squared
|
|
482
|
+
as measures of effect size in educational research". Educational
|
|
483
|
+
Research Review, 6(2), 135-147.
|
|
484
|
+
|
|
485
|
+
Examples
|
|
486
|
+
--------
|
|
487
|
+
>>> group1 = np.array([1, 2, 3, 4, 5])
|
|
488
|
+
>>> group2 = np.array([3, 4, 5, 6, 7])
|
|
489
|
+
>>> group3 = np.array([5, 6, 7, 8, 9])
|
|
490
|
+
>>> eta_squared([group1, group2, group3])
|
|
491
|
+
0.857...
|
|
492
|
+
|
|
493
|
+
>>> # No effect
|
|
494
|
+
>>> group1 = np.array([1, 2, 3, 4, 5])
|
|
495
|
+
>>> group2 = np.array([1, 2, 3, 4, 5])
|
|
496
|
+
>>> eta_squared([group1, group2])
|
|
497
|
+
0.0
|
|
498
|
+
"""
|
|
499
|
+
# Convert all groups to numpy arrays and remove NaN
|
|
500
|
+
groups = [np.asarray(g) for g in groups]
|
|
501
|
+
groups = [g[~np.isnan(g)] for g in groups]
|
|
502
|
+
|
|
503
|
+
# Compute grand mean
|
|
504
|
+
all_data = np.concatenate(groups)
|
|
505
|
+
grand_mean = np.mean(all_data)
|
|
506
|
+
|
|
507
|
+
# Compute total sum of squares
|
|
508
|
+
ss_total = np.sum((all_data - grand_mean) ** 2)
|
|
509
|
+
|
|
510
|
+
# Compute between-group sum of squares
|
|
511
|
+
ss_between = 0
|
|
512
|
+
for group in groups:
|
|
513
|
+
group_mean = np.mean(group)
|
|
514
|
+
n_group = len(group)
|
|
515
|
+
ss_between += n_group * (group_mean - grand_mean) ** 2
|
|
516
|
+
|
|
517
|
+
# Compute eta-squared
|
|
518
|
+
if ss_total == 0:
|
|
519
|
+
return 0.0
|
|
520
|
+
|
|
521
|
+
eta2 = ss_between / ss_total
|
|
522
|
+
|
|
523
|
+
return float(eta2)
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def interpret_eta_squared(eta2: float) -> str:
|
|
527
|
+
"""
|
|
528
|
+
Interpret eta-squared effect size.
|
|
529
|
+
|
|
530
|
+
Parameters
|
|
531
|
+
----------
|
|
532
|
+
eta2 : float
|
|
533
|
+
Eta-squared value
|
|
534
|
+
|
|
535
|
+
Returns
|
|
536
|
+
-------
|
|
537
|
+
str
|
|
538
|
+
Interpretation string
|
|
539
|
+
|
|
540
|
+
Examples
|
|
541
|
+
--------
|
|
542
|
+
>>> interpret_eta_squared(0.005)
|
|
543
|
+
'negligible'
|
|
544
|
+
>>> interpret_eta_squared(0.03)
|
|
545
|
+
'small'
|
|
546
|
+
>>> interpret_eta_squared(0.10)
|
|
547
|
+
'medium'
|
|
548
|
+
>>> interpret_eta_squared(0.20)
|
|
549
|
+
'large'
|
|
550
|
+
"""
|
|
551
|
+
if eta2 < 0.01:
|
|
552
|
+
return 'negligible'
|
|
553
|
+
elif eta2 < 0.06:
|
|
554
|
+
return 'small'
|
|
555
|
+
elif eta2 < 0.14:
|
|
556
|
+
return 'medium'
|
|
557
|
+
else:
|
|
558
|
+
return 'large'
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def epsilon_squared(groups):
|
|
562
|
+
"""
|
|
563
|
+
Compute epsilon-squared (ε²) effect size for Kruskal-Wallis test.
|
|
564
|
+
|
|
565
|
+
Parameters
|
|
566
|
+
----------
|
|
567
|
+
groups : list of arrays
|
|
568
|
+
List of sample arrays for each group
|
|
569
|
+
|
|
570
|
+
Returns
|
|
571
|
+
-------
|
|
572
|
+
float
|
|
573
|
+
Epsilon-squared value (0 to 1)
|
|
574
|
+
|
|
575
|
+
Notes
|
|
576
|
+
-----
|
|
577
|
+
Epsilon-squared (ε²) is the non-parametric analog of eta-squared (η²)
|
|
578
|
+
for the Kruskal-Wallis test. It measures the proportion of variance in
|
|
579
|
+
ranks explained by group membership.
|
|
580
|
+
|
|
581
|
+
.. math::
|
|
582
|
+
\\epsilon^2 = \\frac{H}{(n^2 - 1) / (n + 1)}
|
|
583
|
+
|
|
584
|
+
Where:
|
|
585
|
+
- H: Kruskal-Wallis H statistic
|
|
586
|
+
- n: Total sample size
|
|
587
|
+
|
|
588
|
+
Alternative formula (based on ranks):
|
|
589
|
+
|
|
590
|
+
.. math::
|
|
591
|
+
\\epsilon^2 = \\frac{H - k + 1}{n - k}
|
|
592
|
+
|
|
593
|
+
Where:
|
|
594
|
+
- H: Kruskal-Wallis H statistic
|
|
595
|
+
- k: Number of groups
|
|
596
|
+
- n: Total sample size
|
|
597
|
+
|
|
598
|
+
Interpretation (similar to η²):
|
|
599
|
+
- ε² < 0.01: negligible
|
|
600
|
+
- ε² < 0.06: small
|
|
601
|
+
- ε² < 0.14: medium
|
|
602
|
+
- ε² ≥ 0.14: large
|
|
603
|
+
|
|
604
|
+
References
|
|
605
|
+
----------
|
|
606
|
+
.. [1] Tomczak, M., & Tomczak, E. (2014). "The need to report effect size
|
|
607
|
+
estimates revisited. An overview of some recommended measures of
|
|
608
|
+
effect size". Trends in Sport Sciences, 21(1), 19-25.
|
|
609
|
+
.. [2] Kerby, D. S. (2014). "The simple difference formula: An approach to
|
|
610
|
+
teaching nonparametric correlation". Comprehensive Psychology, 3, 11.
|
|
611
|
+
|
|
612
|
+
Examples
|
|
613
|
+
--------
|
|
614
|
+
>>> group1 = np.array([1, 2, 3, 4, 5])
|
|
615
|
+
>>> group2 = np.array([3, 4, 5, 6, 7])
|
|
616
|
+
>>> group3 = np.array([5, 6, 7, 8, 9])
|
|
617
|
+
>>> epsilon_squared([group1, group2, group3])
|
|
618
|
+
0.857...
|
|
619
|
+
|
|
620
|
+
>>> # No effect
|
|
621
|
+
>>> group1 = np.array([1, 2, 3, 4, 5])
|
|
622
|
+
>>> group2 = np.array([1, 2, 3, 4, 5])
|
|
623
|
+
>>> epsilon_squared([group1, group2])
|
|
624
|
+
0.0
|
|
625
|
+
"""
|
|
626
|
+
from scipy import stats
|
|
627
|
+
|
|
628
|
+
# Convert all groups to numpy arrays and remove NaN
|
|
629
|
+
groups = [np.asarray(g) for g in groups]
|
|
630
|
+
groups = [g[~np.isnan(g)] for g in groups]
|
|
631
|
+
|
|
632
|
+
# Get group sizes
|
|
633
|
+
k = len(groups)
|
|
634
|
+
n = sum(len(g) for g in groups)
|
|
635
|
+
|
|
636
|
+
# Perform Kruskal-Wallis test to get H statistic
|
|
637
|
+
h_stat, _ = stats.kruskal(*groups)
|
|
638
|
+
|
|
639
|
+
# Compute epsilon-squared using H statistic
|
|
640
|
+
# Formula: ε² = (H - k + 1) / (n - k)
|
|
641
|
+
if n == k:
|
|
642
|
+
return 0.0
|
|
643
|
+
|
|
644
|
+
epsilon2 = (h_stat - k + 1) / (n - k)
|
|
645
|
+
|
|
646
|
+
# Ensure value is in valid range [0, 1]
|
|
647
|
+
epsilon2 = max(0.0, min(1.0, epsilon2))
|
|
648
|
+
|
|
649
|
+
return float(epsilon2)
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def interpret_epsilon_squared(epsilon2: float) -> str:
|
|
653
|
+
"""
|
|
654
|
+
Interpret epsilon-squared effect size.
|
|
655
|
+
|
|
656
|
+
Parameters
|
|
657
|
+
----------
|
|
658
|
+
epsilon2 : float
|
|
659
|
+
Epsilon-squared value
|
|
660
|
+
|
|
661
|
+
Returns
|
|
662
|
+
-------
|
|
663
|
+
str
|
|
664
|
+
Interpretation string
|
|
665
|
+
|
|
666
|
+
Examples
|
|
667
|
+
--------
|
|
668
|
+
>>> interpret_epsilon_squared(0.005)
|
|
669
|
+
'negligible'
|
|
670
|
+
>>> interpret_epsilon_squared(0.03)
|
|
671
|
+
'small'
|
|
672
|
+
>>> interpret_epsilon_squared(0.10)
|
|
673
|
+
'medium'
|
|
674
|
+
>>> interpret_epsilon_squared(0.20)
|
|
675
|
+
'large'
|
|
676
|
+
"""
|
|
677
|
+
if epsilon2 < 0.01:
|
|
678
|
+
return 'negligible'
|
|
679
|
+
elif epsilon2 < 0.06:
|
|
680
|
+
return 'small'
|
|
681
|
+
elif epsilon2 < 0.14:
|
|
682
|
+
return 'medium'
|
|
683
|
+
else:
|
|
684
|
+
return 'large'
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def interpret_cohens_d(d: float) -> str:
|
|
688
|
+
"""
|
|
689
|
+
Interpret Cohen's d effect size.
|
|
690
|
+
|
|
691
|
+
Parameters
|
|
692
|
+
----------
|
|
693
|
+
d : float
|
|
694
|
+
Cohen's d value
|
|
695
|
+
|
|
696
|
+
Returns
|
|
697
|
+
-------
|
|
698
|
+
str
|
|
699
|
+
Interpretation string
|
|
700
|
+
|
|
701
|
+
Examples
|
|
702
|
+
--------
|
|
703
|
+
>>> interpret_cohens_d(0.3)
|
|
704
|
+
'small'
|
|
705
|
+
>>> interpret_cohens_d(0.6)
|
|
706
|
+
'medium'
|
|
707
|
+
>>> interpret_cohens_d(0.9)
|
|
708
|
+
'large'
|
|
709
|
+
"""
|
|
710
|
+
d_abs = abs(d)
|
|
711
|
+
|
|
712
|
+
if d_abs < 0.2:
|
|
713
|
+
return 'negligible'
|
|
714
|
+
elif d_abs < 0.5:
|
|
715
|
+
return 'small'
|
|
716
|
+
elif d_abs < 0.8:
|
|
717
|
+
return 'medium'
|
|
718
|
+
else:
|
|
719
|
+
return 'large'
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
"""Main function"""
|
|
723
|
+
def main(args):
|
|
724
|
+
"""Demonstrate effect size computation (Cohen's d, Cliff's delta, eta-squared)."""
|
|
725
|
+
logger.info("Demonstrating effect size calculations")
|
|
726
|
+
|
|
727
|
+
# Set random seed for reproducibility
|
|
728
|
+
np.random.seed(42)
|
|
729
|
+
|
|
730
|
+
# Example 1: Different effect sizes
|
|
731
|
+
logger.info("\n=== Example 1: Different effect sizes ===")
|
|
732
|
+
|
|
733
|
+
n = 50
|
|
734
|
+
control = np.random.normal(0, 1, n)
|
|
735
|
+
|
|
736
|
+
effect_sizes = [0.0, 0.2, 0.5, 0.8, 1.2]
|
|
737
|
+
results = []
|
|
738
|
+
|
|
739
|
+
for true_d in effect_sizes:
|
|
740
|
+
# Generate treatment group with specified effect size
|
|
741
|
+
treatment = np.random.normal(true_d, 1, n)
|
|
742
|
+
|
|
743
|
+
# Compute Cohen's d
|
|
744
|
+
computed_d = cohens_d(control, treatment)
|
|
745
|
+
interpretation = interpret_cohens_d(computed_d)
|
|
746
|
+
|
|
747
|
+
logger.info(
|
|
748
|
+
f"True d = {true_d:.1f}, "
|
|
749
|
+
f"Computed d = {computed_d:.3f}, "
|
|
750
|
+
f"Interpretation: {interpretation}"
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
results.append({
|
|
754
|
+
'true_d': true_d,
|
|
755
|
+
'computed_d': computed_d,
|
|
756
|
+
'interpretation': interpretation
|
|
757
|
+
})
|
|
758
|
+
|
|
759
|
+
# Example 2: Paired vs independent
|
|
760
|
+
logger.info("\n=== Example 2: Paired vs Independent ===")
|
|
761
|
+
|
|
762
|
+
# Generate correlated paired samples
|
|
763
|
+
n_pairs = 30
|
|
764
|
+
baseline = np.random.normal(0, 1, n_pairs)
|
|
765
|
+
noise = np.random.normal(0, 0.3, n_pairs)
|
|
766
|
+
followup = baseline + 0.5 + noise # Effect size ~0.5
|
|
767
|
+
|
|
768
|
+
d_independent = cohens_d(baseline, followup, paired=False)
|
|
769
|
+
d_paired = cohens_d(baseline, followup, paired=True)
|
|
770
|
+
|
|
771
|
+
logger.info(f"Independent samples d = {d_independent:.3f}")
|
|
772
|
+
logger.info(f"Paired samples d = {d_paired:.3f}")
|
|
773
|
+
logger.info(f"Paired is more sensitive due to correlation")
|
|
774
|
+
|
|
775
|
+
# Example 3: Correction methods
|
|
776
|
+
logger.info("\n=== Example 3: Correction methods ===")
|
|
777
|
+
|
|
778
|
+
small_n = 10
|
|
779
|
+
x_small = np.random.normal(0, 1, small_n)
|
|
780
|
+
y_small = np.random.normal(0.5, 1, small_n)
|
|
781
|
+
|
|
782
|
+
d_standard = cohens_d(x_small, y_small)
|
|
783
|
+
d_hedges = cohens_d(x_small, y_small, correction='hedges')
|
|
784
|
+
d_glass = cohens_d(x_small, y_small, correction='glass')
|
|
785
|
+
|
|
786
|
+
logger.info(f"Standard Cohen's d = {d_standard:.3f}")
|
|
787
|
+
logger.info(f"Hedges' g = {d_hedges:.3f} (corrected for small n)")
|
|
788
|
+
logger.info(f"Glass's delta = {d_glass:.3f} (uses control SD only)")
|
|
789
|
+
|
|
790
|
+
# Example 4: Cliff's delta and P(X>Y) (non-parametric)
|
|
791
|
+
logger.info("\n=== Example 4: Non-parametric effect sizes ===")
|
|
792
|
+
|
|
793
|
+
x_cliff = np.array([1, 2, 3, 4, 5, 6, 7, 8])
|
|
794
|
+
y_cliff = np.array([3, 4, 5, 6, 7, 8, 9, 10])
|
|
795
|
+
|
|
796
|
+
delta = cliffs_delta(x_cliff, y_cliff)
|
|
797
|
+
prob = prob_superiority(x_cliff, y_cliff)
|
|
798
|
+
d_cohen = cohens_d(x_cliff, y_cliff)
|
|
799
|
+
|
|
800
|
+
logger.info(f"Cliff's delta: {delta:.3f} ({interpret_cliffs_delta(delta)})")
|
|
801
|
+
logger.info(f"P(X > Y): {prob:.3f} ({interpret_prob_superiority(prob)})")
|
|
802
|
+
logger.info(f"Cohen's d: {d_cohen:.3f}")
|
|
803
|
+
logger.info(f"Relationship: P(X>Y) = (1 + δ) / 2 = {(1 + delta) / 2:.3f}")
|
|
804
|
+
logger.info("Non-parametric measures are robust to outliers and distribution shape")
|
|
805
|
+
|
|
806
|
+
# Example 5: Cliff's delta with outliers
|
|
807
|
+
logger.info("\n=== Example 5: Cliff's delta robustness to outliers ===")
|
|
808
|
+
|
|
809
|
+
x_normal = np.array([1, 2, 3, 4, 5])
|
|
810
|
+
y_normal = np.array([3, 4, 5, 6, 7])
|
|
811
|
+
x_outlier = np.array([1, 2, 3, 4, 100]) # Extreme outlier
|
|
812
|
+
y_outlier = np.array([3, 4, 5, 6, 7])
|
|
813
|
+
|
|
814
|
+
delta_normal = cliffs_delta(x_normal, y_normal)
|
|
815
|
+
delta_outlier = cliffs_delta(x_outlier, y_outlier)
|
|
816
|
+
d_normal = cohens_d(x_normal, y_normal)
|
|
817
|
+
d_outlier = cohens_d(x_outlier, y_outlier)
|
|
818
|
+
|
|
819
|
+
logger.info(f"Without outlier: Cliff's δ = {delta_normal:.3f}, Cohen's d = {d_normal:.3f}")
|
|
820
|
+
logger.info(f"With outlier: Cliff's δ = {delta_outlier:.3f}, Cohen's d = {d_outlier:.3f}")
|
|
821
|
+
logger.info("Cliff's delta is stable, Cohen's d is inflated by outlier")
|
|
822
|
+
|
|
823
|
+
# Example 6: Eta-squared for ANOVA
|
|
824
|
+
logger.info("\n=== Example 6: Eta-squared for ANOVA ===")
|
|
825
|
+
|
|
826
|
+
group1 = np.random.normal(0, 1, 30)
|
|
827
|
+
group2 = np.random.normal(0.5, 1, 30)
|
|
828
|
+
group3 = np.random.normal(1.0, 1, 30)
|
|
829
|
+
|
|
830
|
+
eta2 = eta_squared([group1, group2, group3])
|
|
831
|
+
eta2_interp = interpret_eta_squared(eta2)
|
|
832
|
+
|
|
833
|
+
logger.info(f"Eta-squared = {eta2:.3f} ({eta2_interp})")
|
|
834
|
+
logger.info(f"{eta2:.1%} of variance explained by group membership")
|
|
835
|
+
|
|
836
|
+
# Example 7: Eta-squared with different group variances
|
|
837
|
+
logger.info("\n=== Example 7: Effect size comparison across methods ===")
|
|
838
|
+
|
|
839
|
+
control = np.random.normal(0, 1, 40)
|
|
840
|
+
treatment = np.random.normal(0.6, 1, 40)
|
|
841
|
+
|
|
842
|
+
d = cohens_d(control, treatment)
|
|
843
|
+
delta = cliffs_delta(control, treatment)
|
|
844
|
+
eta2_groups = eta_squared([control, treatment])
|
|
845
|
+
|
|
846
|
+
prob = prob_superiority(control, treatment)
|
|
847
|
+
|
|
848
|
+
logger.info(f"Cohen's d: {d:.3f} ({interpret_cohens_d(d)})")
|
|
849
|
+
logger.info(f"Cliff's delta: {delta:.3f} ({interpret_cliffs_delta(delta)})")
|
|
850
|
+
logger.info(f"P(X > Y): {prob:.3f} ({interpret_prob_superiority(prob)})")
|
|
851
|
+
logger.info(f"Eta-squared: {eta2_groups:.3f} ({interpret_eta_squared(eta2_groups)})")
|
|
852
|
+
|
|
853
|
+
# Create visualization
|
|
854
|
+
logger.info("\n=== Creating visualization ===")
|
|
855
|
+
|
|
856
|
+
fig, axes = stx.plt.subplots(2, 2, figsize=(12, 10))
|
|
857
|
+
|
|
858
|
+
# Plot 1: Effect size comparison
|
|
859
|
+
ax = axes[0, 0]
|
|
860
|
+
df_results = pd.DataFrame(results)
|
|
861
|
+
ax.scatter(df_results['true_d'], df_results['computed_d'], s=100)
|
|
862
|
+
ax.plot([-0.5, 1.5], [-0.5, 1.5], 'k--', alpha=0.5, label='Perfect agreement')
|
|
863
|
+
ax.set_xlabel('True Effect Size')
|
|
864
|
+
ax.set_ylabel('Computed Cohen\'s d')
|
|
865
|
+
ax.set_title('True vs Computed Effect Sizes')
|
|
866
|
+
ax.legend()
|
|
867
|
+
ax.grid(True, alpha=0.3)
|
|
868
|
+
|
|
869
|
+
# Plot 2: Distribution visualization
|
|
870
|
+
ax = axes[0, 1]
|
|
871
|
+
control_demo = np.random.normal(0, 1, 1000)
|
|
872
|
+
treatment_demo = np.random.normal(0.8, 1, 1000)
|
|
873
|
+
|
|
874
|
+
ax.hist(control_demo, bins=30, alpha=0.5, label='Control', density=True)
|
|
875
|
+
ax.hist(treatment_demo, bins=30, alpha=0.5, label='Treatment', density=True)
|
|
876
|
+
|
|
877
|
+
d_demo = cohens_d(control_demo, treatment_demo)
|
|
878
|
+
ax.axvline(np.mean(control_demo), color='blue', linestyle='--', alpha=0.7)
|
|
879
|
+
ax.axvline(np.mean(treatment_demo), color='orange', linestyle='--', alpha=0.7)
|
|
880
|
+
|
|
881
|
+
ax.set_xlabel('Value')
|
|
882
|
+
ax.set_ylabel('Density')
|
|
883
|
+
ax.set_title(f'Distributions (Cohen\'s d = {d_demo:.2f})')
|
|
884
|
+
ax.legend()
|
|
885
|
+
|
|
886
|
+
# Plot 3: Effect size interpretation
|
|
887
|
+
ax = axes[1, 0]
|
|
888
|
+
d_values = np.linspace(-1.5, 1.5, 100)
|
|
889
|
+
interpretations = [interpret_cohens_d(d) for d in d_values]
|
|
890
|
+
|
|
891
|
+
# Color map
|
|
892
|
+
color_map = {'negligible': 'lightgray', 'small': 'yellow',
|
|
893
|
+
'medium': 'orange', 'large': 'red'}
|
|
894
|
+
colors = [color_map[i] for i in interpretations]
|
|
895
|
+
|
|
896
|
+
ax.scatter(d_values, [0] * len(d_values), c=colors, s=50, alpha=0.7)
|
|
897
|
+
ax.set_xlabel('Cohen\'s d')
|
|
898
|
+
ax.set_yticks([])
|
|
899
|
+
ax.set_title('Effect Size Interpretation')
|
|
900
|
+
ax.axvline(0, color='black', linestyle='-', alpha=0.3)
|
|
901
|
+
ax.axvline(0.2, color='black', linestyle='--', alpha=0.3)
|
|
902
|
+
ax.axvline(0.5, color='black', linestyle='--', alpha=0.3)
|
|
903
|
+
ax.axvline(0.8, color='black', linestyle='--', alpha=0.3)
|
|
904
|
+
|
|
905
|
+
# Add labels
|
|
906
|
+
ax.text(0.1, 0.5, 'Negligible', ha='center', fontsize=9)
|
|
907
|
+
ax.text(0.35, 0.5, 'Small', ha='center', fontsize=9)
|
|
908
|
+
ax.text(0.65, 0.5, 'Medium', ha='center', fontsize=9)
|
|
909
|
+
ax.text(1.15, 0.5, 'Large', ha='center', fontsize=9)
|
|
910
|
+
|
|
911
|
+
# Plot 4: Sample size vs precision
|
|
912
|
+
ax = axes[1, 1]
|
|
913
|
+
sample_sizes = [10, 20, 30, 50, 100, 200]
|
|
914
|
+
precisions = []
|
|
915
|
+
|
|
916
|
+
for n in sample_sizes:
|
|
917
|
+
# Simulate multiple experiments
|
|
918
|
+
ds = []
|
|
919
|
+
for _ in range(100):
|
|
920
|
+
x = np.random.normal(0, 1, n)
|
|
921
|
+
y = np.random.normal(0.5, 1, n) # True d = 0.5
|
|
922
|
+
ds.append(cohens_d(x, y))
|
|
923
|
+
|
|
924
|
+
precisions.append(np.std(ds))
|
|
925
|
+
|
|
926
|
+
ax.plot(sample_sizes, precisions, 'o-', linewidth=2)
|
|
927
|
+
ax.set_xlabel('Sample Size (per group)')
|
|
928
|
+
ax.set_ylabel('Std Dev of Cohen\'s d')
|
|
929
|
+
ax.set_title('Effect Size Precision vs Sample Size')
|
|
930
|
+
ax.grid(True, alpha=0.3)
|
|
931
|
+
ax.set_xscale('log')
|
|
932
|
+
|
|
933
|
+
plt.tight_layout()
|
|
934
|
+
|
|
935
|
+
# Save
|
|
936
|
+
stx.io.save(fig, './cohens_d_demo.jpg')
|
|
937
|
+
logger.info("Visualization saved")
|
|
938
|
+
|
|
939
|
+
return 0
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
def parse_args():
|
|
943
|
+
"""Parse command line arguments."""
|
|
944
|
+
parser = argparse.ArgumentParser(
|
|
945
|
+
description='Demonstrate Cohen\'s d effect size calculation'
|
|
946
|
+
)
|
|
947
|
+
parser.add_argument(
|
|
948
|
+
'--verbose',
|
|
949
|
+
action='store_true',
|
|
950
|
+
help='Enable verbose output'
|
|
951
|
+
)
|
|
952
|
+
return parser.parse_args()
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
def run_main():
|
|
956
|
+
"""Initialize SciTeX framework and run main."""
|
|
957
|
+
global CONFIG, sys, plt, rng
|
|
958
|
+
|
|
959
|
+
import sys
|
|
960
|
+
import matplotlib.pyplot as plt
|
|
961
|
+
|
|
962
|
+
args = parse_args()
|
|
963
|
+
|
|
964
|
+
CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
|
|
965
|
+
sys,
|
|
966
|
+
plt,
|
|
967
|
+
args=args,
|
|
968
|
+
file=__file__,
|
|
969
|
+
verbose=args.verbose,
|
|
970
|
+
agg=True,
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
exit_status = main(args)
|
|
974
|
+
|
|
975
|
+
stx.session.close(
|
|
976
|
+
CONFIG,
|
|
977
|
+
verbose=args.verbose,
|
|
978
|
+
exit_status=exit_status,
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
if __name__ == '__main__':
|
|
983
|
+
run_main()
|
|
984
|
+
|
|
985
|
+
# EOF
|