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,322 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-08-01 10:35:00 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/SciTeX-Code/src/scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Unit-Aware Plotting Mixin
|
|
9
|
+
=========================
|
|
10
|
+
|
|
11
|
+
This mixin adds unit handling capabilities to the AxisWrapper class,
|
|
12
|
+
ensuring scientific validity in plots.
|
|
13
|
+
|
|
14
|
+
Features:
|
|
15
|
+
- Automatic unit tracking for axes
|
|
16
|
+
- Unit validation for data compatibility
|
|
17
|
+
- Automatic unit conversion
|
|
18
|
+
- Unit-aware axis labels
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Optional, Dict, Tuple, Union, Any
|
|
22
|
+
import numpy as np
|
|
23
|
+
from ....units import Unit, Q, Units
|
|
24
|
+
from ....errors import SciTeXError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class UnitMismatchError(SciTeXError):
|
|
28
|
+
"""Raised when units are incompatible for an operation."""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class UnitAwareMixin:
|
|
33
|
+
"""Mixin that adds unit awareness to plotting operations."""
|
|
34
|
+
|
|
35
|
+
def __init__(self):
|
|
36
|
+
"""Initialize unit tracking."""
|
|
37
|
+
self._x_unit: Optional[Unit] = None
|
|
38
|
+
self._y_unit: Optional[Unit] = None
|
|
39
|
+
self._z_unit: Optional[Unit] = None
|
|
40
|
+
self._unit_validation_enabled: bool = True
|
|
41
|
+
|
|
42
|
+
def set_unit_validation(self, enabled: bool) -> None:
|
|
43
|
+
"""Enable or disable unit validation."""
|
|
44
|
+
self._unit_validation_enabled = enabled
|
|
45
|
+
|
|
46
|
+
def set_x_unit(self, unit: Union[str, Unit]) -> None:
|
|
47
|
+
"""Set the unit for the x-axis."""
|
|
48
|
+
if isinstance(unit, str):
|
|
49
|
+
unit_obj = getattr(Units, unit, None)
|
|
50
|
+
if unit_obj is None:
|
|
51
|
+
raise ValueError(f"Unknown unit: {unit}")
|
|
52
|
+
unit = unit_obj
|
|
53
|
+
self._x_unit = unit
|
|
54
|
+
self._update_xlabel_with_unit()
|
|
55
|
+
|
|
56
|
+
def set_y_unit(self, unit: Union[str, Unit]) -> None:
|
|
57
|
+
"""Set the unit for the y-axis."""
|
|
58
|
+
if isinstance(unit, str):
|
|
59
|
+
unit_obj = getattr(Units, unit, None)
|
|
60
|
+
if unit_obj is None:
|
|
61
|
+
raise ValueError(f"Unknown unit: {unit}")
|
|
62
|
+
unit = unit_obj
|
|
63
|
+
self._y_unit = unit
|
|
64
|
+
self._update_ylabel_with_unit()
|
|
65
|
+
|
|
66
|
+
def set_z_unit(self, unit: Union[str, Unit]) -> None:
|
|
67
|
+
"""Set the unit for the z-axis (for 3D plots)."""
|
|
68
|
+
if isinstance(unit, str):
|
|
69
|
+
unit_obj = getattr(Units, unit, None)
|
|
70
|
+
if unit_obj is None:
|
|
71
|
+
raise ValueError(f"Unknown unit: {unit}")
|
|
72
|
+
unit = unit_obj
|
|
73
|
+
self._z_unit = unit
|
|
74
|
+
self._update_zlabel_with_unit()
|
|
75
|
+
|
|
76
|
+
def get_x_unit(self) -> Optional[Unit]:
|
|
77
|
+
"""Get the current x-axis unit."""
|
|
78
|
+
return self._x_unit
|
|
79
|
+
|
|
80
|
+
def get_y_unit(self) -> Optional[Unit]:
|
|
81
|
+
"""Get the current y-axis unit."""
|
|
82
|
+
return self._y_unit
|
|
83
|
+
|
|
84
|
+
def get_z_unit(self) -> Optional[Unit]:
|
|
85
|
+
"""Get the current z-axis unit."""
|
|
86
|
+
return self._z_unit
|
|
87
|
+
|
|
88
|
+
def _update_xlabel_with_unit(self) -> None:
|
|
89
|
+
"""Update x-axis label to include unit."""
|
|
90
|
+
if self._x_unit and hasattr(self, '_axes_mpl'):
|
|
91
|
+
current_label = self._axes_mpl.get_xlabel()
|
|
92
|
+
# Remove existing unit if present
|
|
93
|
+
if '[' in current_label and ']' in current_label:
|
|
94
|
+
current_label = current_label.split('[')[0].strip()
|
|
95
|
+
if current_label:
|
|
96
|
+
self._axes_mpl.set_xlabel(f"{current_label} [{self._x_unit.symbol}]")
|
|
97
|
+
|
|
98
|
+
def _update_ylabel_with_unit(self) -> None:
|
|
99
|
+
"""Update y-axis label to include unit."""
|
|
100
|
+
if self._y_unit and hasattr(self, '_axes_mpl'):
|
|
101
|
+
current_label = self._axes_mpl.get_ylabel()
|
|
102
|
+
# Remove existing unit if present
|
|
103
|
+
if '[' in current_label and ']' in current_label:
|
|
104
|
+
current_label = current_label.split('[')[0].strip()
|
|
105
|
+
if current_label:
|
|
106
|
+
self._axes_mpl.set_ylabel(f"{current_label} [{self._y_unit.symbol}]")
|
|
107
|
+
|
|
108
|
+
def _update_zlabel_with_unit(self) -> None:
|
|
109
|
+
"""Update z-axis label to include unit (for 3D plots)."""
|
|
110
|
+
if self._z_unit and hasattr(self, '_axes_mpl') and hasattr(self._axes_mpl, 'set_zlabel'):
|
|
111
|
+
current_label = self._axes_mpl.get_zlabel()
|
|
112
|
+
# Remove existing unit if present
|
|
113
|
+
if '[' in current_label and ']' in current_label:
|
|
114
|
+
current_label = current_label.split('[')[0].strip()
|
|
115
|
+
if current_label:
|
|
116
|
+
self._axes_mpl.set_zlabel(f"{current_label} [{self._z_unit.symbol}]")
|
|
117
|
+
|
|
118
|
+
def plot_with_units(self, x, y, x_unit=None, y_unit=None, **kwargs):
|
|
119
|
+
"""Plot with automatic unit handling.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
x : array-like or Quantity
|
|
124
|
+
X-axis data
|
|
125
|
+
y : array-like or Quantity
|
|
126
|
+
Y-axis data
|
|
127
|
+
x_unit : str or Unit, optional
|
|
128
|
+
Unit for x-axis (overrides detected unit)
|
|
129
|
+
y_unit : str or Unit, optional
|
|
130
|
+
Unit for y-axis (overrides detected unit)
|
|
131
|
+
**kwargs : dict
|
|
132
|
+
Additional plotting parameters
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
lines : list of Line2D
|
|
137
|
+
The plotted lines
|
|
138
|
+
"""
|
|
139
|
+
# Extract values and units from Quantity objects
|
|
140
|
+
x_val, x_detected_unit = self._extract_value_and_unit(x)
|
|
141
|
+
y_val, y_detected_unit = self._extract_value_and_unit(y)
|
|
142
|
+
|
|
143
|
+
# Use provided units or detected units
|
|
144
|
+
if x_unit:
|
|
145
|
+
self.set_x_unit(x_unit)
|
|
146
|
+
elif x_detected_unit and not self._x_unit:
|
|
147
|
+
self.set_x_unit(x_detected_unit)
|
|
148
|
+
|
|
149
|
+
if y_unit:
|
|
150
|
+
self.set_y_unit(y_unit)
|
|
151
|
+
elif y_detected_unit and not self._y_unit:
|
|
152
|
+
self.set_y_unit(y_detected_unit)
|
|
153
|
+
|
|
154
|
+
# Validate units if enabled
|
|
155
|
+
if self._unit_validation_enabled:
|
|
156
|
+
self._validate_unit_compatibility(x_detected_unit, self._x_unit, "x")
|
|
157
|
+
self._validate_unit_compatibility(y_detected_unit, self._y_unit, "y")
|
|
158
|
+
|
|
159
|
+
# Plot using the standard method
|
|
160
|
+
return self.plot(x_val, y_val, **kwargs)
|
|
161
|
+
|
|
162
|
+
def _extract_value_and_unit(self, data) -> Tuple[np.ndarray, Optional[Unit]]:
|
|
163
|
+
"""Extract numerical value and unit from data."""
|
|
164
|
+
if hasattr(data, 'value') and hasattr(data, 'unit'):
|
|
165
|
+
# It's a Quantity object
|
|
166
|
+
return data.value, data.unit
|
|
167
|
+
else:
|
|
168
|
+
# Regular array
|
|
169
|
+
return np.asarray(data), None
|
|
170
|
+
|
|
171
|
+
def _validate_unit_compatibility(self, data_unit: Optional[Unit],
|
|
172
|
+
axis_unit: Optional[Unit],
|
|
173
|
+
axis_name: str) -> None:
|
|
174
|
+
"""Validate that data unit is compatible with axis unit."""
|
|
175
|
+
if not self._unit_validation_enabled:
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
if data_unit and axis_unit:
|
|
179
|
+
# Check if units have same dimensions
|
|
180
|
+
if data_unit.dimensions != axis_unit.dimensions:
|
|
181
|
+
raise UnitMismatchError(
|
|
182
|
+
f"Unit mismatch on {axis_name}-axis: "
|
|
183
|
+
f"data has unit {data_unit.symbol} {data_unit.dimensions}, "
|
|
184
|
+
f"but axis expects {axis_unit.symbol} {axis_unit.dimensions}"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def convert_x_units(self, new_unit: Union[str, Unit],
|
|
188
|
+
update_data: bool = True) -> float:
|
|
189
|
+
"""Convert x-axis to new units.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
new_unit : str or Unit
|
|
194
|
+
Target unit
|
|
195
|
+
update_data : bool
|
|
196
|
+
Whether to update plotted data
|
|
197
|
+
|
|
198
|
+
Returns
|
|
199
|
+
-------
|
|
200
|
+
float
|
|
201
|
+
Conversion factor applied
|
|
202
|
+
"""
|
|
203
|
+
if isinstance(new_unit, str):
|
|
204
|
+
new_unit = getattr(Units, new_unit)
|
|
205
|
+
|
|
206
|
+
if not self._x_unit:
|
|
207
|
+
raise ValueError("No x-axis unit set")
|
|
208
|
+
|
|
209
|
+
# Calculate conversion factor
|
|
210
|
+
factor = self._x_unit.scale / new_unit.scale
|
|
211
|
+
|
|
212
|
+
if update_data and hasattr(self, '_axes_mpl'):
|
|
213
|
+
# Update all line data
|
|
214
|
+
for line in self._axes_mpl.lines:
|
|
215
|
+
xdata = line.get_xdata()
|
|
216
|
+
line.set_xdata(xdata * factor)
|
|
217
|
+
|
|
218
|
+
# Update x-axis limits
|
|
219
|
+
xlim = self._axes_mpl.get_xlim()
|
|
220
|
+
self._axes_mpl.set_xlim([x * factor for x in xlim])
|
|
221
|
+
|
|
222
|
+
# Update unit
|
|
223
|
+
self.set_x_unit(new_unit)
|
|
224
|
+
|
|
225
|
+
return factor
|
|
226
|
+
|
|
227
|
+
def convert_y_units(self, new_unit: Union[str, Unit],
|
|
228
|
+
update_data: bool = True) -> float:
|
|
229
|
+
"""Convert y-axis to new units.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
new_unit : str or Unit
|
|
234
|
+
Target unit
|
|
235
|
+
update_data : bool
|
|
236
|
+
Whether to update plotted data
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
float
|
|
241
|
+
Conversion factor applied
|
|
242
|
+
"""
|
|
243
|
+
if isinstance(new_unit, str):
|
|
244
|
+
new_unit = getattr(Units, new_unit)
|
|
245
|
+
|
|
246
|
+
if not self._y_unit:
|
|
247
|
+
raise ValueError("No y-axis unit set")
|
|
248
|
+
|
|
249
|
+
# Calculate conversion factor
|
|
250
|
+
factor = self._y_unit.scale / new_unit.scale
|
|
251
|
+
|
|
252
|
+
if update_data and hasattr(self, '_axes_mpl'):
|
|
253
|
+
# Update all line data
|
|
254
|
+
for line in self._axes_mpl.lines:
|
|
255
|
+
ydata = line.get_ydata()
|
|
256
|
+
line.set_ydata(ydata * factor)
|
|
257
|
+
|
|
258
|
+
# Update y-axis limits
|
|
259
|
+
ylim = self._axes_mpl.get_ylim()
|
|
260
|
+
self._axes_mpl.set_ylim([y * factor for y in ylim])
|
|
261
|
+
|
|
262
|
+
# Update unit
|
|
263
|
+
self.set_y_unit(new_unit)
|
|
264
|
+
|
|
265
|
+
return factor
|
|
266
|
+
|
|
267
|
+
def set_xlabel(self, label: str, unit: Optional[Union[str, Unit]] = None) -> None:
|
|
268
|
+
"""Set x-axis label with optional unit.
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
label : str
|
|
273
|
+
Axis label text
|
|
274
|
+
unit : str or Unit, optional
|
|
275
|
+
Unit to display
|
|
276
|
+
"""
|
|
277
|
+
if unit:
|
|
278
|
+
self.set_x_unit(unit)
|
|
279
|
+
|
|
280
|
+
if self._x_unit:
|
|
281
|
+
label = f"{label} [{self._x_unit.symbol}]"
|
|
282
|
+
|
|
283
|
+
self._axes_mpl.set_xlabel(label)
|
|
284
|
+
|
|
285
|
+
def set_ylabel(self, label: str, unit: Optional[Union[str, Unit]] = None) -> None:
|
|
286
|
+
"""Set y-axis label with optional unit.
|
|
287
|
+
|
|
288
|
+
Parameters
|
|
289
|
+
----------
|
|
290
|
+
label : str
|
|
291
|
+
Axis label text
|
|
292
|
+
unit : str or Unit, optional
|
|
293
|
+
Unit to display
|
|
294
|
+
"""
|
|
295
|
+
if unit:
|
|
296
|
+
self.set_y_unit(unit)
|
|
297
|
+
|
|
298
|
+
if self._y_unit:
|
|
299
|
+
label = f"{label} [{self._y_unit.symbol}]"
|
|
300
|
+
|
|
301
|
+
self._axes_mpl.set_ylabel(label)
|
|
302
|
+
|
|
303
|
+
def set_zlabel(self, label: str, unit: Optional[Union[str, Unit]] = None) -> None:
|
|
304
|
+
"""Set z-axis label with optional unit (for 3D plots).
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
label : str
|
|
309
|
+
Axis label text
|
|
310
|
+
unit : str or Unit, optional
|
|
311
|
+
Unit to display
|
|
312
|
+
"""
|
|
313
|
+
if not hasattr(self._axes_mpl, 'set_zlabel'):
|
|
314
|
+
raise ValueError("Z-axis labels only available for 3D plots")
|
|
315
|
+
|
|
316
|
+
if unit:
|
|
317
|
+
self.set_z_unit(unit)
|
|
318
|
+
|
|
319
|
+
if self._z_unit:
|
|
320
|
+
label = f"{label} [{self._z_unit.symbol}]"
|
|
321
|
+
|
|
322
|
+
self._axes_mpl.set_zlabel(label)
|
|
@@ -18,6 +18,7 @@ import pandas as pd
|
|
|
18
18
|
class FigWrapper:
|
|
19
19
|
def __init__(self, fig_mpl):
|
|
20
20
|
self._fig_mpl = fig_mpl
|
|
21
|
+
self._axes = [] # Keep track of axes for synchronization
|
|
21
22
|
self._last_saved_info = None
|
|
22
23
|
self._not_saved_yet_flag = True
|
|
23
24
|
self._called_from_mng_io_save = False
|
|
@@ -36,7 +37,17 @@ class FigWrapper:
|
|
|
36
37
|
|
|
37
38
|
@wraps(attr_mpl)
|
|
38
39
|
def wrapper(*args, track=None, id=None, **kwargs):
|
|
39
|
-
|
|
40
|
+
# Suppress constrained_layout warnings for certain operations
|
|
41
|
+
import warnings
|
|
42
|
+
with warnings.catch_warnings():
|
|
43
|
+
if attr in ['subplots_adjust', 'tight_layout']:
|
|
44
|
+
warnings.filterwarnings('ignore',
|
|
45
|
+
message='.*constrained_layout.*',
|
|
46
|
+
category=UserWarning)
|
|
47
|
+
warnings.filterwarnings('ignore',
|
|
48
|
+
message='.*layout engine.*incompatible.*',
|
|
49
|
+
category=UserWarning)
|
|
50
|
+
results = attr_mpl(*args, **kwargs)
|
|
40
51
|
# self._track(track, id, attr, args, kwargs)
|
|
41
52
|
return results
|
|
42
53
|
|
|
@@ -96,15 +107,59 @@ class FigWrapper:
|
|
|
96
107
|
if df is not None and not df.empty:
|
|
97
108
|
# Add axis ID prefix to column names if not already present
|
|
98
109
|
prefix = f"ax_{ii:02d}_"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
# Make column names unique by appending index if there are duplicates
|
|
111
|
+
new_cols = []
|
|
112
|
+
col_counts = {}
|
|
113
|
+
for col in df.columns:
|
|
114
|
+
# Convert to string and check if already has prefix
|
|
115
|
+
col_str = str(col) if not (isinstance(col, str) and col.startswith(prefix)) else col
|
|
116
|
+
if not col_str.startswith(prefix):
|
|
117
|
+
col_str = f"{prefix}{col_str}"
|
|
118
|
+
|
|
119
|
+
# Handle duplicates by adding a counter
|
|
120
|
+
if col_str in col_counts:
|
|
121
|
+
col_counts[col_str] += 1
|
|
122
|
+
col_str = f"{col_str}_{col_counts[col_str]}"
|
|
123
|
+
else:
|
|
124
|
+
col_counts[col_str] = 0
|
|
125
|
+
|
|
126
|
+
new_cols.append(col_str)
|
|
127
|
+
|
|
128
|
+
df.columns = new_cols
|
|
103
129
|
dfs.append(df)
|
|
104
130
|
|
|
105
131
|
# Return concatenated DataFrame or empty DataFrame if no data
|
|
106
132
|
return pd.concat(dfs, axis=1) if dfs else pd.DataFrame()
|
|
107
|
-
|
|
133
|
+
|
|
134
|
+
def colorbar(self, mappable, ax=None, **kwargs):
|
|
135
|
+
"""Add a colorbar to the figure, automatically unwrapping SciTeX axes.
|
|
136
|
+
|
|
137
|
+
This method properly handles both regular matplotlib axes and SciTeX
|
|
138
|
+
AxisWrapper objects when creating colorbars.
|
|
139
|
+
|
|
140
|
+
Parameters:
|
|
141
|
+
-----------
|
|
142
|
+
mappable : ScalarMappable
|
|
143
|
+
The image, contour set, etc. to which the colorbar applies
|
|
144
|
+
ax : Axes or AxisWrapper, optional
|
|
145
|
+
The axes to attach the colorbar to. If not specified, uses current axes.
|
|
146
|
+
**kwargs : dict
|
|
147
|
+
Additional keyword arguments passed to matplotlib's colorbar
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
--------
|
|
151
|
+
Colorbar
|
|
152
|
+
The created colorbar object
|
|
153
|
+
"""
|
|
154
|
+
# Unwrap axes if it's a SciTeX AxisWrapper
|
|
155
|
+
if ax is not None:
|
|
156
|
+
ax_mpl = ax._axis_mpl if hasattr(ax, '_axis_mpl') else ax
|
|
157
|
+
else:
|
|
158
|
+
ax_mpl = None
|
|
159
|
+
|
|
160
|
+
# Call matplotlib's colorbar with the unwrapped axes
|
|
161
|
+
return self._fig_mpl.colorbar(mappable, ax=ax_mpl, **kwargs)
|
|
162
|
+
|
|
108
163
|
def _traverse_axes(self):
|
|
109
164
|
"""Helper method to traverse all axis wrappers in the figure."""
|
|
110
165
|
if hasattr(self, 'axes'):
|
|
@@ -179,6 +234,7 @@ class FigWrapper:
|
|
|
179
234
|
# If both fail, do nothing - figure will use default layout
|
|
180
235
|
pass
|
|
181
236
|
|
|
237
|
+
|
|
182
238
|
def adjust_layout(self, **kwargs):
|
|
183
239
|
"""Adjust the constrained layout parameters.
|
|
184
240
|
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-
|
|
3
|
+
# Timestamp: "2025-09-21 01:52:22 (ywatanabe)"
|
|
4
4
|
# File: /ssh:sp:/home/ywatanabe/proj/scitex_repo/src/scitex/plt/_subplots/_export_as_csv.py
|
|
5
5
|
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
6
7
|
import os
|
|
7
|
-
|
|
8
|
-
__FILE__ = "./src/scitex/plt/_subplots/_export_as_csv.py"
|
|
8
|
+
__FILE__ = __file__
|
|
9
9
|
__DIR__ = os.path.dirname(__FILE__)
|
|
10
10
|
# ----------------------------------------
|
|
11
11
|
|
|
12
12
|
import warnings
|
|
13
13
|
|
|
14
|
+
import numpy as np
|
|
14
15
|
import pandas as pd
|
|
16
|
+
from scitex.pd import to_xyz
|
|
15
17
|
|
|
16
|
-
from ._export_as_csv_formatters import (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
_format_plot_box,
|
|
18
|
+
from ._export_as_csv_formatters import (_format_annotate, _format_bar,
|
|
19
|
+
_format_barh, _format_boxplot,
|
|
20
|
+
_format_contour, _format_errorbar,
|
|
21
|
+
_format_eventplot, _format_fill,
|
|
22
|
+
_format_fill_between, _format_hist,
|
|
23
|
+
_format_imshow, _format_imshow2d,
|
|
24
|
+
_format_plot, _format_plot_box,
|
|
23
25
|
_format_plot_conf_mat,
|
|
24
26
|
_format_plot_ecdf, _format_plot_fillv,
|
|
25
27
|
_format_plot_heatmap,
|
|
@@ -31,6 +33,7 @@ from ._export_as_csv_formatters import (_format_bar, _format_barh,
|
|
|
31
33
|
_format_plot_median_iqr,
|
|
32
34
|
_format_plot_raster,
|
|
33
35
|
_format_plot_rectangle,
|
|
36
|
+
_format_plot_scatter,
|
|
34
37
|
_format_plot_scatter_hist,
|
|
35
38
|
_format_plot_shaded_line,
|
|
36
39
|
_format_plot_violin, _format_scatter,
|
|
@@ -45,30 +48,30 @@ from ._export_as_csv_formatters import (_format_bar, _format_barh,
|
|
|
45
48
|
_format_sns_scatterplot,
|
|
46
49
|
_format_sns_stripplot,
|
|
47
50
|
_format_sns_swarmplot,
|
|
48
|
-
_format_sns_violinplot,
|
|
49
|
-
_format_violinplot)
|
|
50
|
-
|
|
51
|
-
from scitex.pd import to_xyz
|
|
51
|
+
_format_sns_violinplot, _format_text,
|
|
52
|
+
_format_violin, _format_violinplot)
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
def _to_numpy(data):
|
|
55
56
|
"""Convert various data types to numpy array.
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
Handles torch tensors, pandas Series/DataFrame, and other array-like objects.
|
|
58
|
-
|
|
59
|
+
|
|
59
60
|
Parameters
|
|
60
61
|
----------
|
|
61
62
|
data : array-like
|
|
62
63
|
Data to convert to numpy array
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
Returns
|
|
65
66
|
-------
|
|
66
67
|
numpy.ndarray
|
|
67
68
|
Data as numpy array
|
|
68
69
|
"""
|
|
69
|
-
if hasattr(data,
|
|
70
|
-
return
|
|
71
|
-
|
|
70
|
+
if hasattr(data, "numpy"): # torch tensor
|
|
71
|
+
return (
|
|
72
|
+
data.detach().numpy() if hasattr(data, "detach") else data.numpy()
|
|
73
|
+
)
|
|
74
|
+
elif hasattr(data, "values"): # pandas series/dataframe
|
|
72
75
|
return data.values
|
|
73
76
|
else:
|
|
74
77
|
return np.asarray(data)
|
|
@@ -98,23 +101,30 @@ def export_as_csv(history_records):
|
|
|
98
101
|
dfs.append(formatted_df)
|
|
99
102
|
except Exception as e:
|
|
100
103
|
warnings.warn(f"Failed to format record {record[0]}: {e}")
|
|
101
|
-
|
|
104
|
+
|
|
102
105
|
# If no valid dataframes were created, return an empty one
|
|
103
106
|
if not dfs:
|
|
104
107
|
warnings.warn("No valid data found to export.")
|
|
105
108
|
return pd.DataFrame()
|
|
106
109
|
|
|
107
110
|
try:
|
|
108
|
-
|
|
111
|
+
# Reset index for each dataframe to avoid alignment issues
|
|
112
|
+
dfs_reset = [df.reset_index(drop=True) for df in dfs]
|
|
113
|
+
df = pd.concat(dfs_reset, axis=1)
|
|
109
114
|
return df
|
|
110
115
|
except Exception as e:
|
|
111
116
|
warnings.warn(f"Failed to combine plotting records: {e}")
|
|
112
117
|
# Return a DataFrame with metadata about what records were attempted
|
|
113
|
-
meta_df = pd.DataFrame(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
meta_df = pd.DataFrame(
|
|
119
|
+
{
|
|
120
|
+
"record_id": [r[0] for r in history_records.values()],
|
|
121
|
+
"method": [r[1] for r in history_records.values()],
|
|
122
|
+
"has_data": [
|
|
123
|
+
"Yes" if r[2] and r[2] != {} else "No"
|
|
124
|
+
for r in history_records.values()
|
|
125
|
+
],
|
|
126
|
+
}
|
|
127
|
+
)
|
|
118
128
|
return meta_df
|
|
119
129
|
|
|
120
130
|
|
|
@@ -160,6 +170,10 @@ def format_record(record):
|
|
|
160
170
|
return _format_violin(id, tracked_dict, kwargs)
|
|
161
171
|
elif method == "violinplot":
|
|
162
172
|
return _format_violinplot(id, tracked_dict, kwargs)
|
|
173
|
+
elif method == "text":
|
|
174
|
+
return _format_text(id, tracked_dict, kwargs)
|
|
175
|
+
elif method == "annotate":
|
|
176
|
+
return _format_annotate(id, tracked_dict, kwargs)
|
|
163
177
|
|
|
164
178
|
# Custom plotting functions
|
|
165
179
|
elif method == "plot_box":
|
|
@@ -190,6 +204,8 @@ def format_record(record):
|
|
|
190
204
|
return _format_plot_raster(id, tracked_dict, kwargs)
|
|
191
205
|
elif method == "plot_rectangle":
|
|
192
206
|
return _format_plot_rectangle(id, tracked_dict, kwargs)
|
|
207
|
+
elif method == "plot_scatter":
|
|
208
|
+
return _format_plot_scatter(id, tracked_dict, kwargs)
|
|
193
209
|
elif method == "plot_scatter_hist":
|
|
194
210
|
return _format_plot_scatter_hist(id, tracked_dict, kwargs)
|
|
195
211
|
elif method == "plot_shaded_line":
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
# File: /data/gpfs/projects/punim2354/ywatanabe/scitex_repo/src/scitex/plt/_subplots/_export_as_csv_formatters/__init__.py
|
|
5
5
|
# ----------------------------------------
|
|
6
6
|
import os
|
|
7
|
-
__FILE__ =
|
|
8
|
-
"./src/scitex/plt/_subplots/_export_as_csv_formatters/__init__.py"
|
|
9
|
-
)
|
|
7
|
+
__FILE__ = __file__
|
|
10
8
|
__DIR__ = os.path.dirname(__FILE__)
|
|
11
9
|
# ----------------------------------------
|
|
12
10
|
|
|
13
11
|
# Standard matplotlib formatters
|
|
14
12
|
from ._format_plot import _format_plot
|
|
15
13
|
from ._format_scatter import _format_scatter
|
|
14
|
+
from ._format_text import _format_text
|
|
15
|
+
from ._format_annotate import _format_annotate
|
|
16
16
|
from ._format_bar import _format_bar
|
|
17
17
|
from ._format_barh import _format_barh
|
|
18
18
|
from ._format_hist import _format_hist
|
|
@@ -42,6 +42,7 @@ from ._format_plot_mean_std import _format_plot_mean_std
|
|
|
42
42
|
from ._format_plot_median_iqr import _format_plot_median_iqr
|
|
43
43
|
from ._format_plot_raster import _format_plot_raster
|
|
44
44
|
from ._format_plot_rectangle import _format_plot_rectangle
|
|
45
|
+
from ._format_plot_scatter import _format_plot_scatter
|
|
45
46
|
from ._format_plot_scatter_hist import _format_plot_scatter_hist
|
|
46
47
|
from ._format_plot_shaded_line import _format_plot_shaded_line
|
|
47
48
|
from ._format_plot_violin import _format_plot_violin
|
|
@@ -58,4 +59,4 @@ from ._format_sns_pairplot import _format_sns_pairplot
|
|
|
58
59
|
from ._format_sns_scatterplot import _format_sns_scatterplot
|
|
59
60
|
from ._format_sns_stripplot import _format_sns_stripplot
|
|
60
61
|
from ._format_sns_swarmplot import _format_sns_swarmplot
|
|
61
|
-
from ._format_sns_violinplot import _format_sns_violinplot
|
|
62
|
+
from ._format_sns_violinplot import _format_sns_violinplot
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-10-04 02:30:00 (ywatanabe)"
|
|
4
|
+
# File: /data/gpfs/projects/punim2354/ywatanabe/SciTeX-Code/src/scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = __file__
|
|
9
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
10
|
+
# ----------------------------------------
|
|
11
|
+
|
|
12
|
+
import pandas as pd
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _make_column_name(id, suffix, method="annotate"):
|
|
16
|
+
"""Create column name with method descriptor, avoiding duplication.
|
|
17
|
+
|
|
18
|
+
For example:
|
|
19
|
+
- id="annotate_0", suffix="x" -> "annotate_0_x"
|
|
20
|
+
- id="plot_5", suffix="x" -> "plot_5_annotate_x"
|
|
21
|
+
"""
|
|
22
|
+
# Check if method name is already in the ID
|
|
23
|
+
id_parts = id.rsplit('_', 1)
|
|
24
|
+
if len(id_parts) == 2 and id_parts[0].endswith(method):
|
|
25
|
+
# Method already in ID, don't duplicate
|
|
26
|
+
return f"{id}_{suffix}"
|
|
27
|
+
else:
|
|
28
|
+
# Method not in ID, add it for clarity
|
|
29
|
+
return f"{id}_{method}_{suffix}"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _format_annotate(id, tracked_dict, kwargs):
|
|
33
|
+
"""Format data from an annotate call.
|
|
34
|
+
|
|
35
|
+
matplotlib annotate signature: annotate(text, xy, xytext=None, **kwargs)
|
|
36
|
+
- text: The text of the annotation
|
|
37
|
+
- xy: The point (x, y) to annotate
|
|
38
|
+
- xytext: The position (x, y) to place the text at (optional)
|
|
39
|
+
"""
|
|
40
|
+
# Check if tracked_dict is empty or not a dictionary
|
|
41
|
+
if not tracked_dict or not isinstance(tracked_dict, dict):
|
|
42
|
+
return pd.DataFrame()
|
|
43
|
+
|
|
44
|
+
# Get the args from tracked_dict
|
|
45
|
+
args = tracked_dict.get("args", [])
|
|
46
|
+
|
|
47
|
+
# Extract text and xy coordinates if available
|
|
48
|
+
if len(args) >= 2:
|
|
49
|
+
text_content = args[0]
|
|
50
|
+
xy = args[1]
|
|
51
|
+
|
|
52
|
+
# xy should be a tuple (x, y)
|
|
53
|
+
if hasattr(xy, '__len__') and len(xy) >= 2:
|
|
54
|
+
x, y = xy[0], xy[1]
|
|
55
|
+
else:
|
|
56
|
+
return pd.DataFrame()
|
|
57
|
+
|
|
58
|
+
data = {
|
|
59
|
+
_make_column_name(id, "x"): [x],
|
|
60
|
+
_make_column_name(id, "y"): [y],
|
|
61
|
+
_make_column_name(id, "content"): [text_content]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Check if xytext was provided (either as third arg or in kwargs)
|
|
65
|
+
xytext = None
|
|
66
|
+
if len(args) >= 3:
|
|
67
|
+
xytext = args[2]
|
|
68
|
+
elif "xytext" in kwargs:
|
|
69
|
+
xytext = kwargs["xytext"]
|
|
70
|
+
|
|
71
|
+
if xytext is not None and hasattr(xytext, '__len__') and len(xytext) >= 2:
|
|
72
|
+
data[_make_column_name(id, "text_x")] = [xytext[0]]
|
|
73
|
+
data[_make_column_name(id, "text_y")] = [xytext[1]]
|
|
74
|
+
|
|
75
|
+
# Create DataFrame with proper column names (use dict with list values)
|
|
76
|
+
df = pd.DataFrame(data)
|
|
77
|
+
return df
|
|
78
|
+
|
|
79
|
+
return pd.DataFrame()
|
|
80
|
+
|
|
81
|
+
# EOF
|