scitex 2.0.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scitex/__init__.py +73 -0
- scitex/__main__.py +89 -0
- scitex/__version__.py +14 -0
- scitex/_sh.py +59 -0
- scitex/ai/_LearningCurveLogger.py +583 -0
- scitex/ai/__Classifiers.py +101 -0
- scitex/ai/__init__.py +55 -0
- scitex/ai/_gen_ai/_Anthropic.py +173 -0
- scitex/ai/_gen_ai/_BaseGenAI.py +336 -0
- scitex/ai/_gen_ai/_DeepSeek.py +175 -0
- scitex/ai/_gen_ai/_Google.py +161 -0
- scitex/ai/_gen_ai/_Groq.py +97 -0
- scitex/ai/_gen_ai/_Llama.py +142 -0
- scitex/ai/_gen_ai/_OpenAI.py +230 -0
- scitex/ai/_gen_ai/_PARAMS.py +565 -0
- scitex/ai/_gen_ai/_Perplexity.py +191 -0
- scitex/ai/_gen_ai/__init__.py +32 -0
- scitex/ai/_gen_ai/_calc_cost.py +78 -0
- scitex/ai/_gen_ai/_format_output_func.py +183 -0
- scitex/ai/_gen_ai/_genai_factory.py +71 -0
- scitex/ai/act/__init__.py +8 -0
- scitex/ai/act/_define.py +11 -0
- scitex/ai/classification/__init__.py +7 -0
- scitex/ai/classification/classification_reporter.py +1137 -0
- scitex/ai/classification/classifier_server.py +131 -0
- scitex/ai/classification/classifiers.py +101 -0
- scitex/ai/classification_reporter.py +1161 -0
- scitex/ai/classifier_server.py +131 -0
- scitex/ai/clustering/__init__.py +11 -0
- scitex/ai/clustering/_pca.py +115 -0
- scitex/ai/clustering/_umap.py +376 -0
- scitex/ai/early_stopping.py +149 -0
- scitex/ai/feature_extraction/__init__.py +56 -0
- scitex/ai/feature_extraction/vit.py +148 -0
- scitex/ai/genai/__init__.py +277 -0
- scitex/ai/genai/anthropic.py +177 -0
- scitex/ai/genai/anthropic_provider.py +320 -0
- scitex/ai/genai/anthropic_refactored.py +109 -0
- scitex/ai/genai/auth_manager.py +200 -0
- scitex/ai/genai/base_genai.py +336 -0
- scitex/ai/genai/base_provider.py +291 -0
- scitex/ai/genai/calc_cost.py +78 -0
- scitex/ai/genai/chat_history.py +307 -0
- scitex/ai/genai/cost_tracker.py +276 -0
- scitex/ai/genai/deepseek.py +188 -0
- scitex/ai/genai/deepseek_provider.py +251 -0
- scitex/ai/genai/format_output_func.py +183 -0
- scitex/ai/genai/genai_factory.py +71 -0
- scitex/ai/genai/google.py +169 -0
- scitex/ai/genai/google_provider.py +228 -0
- scitex/ai/genai/groq.py +104 -0
- scitex/ai/genai/groq_provider.py +248 -0
- scitex/ai/genai/image_processor.py +250 -0
- scitex/ai/genai/llama.py +155 -0
- scitex/ai/genai/llama_provider.py +214 -0
- scitex/ai/genai/mock_provider.py +127 -0
- scitex/ai/genai/model_registry.py +304 -0
- scitex/ai/genai/openai.py +230 -0
- scitex/ai/genai/openai_provider.py +293 -0
- scitex/ai/genai/params.py +565 -0
- scitex/ai/genai/perplexity.py +202 -0
- scitex/ai/genai/perplexity_provider.py +205 -0
- scitex/ai/genai/provider_base.py +302 -0
- scitex/ai/genai/provider_factory.py +370 -0
- scitex/ai/genai/response_handler.py +235 -0
- scitex/ai/layer/_Pass.py +21 -0
- scitex/ai/layer/__init__.py +10 -0
- scitex/ai/layer/_switch.py +8 -0
- scitex/ai/loss/_L1L2Losses.py +34 -0
- scitex/ai/loss/__init__.py +12 -0
- scitex/ai/loss/multi_task_loss.py +47 -0
- scitex/ai/metrics/__init__.py +9 -0
- scitex/ai/metrics/_bACC.py +51 -0
- scitex/ai/metrics/silhoute_score_block.py +496 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
- scitex/ai/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
- scitex/ai/optim/__init__.py +13 -0
- scitex/ai/optim/_get_set.py +31 -0
- scitex/ai/optim/_optimizers.py +71 -0
- scitex/ai/plt/__init__.py +21 -0
- scitex/ai/plt/_conf_mat.py +592 -0
- scitex/ai/plt/_learning_curve.py +194 -0
- scitex/ai/plt/_optuna_study.py +111 -0
- scitex/ai/plt/aucs/__init__.py +2 -0
- scitex/ai/plt/aucs/example.py +60 -0
- scitex/ai/plt/aucs/pre_rec_auc.py +223 -0
- scitex/ai/plt/aucs/roc_auc.py +246 -0
- scitex/ai/sampling/undersample.py +29 -0
- scitex/ai/sk/__init__.py +11 -0
- scitex/ai/sk/_clf.py +58 -0
- scitex/ai/sk/_to_sktime.py +100 -0
- scitex/ai/sklearn/__init__.py +26 -0
- scitex/ai/sklearn/clf.py +58 -0
- scitex/ai/sklearn/to_sktime.py +100 -0
- scitex/ai/training/__init__.py +7 -0
- scitex/ai/training/early_stopping.py +150 -0
- scitex/ai/training/learning_curve_logger.py +555 -0
- scitex/ai/utils/__init__.py +22 -0
- scitex/ai/utils/_check_params.py +50 -0
- scitex/ai/utils/_default_dataset.py +46 -0
- scitex/ai/utils/_format_samples_for_sktime.py +26 -0
- scitex/ai/utils/_label_encoder.py +134 -0
- scitex/ai/utils/_merge_labels.py +22 -0
- scitex/ai/utils/_sliding_window_data_augmentation.py +11 -0
- scitex/ai/utils/_under_sample.py +51 -0
- scitex/ai/utils/_verify_n_gpus.py +16 -0
- scitex/ai/utils/grid_search.py +148 -0
- scitex/context/__init__.py +9 -0
- scitex/context/_suppress_output.py +38 -0
- scitex/db/_BaseMixins/_BaseBackupMixin.py +30 -0
- scitex/db/_BaseMixins/_BaseBatchMixin.py +31 -0
- scitex/db/_BaseMixins/_BaseBlobMixin.py +81 -0
- scitex/db/_BaseMixins/_BaseConnectionMixin.py +43 -0
- scitex/db/_BaseMixins/_BaseImportExportMixin.py +39 -0
- scitex/db/_BaseMixins/_BaseIndexMixin.py +29 -0
- scitex/db/_BaseMixins/_BaseMaintenanceMixin.py +33 -0
- scitex/db/_BaseMixins/_BaseQueryMixin.py +52 -0
- scitex/db/_BaseMixins/_BaseRowMixin.py +32 -0
- scitex/db/_BaseMixins/_BaseSchemaMixin.py +44 -0
- scitex/db/_BaseMixins/_BaseTableMixin.py +66 -0
- scitex/db/_BaseMixins/_BaseTransactionMixin.py +52 -0
- scitex/db/_BaseMixins/__init__.py +30 -0
- scitex/db/_PostgreSQL.py +126 -0
- scitex/db/_PostgreSQLMixins/_BackupMixin.py +166 -0
- scitex/db/_PostgreSQLMixins/_BatchMixin.py +82 -0
- scitex/db/_PostgreSQLMixins/_BlobMixin.py +231 -0
- scitex/db/_PostgreSQLMixins/_ConnectionMixin.py +92 -0
- scitex/db/_PostgreSQLMixins/_ImportExportMixin.py +59 -0
- scitex/db/_PostgreSQLMixins/_IndexMixin.py +64 -0
- scitex/db/_PostgreSQLMixins/_MaintenanceMixin.py +175 -0
- scitex/db/_PostgreSQLMixins/_QueryMixin.py +108 -0
- scitex/db/_PostgreSQLMixins/_RowMixin.py +75 -0
- scitex/db/_PostgreSQLMixins/_SchemaMixin.py +126 -0
- scitex/db/_PostgreSQLMixins/_TableMixin.py +176 -0
- scitex/db/_PostgreSQLMixins/_TransactionMixin.py +57 -0
- scitex/db/_PostgreSQLMixins/__init__.py +34 -0
- scitex/db/_SQLite3.py +2136 -0
- scitex/db/_SQLite3Mixins/_BatchMixin.py +243 -0
- scitex/db/_SQLite3Mixins/_BlobMixin.py +229 -0
- scitex/db/_SQLite3Mixins/_ConnectionMixin.py +108 -0
- scitex/db/_SQLite3Mixins/_ImportExportMixin.py +80 -0
- scitex/db/_SQLite3Mixins/_IndexMixin.py +32 -0
- scitex/db/_SQLite3Mixins/_MaintenanceMixin.py +176 -0
- scitex/db/_SQLite3Mixins/_QueryMixin.py +83 -0
- scitex/db/_SQLite3Mixins/_RowMixin.py +75 -0
- scitex/db/_SQLite3Mixins/_TableMixin.py +183 -0
- scitex/db/_SQLite3Mixins/_TransactionMixin.py +71 -0
- scitex/db/_SQLite3Mixins/__init__.py +30 -0
- scitex/db/__init__.py +14 -0
- scitex/db/_delete_duplicates.py +397 -0
- scitex/db/_inspect.py +163 -0
- scitex/decorators/__init__.py +54 -0
- scitex/decorators/_auto_order.py +172 -0
- scitex/decorators/_batch_fn.py +127 -0
- scitex/decorators/_cache_disk.py +32 -0
- scitex/decorators/_cache_mem.py +12 -0
- scitex/decorators/_combined.py +98 -0
- scitex/decorators/_converters.py +282 -0
- scitex/decorators/_deprecated.py +26 -0
- scitex/decorators/_not_implemented.py +30 -0
- scitex/decorators/_numpy_fn.py +86 -0
- scitex/decorators/_pandas_fn.py +121 -0
- scitex/decorators/_preserve_doc.py +19 -0
- scitex/decorators/_signal_fn.py +95 -0
- scitex/decorators/_timeout.py +55 -0
- scitex/decorators/_torch_fn.py +136 -0
- scitex/decorators/_wrap.py +39 -0
- scitex/decorators/_xarray_fn.py +88 -0
- scitex/dev/__init__.py +15 -0
- scitex/dev/_analyze_code_flow.py +284 -0
- scitex/dev/_reload.py +59 -0
- scitex/dict/_DotDict.py +442 -0
- scitex/dict/__init__.py +18 -0
- scitex/dict/_listed_dict.py +42 -0
- scitex/dict/_pop_keys.py +36 -0
- scitex/dict/_replace.py +13 -0
- scitex/dict/_safe_merge.py +62 -0
- scitex/dict/_to_str.py +32 -0
- scitex/dsp/__init__.py +72 -0
- scitex/dsp/_crop.py +122 -0
- scitex/dsp/_demo_sig.py +331 -0
- scitex/dsp/_detect_ripples.py +212 -0
- scitex/dsp/_ensure_3d.py +18 -0
- scitex/dsp/_hilbert.py +78 -0
- scitex/dsp/_listen.py +702 -0
- scitex/dsp/_misc.py +30 -0
- scitex/dsp/_mne.py +32 -0
- scitex/dsp/_modulation_index.py +79 -0
- scitex/dsp/_pac.py +319 -0
- scitex/dsp/_psd.py +102 -0
- scitex/dsp/_resample.py +65 -0
- scitex/dsp/_time.py +36 -0
- scitex/dsp/_transform.py +68 -0
- scitex/dsp/_wavelet.py +212 -0
- scitex/dsp/add_noise.py +111 -0
- scitex/dsp/example.py +253 -0
- scitex/dsp/filt.py +155 -0
- scitex/dsp/norm.py +18 -0
- scitex/dsp/params.py +51 -0
- scitex/dsp/reference.py +43 -0
- scitex/dsp/template.py +25 -0
- scitex/dsp/utils/__init__.py +15 -0
- scitex/dsp/utils/_differential_bandpass_filters.py +120 -0
- scitex/dsp/utils/_ensure_3d.py +18 -0
- scitex/dsp/utils/_ensure_even_len.py +10 -0
- scitex/dsp/utils/_zero_pad.py +48 -0
- scitex/dsp/utils/filter.py +408 -0
- scitex/dsp/utils/pac.py +177 -0
- scitex/dt/__init__.py +8 -0
- scitex/dt/_linspace.py +130 -0
- scitex/etc/__init__.py +15 -0
- scitex/etc/wait_key.py +34 -0
- scitex/gen/_DimHandler.py +196 -0
- scitex/gen/_TimeStamper.py +244 -0
- scitex/gen/__init__.py +95 -0
- scitex/gen/_alternate_kwarg.py +13 -0
- scitex/gen/_cache.py +11 -0
- scitex/gen/_check_host.py +34 -0
- scitex/gen/_ci.py +12 -0
- scitex/gen/_close.py +222 -0
- scitex/gen/_embed.py +78 -0
- scitex/gen/_inspect_module.py +257 -0
- scitex/gen/_is_ipython.py +12 -0
- scitex/gen/_less.py +48 -0
- scitex/gen/_list_packages.py +139 -0
- scitex/gen/_mat2py.py +88 -0
- scitex/gen/_norm.py +170 -0
- scitex/gen/_paste.py +18 -0
- scitex/gen/_print_config.py +84 -0
- scitex/gen/_shell.py +48 -0
- scitex/gen/_src.py +111 -0
- scitex/gen/_start.py +451 -0
- scitex/gen/_symlink.py +55 -0
- scitex/gen/_symlog.py +27 -0
- scitex/gen/_tee.py +238 -0
- scitex/gen/_title2path.py +60 -0
- scitex/gen/_title_case.py +88 -0
- scitex/gen/_to_even.py +84 -0
- scitex/gen/_to_odd.py +34 -0
- scitex/gen/_to_rank.py +39 -0
- scitex/gen/_transpose.py +37 -0
- scitex/gen/_type.py +78 -0
- scitex/gen/_var_info.py +73 -0
- scitex/gen/_wrap.py +17 -0
- scitex/gen/_xml2dict.py +76 -0
- scitex/gen/misc.py +730 -0
- scitex/gen/path.py +0 -0
- scitex/general/__init__.py +5 -0
- scitex/gists/_SigMacro_processFigure_S.py +128 -0
- scitex/gists/_SigMacro_toBlue.py +172 -0
- scitex/gists/__init__.py +12 -0
- scitex/io/_H5Explorer.py +292 -0
- scitex/io/__init__.py +82 -0
- scitex/io/_cache.py +101 -0
- scitex/io/_flush.py +24 -0
- scitex/io/_glob.py +103 -0
- scitex/io/_json2md.py +113 -0
- scitex/io/_load.py +168 -0
- scitex/io/_load_configs.py +146 -0
- scitex/io/_load_modules/__init__.py +38 -0
- scitex/io/_load_modules/_catboost.py +66 -0
- scitex/io/_load_modules/_con.py +20 -0
- scitex/io/_load_modules/_db.py +24 -0
- scitex/io/_load_modules/_docx.py +42 -0
- scitex/io/_load_modules/_eeg.py +110 -0
- scitex/io/_load_modules/_hdf5.py +196 -0
- scitex/io/_load_modules/_image.py +19 -0
- scitex/io/_load_modules/_joblib.py +19 -0
- scitex/io/_load_modules/_json.py +18 -0
- scitex/io/_load_modules/_markdown.py +103 -0
- scitex/io/_load_modules/_matlab.py +37 -0
- scitex/io/_load_modules/_numpy.py +39 -0
- scitex/io/_load_modules/_optuna.py +155 -0
- scitex/io/_load_modules/_pandas.py +69 -0
- scitex/io/_load_modules/_pdf.py +31 -0
- scitex/io/_load_modules/_pickle.py +24 -0
- scitex/io/_load_modules/_torch.py +16 -0
- scitex/io/_load_modules/_txt.py +126 -0
- scitex/io/_load_modules/_xml.py +49 -0
- scitex/io/_load_modules/_yaml.py +23 -0
- scitex/io/_mv_to_tmp.py +19 -0
- scitex/io/_path.py +286 -0
- scitex/io/_reload.py +78 -0
- scitex/io/_save.py +539 -0
- scitex/io/_save_modules/__init__.py +66 -0
- scitex/io/_save_modules/_catboost.py +22 -0
- scitex/io/_save_modules/_csv.py +89 -0
- scitex/io/_save_modules/_excel.py +49 -0
- scitex/io/_save_modules/_hdf5.py +249 -0
- scitex/io/_save_modules/_html.py +48 -0
- scitex/io/_save_modules/_image.py +140 -0
- scitex/io/_save_modules/_joblib.py +25 -0
- scitex/io/_save_modules/_json.py +25 -0
- scitex/io/_save_modules/_listed_dfs_as_csv.py +57 -0
- scitex/io/_save_modules/_listed_scalars_as_csv.py +42 -0
- scitex/io/_save_modules/_matlab.py +24 -0
- scitex/io/_save_modules/_mp4.py +29 -0
- scitex/io/_save_modules/_numpy.py +57 -0
- scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +38 -0
- scitex/io/_save_modules/_pickle.py +45 -0
- scitex/io/_save_modules/_plotly.py +27 -0
- scitex/io/_save_modules/_text.py +23 -0
- scitex/io/_save_modules/_torch.py +26 -0
- scitex/io/_save_modules/_yaml.py +29 -0
- scitex/life/__init__.py +10 -0
- scitex/life/_monitor_rain.py +49 -0
- scitex/linalg/__init__.py +17 -0
- scitex/linalg/_distance.py +63 -0
- scitex/linalg/_geometric_median.py +64 -0
- scitex/linalg/_misc.py +73 -0
- scitex/nn/_AxiswiseDropout.py +27 -0
- scitex/nn/_BNet.py +126 -0
- scitex/nn/_BNet_Res.py +164 -0
- scitex/nn/_ChannelGainChanger.py +44 -0
- scitex/nn/_DropoutChannels.py +50 -0
- scitex/nn/_Filters.py +489 -0
- scitex/nn/_FreqGainChanger.py +110 -0
- scitex/nn/_GaussianFilter.py +48 -0
- scitex/nn/_Hilbert.py +111 -0
- scitex/nn/_MNet_1000.py +157 -0
- scitex/nn/_ModulationIndex.py +221 -0
- scitex/nn/_PAC.py +414 -0
- scitex/nn/_PSD.py +40 -0
- scitex/nn/_ResNet1D.py +120 -0
- scitex/nn/_SpatialAttention.py +25 -0
- scitex/nn/_Spectrogram.py +161 -0
- scitex/nn/_SwapChannels.py +50 -0
- scitex/nn/_TransposeLayer.py +19 -0
- scitex/nn/_Wavelet.py +183 -0
- scitex/nn/__init__.py +63 -0
- scitex/os/__init__.py +8 -0
- scitex/os/_mv.py +50 -0
- scitex/parallel/__init__.py +8 -0
- scitex/parallel/_run.py +151 -0
- scitex/path/__init__.py +33 -0
- scitex/path/_clean.py +52 -0
- scitex/path/_find.py +108 -0
- scitex/path/_get_module_path.py +51 -0
- scitex/path/_get_spath.py +35 -0
- scitex/path/_getsize.py +18 -0
- scitex/path/_increment_version.py +87 -0
- scitex/path/_mk_spath.py +51 -0
- scitex/path/_path.py +19 -0
- scitex/path/_split.py +23 -0
- scitex/path/_this_path.py +19 -0
- scitex/path/_version.py +101 -0
- scitex/pd/__init__.py +41 -0
- scitex/pd/_find_indi.py +126 -0
- scitex/pd/_find_pval.py +113 -0
- scitex/pd/_force_df.py +154 -0
- scitex/pd/_from_xyz.py +71 -0
- scitex/pd/_ignore_SettingWithCopyWarning.py +34 -0
- scitex/pd/_melt_cols.py +81 -0
- scitex/pd/_merge_columns.py +221 -0
- scitex/pd/_mv.py +63 -0
- scitex/pd/_replace.py +62 -0
- scitex/pd/_round.py +93 -0
- scitex/pd/_slice.py +63 -0
- scitex/pd/_sort.py +91 -0
- scitex/pd/_to_numeric.py +53 -0
- scitex/pd/_to_xy.py +59 -0
- scitex/pd/_to_xyz.py +110 -0
- scitex/plt/__init__.py +36 -0
- scitex/plt/_subplots/_AxesWrapper.py +182 -0
- scitex/plt/_subplots/_AxisWrapper.py +249 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +414 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +896 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +368 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_TrackingMixin.py +185 -0
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +16 -0
- scitex/plt/_subplots/_FigWrapper.py +226 -0
- scitex/plt/_subplots/_SubplotsWrapper.py +171 -0
- scitex/plt/_subplots/__init__.py +111 -0
- scitex/plt/_subplots/_export_as_csv.py +232 -0
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +61 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +90 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +49 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +46 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +39 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +125 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +72 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +34 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +36 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +79 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +59 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +32 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +79 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +75 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +64 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +44 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +70 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +66 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +95 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +67 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +52 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +46 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +46 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +46 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +46 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +44 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +103 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +82 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +58 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +117 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +30 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +51 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +93 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +94 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +92 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +65 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +59 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +58 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +45 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +70 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +75 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +75 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +155 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +64 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +77 -0
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +210 -0
- scitex/plt/_subplots/_export_as_csv_formatters/verify_formatters.py +342 -0
- scitex/plt/_subplots/_export_as_csv_formatters.py +115 -0
- scitex/plt/_tpl.py +28 -0
- scitex/plt/ax/__init__.py +114 -0
- scitex/plt/ax/_plot/__init__.py +53 -0
- scitex/plt/ax/_plot/_plot_circular_hist.py +124 -0
- scitex/plt/ax/_plot/_plot_conf_mat.py +136 -0
- scitex/plt/ax/_plot/_plot_cube.py +57 -0
- scitex/plt/ax/_plot/_plot_ecdf.py +84 -0
- scitex/plt/ax/_plot/_plot_fillv.py +55 -0
- scitex/plt/ax/_plot/_plot_heatmap.py +266 -0
- scitex/plt/ax/_plot/_plot_image.py +94 -0
- scitex/plt/ax/_plot/_plot_joyplot.py +76 -0
- scitex/plt/ax/_plot/_plot_raster.py +172 -0
- scitex/plt/ax/_plot/_plot_rectangle.py +69 -0
- scitex/plt/ax/_plot/_plot_scatter_hist.py +133 -0
- scitex/plt/ax/_plot/_plot_shaded_line.py +142 -0
- scitex/plt/ax/_plot/_plot_statistical_shaded_line.py +221 -0
- scitex/plt/ax/_plot/_plot_violin.py +343 -0
- scitex/plt/ax/_style/__init__.py +38 -0
- scitex/plt/ax/_style/_add_marginal_ax.py +44 -0
- scitex/plt/ax/_style/_add_panel.py +92 -0
- scitex/plt/ax/_style/_extend.py +64 -0
- scitex/plt/ax/_style/_force_aspect.py +37 -0
- scitex/plt/ax/_style/_format_label.py +23 -0
- scitex/plt/ax/_style/_hide_spines.py +84 -0
- scitex/plt/ax/_style/_map_ticks.py +182 -0
- scitex/plt/ax/_style/_rotate_labels.py +215 -0
- scitex/plt/ax/_style/_sci_note.py +279 -0
- scitex/plt/ax/_style/_set_log_scale.py +299 -0
- scitex/plt/ax/_style/_set_meta.py +261 -0
- scitex/plt/ax/_style/_set_n_ticks.py +37 -0
- scitex/plt/ax/_style/_set_size.py +16 -0
- scitex/plt/ax/_style/_set_supxyt.py +116 -0
- scitex/plt/ax/_style/_set_ticks.py +276 -0
- scitex/plt/ax/_style/_set_xyt.py +121 -0
- scitex/plt/ax/_style/_share_axes.py +264 -0
- scitex/plt/ax/_style/_shift.py +139 -0
- scitex/plt/ax/_style/_show_spines.py +333 -0
- scitex/plt/color/_PARAMS.py +70 -0
- scitex/plt/color/__init__.py +52 -0
- scitex/plt/color/_add_hue_col.py +41 -0
- scitex/plt/color/_colors.py +205 -0
- scitex/plt/color/_get_colors_from_cmap.py +134 -0
- scitex/plt/color/_interpolate.py +29 -0
- scitex/plt/color/_vizualize_colors.py +54 -0
- scitex/plt/utils/__init__.py +44 -0
- scitex/plt/utils/_calc_bacc_from_conf_mat.py +46 -0
- scitex/plt/utils/_calc_nice_ticks.py +101 -0
- scitex/plt/utils/_close.py +68 -0
- scitex/plt/utils/_colorbar.py +96 -0
- scitex/plt/utils/_configure_mpl.py +295 -0
- scitex/plt/utils/_histogram_utils.py +132 -0
- scitex/plt/utils/_im2grid.py +70 -0
- scitex/plt/utils/_is_valid_axis.py +78 -0
- scitex/plt/utils/_mk_colorbar.py +65 -0
- scitex/plt/utils/_mk_patches.py +26 -0
- scitex/plt/utils/_scientific_captions.py +638 -0
- scitex/plt/utils/_scitex_config.py +223 -0
- scitex/reproduce/__init__.py +14 -0
- scitex/reproduce/_fix_seeds.py +45 -0
- scitex/reproduce/_gen_ID.py +55 -0
- scitex/reproduce/_gen_timestamp.py +35 -0
- scitex/res/__init__.py +5 -0
- scitex/resource/__init__.py +13 -0
- scitex/resource/_get_processor_usages.py +281 -0
- scitex/resource/_get_specs.py +280 -0
- scitex/resource/_log_processor_usages.py +190 -0
- scitex/resource/_utils/__init__.py +31 -0
- scitex/resource/_utils/_get_env_info.py +481 -0
- scitex/resource/limit_ram.py +33 -0
- scitex/scholar/__init__.py +24 -0
- scitex/scholar/_local_search.py +454 -0
- scitex/scholar/_paper.py +244 -0
- scitex/scholar/_pdf_downloader.py +325 -0
- scitex/scholar/_search.py +393 -0
- scitex/scholar/_vector_search.py +370 -0
- scitex/scholar/_web_sources.py +457 -0
- scitex/stats/__init__.py +31 -0
- scitex/stats/_calc_partial_corr.py +17 -0
- scitex/stats/_corr_test_multi.py +94 -0
- scitex/stats/_corr_test_wrapper.py +115 -0
- scitex/stats/_describe_wrapper.py +90 -0
- scitex/stats/_multiple_corrections.py +63 -0
- scitex/stats/_nan_stats.py +93 -0
- scitex/stats/_p2stars.py +116 -0
- scitex/stats/_p2stars_wrapper.py +56 -0
- scitex/stats/_statistical_tests.py +73 -0
- scitex/stats/desc/__init__.py +40 -0
- scitex/stats/desc/_describe.py +189 -0
- scitex/stats/desc/_nan.py +289 -0
- scitex/stats/desc/_real.py +94 -0
- scitex/stats/multiple/__init__.py +14 -0
- scitex/stats/multiple/_bonferroni_correction.py +72 -0
- scitex/stats/multiple/_fdr_correction.py +400 -0
- scitex/stats/multiple/_multicompair.py +28 -0
- scitex/stats/tests/__corr_test.py +277 -0
- scitex/stats/tests/__corr_test_multi.py +343 -0
- scitex/stats/tests/__corr_test_single.py +277 -0
- scitex/stats/tests/__init__.py +22 -0
- scitex/stats/tests/_brunner_munzel_test.py +192 -0
- scitex/stats/tests/_nocorrelation_test.py +28 -0
- scitex/stats/tests/_smirnov_grubbs.py +98 -0
- scitex/str/__init__.py +113 -0
- scitex/str/_clean_path.py +75 -0
- scitex/str/_color_text.py +52 -0
- scitex/str/_decapitalize.py +58 -0
- scitex/str/_factor_out_digits.py +281 -0
- scitex/str/_format_plot_text.py +498 -0
- scitex/str/_grep.py +48 -0
- scitex/str/_latex.py +155 -0
- scitex/str/_latex_fallback.py +471 -0
- scitex/str/_mask_api.py +39 -0
- scitex/str/_mask_api_key.py +8 -0
- scitex/str/_parse.py +158 -0
- scitex/str/_print_block.py +47 -0
- scitex/str/_print_debug.py +68 -0
- scitex/str/_printc.py +62 -0
- scitex/str/_readable_bytes.py +38 -0
- scitex/str/_remove_ansi.py +23 -0
- scitex/str/_replace.py +134 -0
- scitex/str/_search.py +125 -0
- scitex/str/_squeeze_space.py +36 -0
- scitex/tex/__init__.py +10 -0
- scitex/tex/_preview.py +103 -0
- scitex/tex/_to_vec.py +116 -0
- scitex/torch/__init__.py +18 -0
- scitex/torch/_apply_to.py +34 -0
- scitex/torch/_nan_funcs.py +77 -0
- scitex/types/_ArrayLike.py +44 -0
- scitex/types/_ColorLike.py +21 -0
- scitex/types/__init__.py +14 -0
- scitex/types/_is_listed_X.py +70 -0
- scitex/utils/__init__.py +22 -0
- scitex/utils/_compress_hdf5.py +116 -0
- scitex/utils/_email.py +120 -0
- scitex/utils/_grid.py +148 -0
- scitex/utils/_notify.py +247 -0
- scitex/utils/_search.py +121 -0
- scitex/web/__init__.py +38 -0
- scitex/web/_search_pubmed.py +438 -0
- scitex/web/_summarize_url.py +158 -0
- scitex-2.0.0.dist-info/METADATA +307 -0
- scitex-2.0.0.dist-info/RECORD +572 -0
- scitex-2.0.0.dist-info/WHEEL +6 -0
- scitex-2.0.0.dist-info/licenses/LICENSE +7 -0
- scitex-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-02-27 22:15:18 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_dev/src/scitex/db/_PostgreSQLMixins/_MaintenanceMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_PostgreSQLMixins/_MaintenanceMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
import pandas as pd
|
|
11
|
+
import contextlib
|
|
12
|
+
from typing import ContextManager, Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
import psycopg2
|
|
15
|
+
|
|
16
|
+
from .._BaseMixins._BaseMaintenanceMixin import _BaseMaintenanceMixin
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _MaintenanceMixin(_BaseMaintenanceMixin):
|
|
20
|
+
@contextlib.contextmanager
|
|
21
|
+
def maintenance_lock(self) -> ContextManager[None]:
|
|
22
|
+
if not self._maintenance_lock.acquire(timeout=300):
|
|
23
|
+
raise TimeoutError("Could not acquire maintenance lock")
|
|
24
|
+
try:
|
|
25
|
+
yield
|
|
26
|
+
finally:
|
|
27
|
+
self._maintenance_lock.release()
|
|
28
|
+
|
|
29
|
+
def vacuum(self, table: Optional[str] = None, full: bool = False) -> None:
|
|
30
|
+
"""Execute VACUUM on the specified table or entire database"""
|
|
31
|
+
with self.maintenance_lock():
|
|
32
|
+
try:
|
|
33
|
+
self._check_writable()
|
|
34
|
+
query = "VACUUM"
|
|
35
|
+
if full:
|
|
36
|
+
query += " FULL"
|
|
37
|
+
if table:
|
|
38
|
+
query += f" {table}"
|
|
39
|
+
self.execute(query)
|
|
40
|
+
except psycopg2.Error as err:
|
|
41
|
+
raise ValueError(f"Vacuum operation failed: {err}")
|
|
42
|
+
|
|
43
|
+
def analyze(self, table: Optional[str] = None) -> None:
|
|
44
|
+
"""Update statistics for query optimization"""
|
|
45
|
+
with self.maintenance_lock():
|
|
46
|
+
try:
|
|
47
|
+
self._check_writable()
|
|
48
|
+
query = "ANALYZE"
|
|
49
|
+
if table:
|
|
50
|
+
query += f" {table}"
|
|
51
|
+
self.execute(query)
|
|
52
|
+
except psycopg2.Error as err:
|
|
53
|
+
raise ValueError(f"Analyze operation failed: {err}")
|
|
54
|
+
|
|
55
|
+
def reindex(self, table: Optional[str] = None) -> None:
|
|
56
|
+
"""Rebuild indexes"""
|
|
57
|
+
with self.maintenance_lock():
|
|
58
|
+
try:
|
|
59
|
+
self._check_writable()
|
|
60
|
+
if table:
|
|
61
|
+
self.execute(f"REINDEX TABLE {table}")
|
|
62
|
+
else:
|
|
63
|
+
self.execute("REINDEX DATABASE CURRENT_DATABASE()")
|
|
64
|
+
except psycopg2.Error as err:
|
|
65
|
+
raise ValueError(f"Reindex operation failed: {err}")
|
|
66
|
+
|
|
67
|
+
def get_table_size(self, table: str) -> str:
|
|
68
|
+
"""Get the size of a specific table"""
|
|
69
|
+
try:
|
|
70
|
+
query = """
|
|
71
|
+
SELECT pg_size_pretty(pg_total_relation_size(%s))
|
|
72
|
+
"""
|
|
73
|
+
self.execute(query, (table,))
|
|
74
|
+
return self.cursor.fetchone()[0]
|
|
75
|
+
except psycopg2.Error as err:
|
|
76
|
+
raise ValueError(f"Failed to get table size: {err}")
|
|
77
|
+
|
|
78
|
+
def get_database_size(self) -> str:
|
|
79
|
+
"""Get the size of the current database"""
|
|
80
|
+
try:
|
|
81
|
+
query = """
|
|
82
|
+
SELECT pg_size_pretty(pg_database_size(current_database()))
|
|
83
|
+
"""
|
|
84
|
+
self.execute(query)
|
|
85
|
+
return self.cursor.fetchone()[0]
|
|
86
|
+
except psycopg2.Error as err:
|
|
87
|
+
raise ValueError(f"Failed to get database size: {err}")
|
|
88
|
+
|
|
89
|
+
def get_table_info(self) -> List[Dict]:
|
|
90
|
+
"""Get information about all tables in the database"""
|
|
91
|
+
try:
|
|
92
|
+
query = """
|
|
93
|
+
SELECT
|
|
94
|
+
table_name,
|
|
95
|
+
pg_size_pretty(pg_total_relation_size(quote_ident(table_name))) as size,
|
|
96
|
+
(SELECT count(*) FROM information_schema.columns
|
|
97
|
+
WHERE table_name=tables.table_name) as columns,
|
|
98
|
+
(SELECT COUNT(*) FROM information_schema.table_constraints
|
|
99
|
+
WHERE table_name=tables.table_name AND constraint_type='PRIMARY KEY') as has_pk
|
|
100
|
+
FROM information_schema.tables
|
|
101
|
+
WHERE table_schema = 'public'
|
|
102
|
+
ORDER BY table_name;
|
|
103
|
+
"""
|
|
104
|
+
self.execute(query)
|
|
105
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
106
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
107
|
+
except psycopg2.Error as err:
|
|
108
|
+
raise ValueError(f"Failed to get table information: {err}")
|
|
109
|
+
|
|
110
|
+
def optimize(self, table: Optional[str] = None) -> None:
|
|
111
|
+
"""Perform full optimization on table or database"""
|
|
112
|
+
with self.maintenance_lock():
|
|
113
|
+
try:
|
|
114
|
+
self.vacuum(table, full=True)
|
|
115
|
+
self.analyze(table)
|
|
116
|
+
self.reindex(table)
|
|
117
|
+
except ValueError as err:
|
|
118
|
+
raise ValueError(f"Optimization failed: {err}")
|
|
119
|
+
|
|
120
|
+
def get_summaries(
|
|
121
|
+
self,
|
|
122
|
+
table_names: Optional[List[str]] = None,
|
|
123
|
+
verbose: bool = True,
|
|
124
|
+
limit: int = 5,
|
|
125
|
+
) -> Dict[str, pd.DataFrame]:
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
if table_names is None:
|
|
129
|
+
table_names = self.get_table_names()
|
|
130
|
+
if isinstance(table_names, str):
|
|
131
|
+
table_names = [table_names]
|
|
132
|
+
|
|
133
|
+
sample_tables = {}
|
|
134
|
+
for table_name in table_names:
|
|
135
|
+
query = f"""
|
|
136
|
+
SELECT *
|
|
137
|
+
FROM {table_name}
|
|
138
|
+
LIMIT {limit}
|
|
139
|
+
"""
|
|
140
|
+
self.execute(query)
|
|
141
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
142
|
+
rows = self.cursor.fetchall()
|
|
143
|
+
table_sample = pd.DataFrame(rows, columns=columns)
|
|
144
|
+
|
|
145
|
+
for column in table_sample.columns:
|
|
146
|
+
if table_sample[column].dtype == object:
|
|
147
|
+
try:
|
|
148
|
+
pd.to_datetime(
|
|
149
|
+
table_sample[column], format="mixed", errors="raise"
|
|
150
|
+
)
|
|
151
|
+
continue
|
|
152
|
+
except (ValueError, TypeError):
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
# try:
|
|
156
|
+
# pd.to_datetime(table_sample[column])
|
|
157
|
+
# continue
|
|
158
|
+
# except:
|
|
159
|
+
# pass
|
|
160
|
+
|
|
161
|
+
if (
|
|
162
|
+
table_sample[column]
|
|
163
|
+
.apply(lambda x: isinstance(x, str))
|
|
164
|
+
.all()
|
|
165
|
+
):
|
|
166
|
+
continue
|
|
167
|
+
|
|
168
|
+
sample_tables[table_name] = table_sample
|
|
169
|
+
|
|
170
|
+
return sample_tables
|
|
171
|
+
except psycopg2.Error as err:
|
|
172
|
+
raise ValueError(f"Failed to get summaries: {err}")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# EOF
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-02-27 22:15:24 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_dev/src/scitex/db/_PostgreSQLMixins/_QueryMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_PostgreSQLMixins/_QueryMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from typing import List, Dict, Any, Optional, Union, Tuple
|
|
11
|
+
from .._BaseMixins._BaseQueryMixin import _BaseQueryMixin
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _QueryMixin(_BaseQueryMixin):
|
|
15
|
+
def select(
|
|
16
|
+
self,
|
|
17
|
+
table: str,
|
|
18
|
+
columns: Optional[List[str]] = None,
|
|
19
|
+
where: Optional[str] = None,
|
|
20
|
+
params: Optional[tuple] = None,
|
|
21
|
+
order_by: Optional[str] = None,
|
|
22
|
+
limit: Optional[int] = None,
|
|
23
|
+
) -> List[Dict[str, Any]]:
|
|
24
|
+
"""Execute a SELECT query with optional conditions"""
|
|
25
|
+
cols_str = "*" if not columns else ", ".join(columns)
|
|
26
|
+
query = f"SELECT {cols_str} FROM {table}"
|
|
27
|
+
|
|
28
|
+
if where:
|
|
29
|
+
query += f" WHERE {where}"
|
|
30
|
+
if order_by:
|
|
31
|
+
query += f" ORDER BY {order_by}"
|
|
32
|
+
if limit:
|
|
33
|
+
query += f" LIMIT {limit}"
|
|
34
|
+
|
|
35
|
+
self.execute(query, params)
|
|
36
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
37
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
38
|
+
|
|
39
|
+
def insert(self, table: str, data: Dict[str, Any]) -> None:
|
|
40
|
+
"""Insert a single record into a table"""
|
|
41
|
+
self._check_writable()
|
|
42
|
+
columns = list(data.keys())
|
|
43
|
+
values = list(data.values())
|
|
44
|
+
placeholders = ["%s"] * len(values)
|
|
45
|
+
|
|
46
|
+
query = f"""
|
|
47
|
+
INSERT INTO {table}
|
|
48
|
+
({', '.join(columns)})
|
|
49
|
+
VALUES ({', '.join(placeholders)})
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
self.execute(query, tuple(values))
|
|
53
|
+
|
|
54
|
+
def update(
|
|
55
|
+
self,
|
|
56
|
+
table: str,
|
|
57
|
+
data: Dict[str, Any],
|
|
58
|
+
where: str,
|
|
59
|
+
params: Optional[tuple] = None,
|
|
60
|
+
) -> int:
|
|
61
|
+
"""Update records in a table"""
|
|
62
|
+
self._check_writable()
|
|
63
|
+
set_items = [f"{k} = %s" for k in data.keys()]
|
|
64
|
+
values = list(data.values())
|
|
65
|
+
|
|
66
|
+
query = f"""
|
|
67
|
+
UPDATE {table}
|
|
68
|
+
SET {', '.join(set_items)}
|
|
69
|
+
WHERE {where}
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
if params:
|
|
73
|
+
values.extend(params)
|
|
74
|
+
|
|
75
|
+
self.execute(query, tuple(values))
|
|
76
|
+
return self.cursor.rowcount
|
|
77
|
+
|
|
78
|
+
def delete(self, table: str, where: str, params: Optional[tuple] = None) -> int:
|
|
79
|
+
"""Delete records from a table"""
|
|
80
|
+
self._check_writable()
|
|
81
|
+
query = f"DELETE FROM {table} WHERE {where}"
|
|
82
|
+
self.execute(query, params)
|
|
83
|
+
return self.cursor.rowcount
|
|
84
|
+
|
|
85
|
+
def execute_query(
|
|
86
|
+
self, query: str, params: Optional[tuple] = None
|
|
87
|
+
) -> List[Dict[str, Any]]:
|
|
88
|
+
"""Execute a custom query and return results as dictionaries"""
|
|
89
|
+
self.execute(query, params)
|
|
90
|
+
|
|
91
|
+
if self.cursor.description: # If the query returns results
|
|
92
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
93
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
def count(
|
|
97
|
+
self, table: str, where: Optional[str] = None, params: Optional[tuple] = None
|
|
98
|
+
) -> int:
|
|
99
|
+
"""Count records in a table"""
|
|
100
|
+
query = f"SELECT COUNT(*) FROM {table}"
|
|
101
|
+
if where:
|
|
102
|
+
query += f" WHERE {where}"
|
|
103
|
+
|
|
104
|
+
self.execute(query, params)
|
|
105
|
+
return self.cursor.fetchone()[0]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# EOF
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-02-27 22:15:30 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_dev/src/scitex/db/_PostgreSQLMixins/_RowMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/db/_PostgreSQLMixins/_RowMixin.py"
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import psycopg2
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _RowMixin:
|
|
14
|
+
def get_rows(
|
|
15
|
+
self,
|
|
16
|
+
table_name: str,
|
|
17
|
+
columns: List[str] = None,
|
|
18
|
+
where: str = None,
|
|
19
|
+
order_by: str = None,
|
|
20
|
+
limit: Optional[int] = None,
|
|
21
|
+
offset: Optional[int] = None,
|
|
22
|
+
return_as: str = "dataframe",
|
|
23
|
+
):
|
|
24
|
+
try:
|
|
25
|
+
if columns is None:
|
|
26
|
+
columns_str = "*"
|
|
27
|
+
elif isinstance(columns, str):
|
|
28
|
+
columns_str = f'"{columns}"'
|
|
29
|
+
else:
|
|
30
|
+
columns_str = ", ".join(f'"{col}"' for col in columns)
|
|
31
|
+
|
|
32
|
+
query_parts = [f"SELECT {columns_str} FROM {table_name}"]
|
|
33
|
+
|
|
34
|
+
if where:
|
|
35
|
+
query_parts.append(f"WHERE {where}")
|
|
36
|
+
if order_by:
|
|
37
|
+
query_parts.append(f"ORDER BY {order_by}")
|
|
38
|
+
if limit is not None:
|
|
39
|
+
query_parts.append(f"LIMIT {limit}")
|
|
40
|
+
if offset is not None:
|
|
41
|
+
query_parts.append(f"OFFSET {offset}")
|
|
42
|
+
|
|
43
|
+
query = " ".join(query_parts)
|
|
44
|
+
self.cursor.execute(query)
|
|
45
|
+
|
|
46
|
+
column_names = [desc[0] for desc in self.cursor.description]
|
|
47
|
+
data = self.cursor.fetchall()
|
|
48
|
+
|
|
49
|
+
if return_as == "list":
|
|
50
|
+
return data
|
|
51
|
+
elif return_as == "dict":
|
|
52
|
+
return [dict(zip(column_names, row)) for row in data]
|
|
53
|
+
else:
|
|
54
|
+
return pd.DataFrame(data, columns=column_names)
|
|
55
|
+
|
|
56
|
+
except (Exception, psycopg2.Error) as err:
|
|
57
|
+
raise ValueError(f"Query execution failed: {err}")
|
|
58
|
+
|
|
59
|
+
def get_row_count(self, table_name: str = None, where: str = None) -> int:
|
|
60
|
+
try:
|
|
61
|
+
if table_name is None:
|
|
62
|
+
raise ValueError("Table name must be specified")
|
|
63
|
+
|
|
64
|
+
query = f"SELECT COUNT(*) FROM {table_name}"
|
|
65
|
+
if where:
|
|
66
|
+
query += f" WHERE {where}"
|
|
67
|
+
|
|
68
|
+
self.cursor.execute(query)
|
|
69
|
+
return self.cursor.fetchone()[0]
|
|
70
|
+
|
|
71
|
+
except (Exception, psycopg2.Error) as err:
|
|
72
|
+
raise ValueError(f"Failed to get row count: {err}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# EOF
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-02-27 22:14:23 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_dev/src/scitex/db/_PostgreSQLMixins/_SchemaMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_PostgreSQLMixins/_SchemaMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from typing import List, Dict, Any, Optional
|
|
11
|
+
from .._BaseMixins._BaseSchemaMixin import _BaseSchemaMixin
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _SchemaMixin(_BaseSchemaMixin):
|
|
15
|
+
def get_tables(self) -> List[str]:
|
|
16
|
+
"""Get all tables in the current database"""
|
|
17
|
+
query = """
|
|
18
|
+
SELECT table_name
|
|
19
|
+
FROM information_schema.tables
|
|
20
|
+
WHERE table_schema = 'public'
|
|
21
|
+
"""
|
|
22
|
+
self.execute(query)
|
|
23
|
+
return [row[0] for row in self.cursor.fetchall()]
|
|
24
|
+
|
|
25
|
+
def get_columns(self, table: str) -> List[Dict[str, Any]]:
|
|
26
|
+
"""Get detailed information about columns in a table"""
|
|
27
|
+
query = """
|
|
28
|
+
SELECT column_name, data_type, is_nullable, column_default
|
|
29
|
+
FROM information_schema.columns
|
|
30
|
+
WHERE table_schema = 'public' AND table_name = %s
|
|
31
|
+
ORDER BY ordinal_position
|
|
32
|
+
"""
|
|
33
|
+
self.execute(query, (table,))
|
|
34
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
35
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
36
|
+
|
|
37
|
+
def get_primary_keys(self, table: str) -> List[str]:
|
|
38
|
+
"""Get primary key columns for a table"""
|
|
39
|
+
query = """
|
|
40
|
+
SELECT a.attname
|
|
41
|
+
FROM pg_index i
|
|
42
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
43
|
+
WHERE i.indrelid = %s::regclass AND i.indisprimary
|
|
44
|
+
"""
|
|
45
|
+
self.execute(query, (table,))
|
|
46
|
+
return [row[0] for row in self.cursor.fetchall()]
|
|
47
|
+
|
|
48
|
+
def get_foreign_keys(self, table: str) -> List[Dict[str, Any]]:
|
|
49
|
+
"""Get foreign key constraints for a table"""
|
|
50
|
+
query = """
|
|
51
|
+
SELECT
|
|
52
|
+
kcu.column_name,
|
|
53
|
+
ccu.table_name AS foreign_table_name,
|
|
54
|
+
ccu.column_name AS foreign_column_name
|
|
55
|
+
FROM information_schema.table_constraints AS tc
|
|
56
|
+
JOIN information_schema.key_column_usage AS kcu
|
|
57
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
58
|
+
JOIN information_schema.constraint_column_usage AS ccu
|
|
59
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
60
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
61
|
+
AND tc.table_name = %s
|
|
62
|
+
"""
|
|
63
|
+
self.execute(query, (table,))
|
|
64
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
65
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
66
|
+
|
|
67
|
+
def get_indexes(self, table: str) -> List[Dict[str, Any]]:
|
|
68
|
+
"""Get all indexes for a table"""
|
|
69
|
+
query = """
|
|
70
|
+
SELECT
|
|
71
|
+
i.relname as index_name,
|
|
72
|
+
a.attname as column_name,
|
|
73
|
+
ix.indisunique as is_unique,
|
|
74
|
+
ix.indisprimary as is_primary
|
|
75
|
+
FROM pg_class t
|
|
76
|
+
JOIN pg_index ix ON t.oid = ix.indrelid
|
|
77
|
+
JOIN pg_class i ON i.oid = ix.indexrelid
|
|
78
|
+
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
|
|
79
|
+
WHERE t.relname = %s
|
|
80
|
+
"""
|
|
81
|
+
self.execute(query, (table,))
|
|
82
|
+
columns = [desc[0] for desc in self.cursor.description]
|
|
83
|
+
return [dict(zip(columns, row)) for row in self.cursor.fetchall()]
|
|
84
|
+
|
|
85
|
+
def table_exists(self, table: str) -> bool:
|
|
86
|
+
"""Check if a table exists"""
|
|
87
|
+
query = """
|
|
88
|
+
SELECT EXISTS (
|
|
89
|
+
SELECT FROM information_schema.tables
|
|
90
|
+
WHERE table_schema = 'public'
|
|
91
|
+
AND table_name = %s
|
|
92
|
+
)
|
|
93
|
+
"""
|
|
94
|
+
self.execute(query, (table,))
|
|
95
|
+
return self.cursor.fetchone()[0]
|
|
96
|
+
|
|
97
|
+
def column_exists(self, table: str, column: str) -> bool:
|
|
98
|
+
"""Check if a column exists in a table"""
|
|
99
|
+
query = """
|
|
100
|
+
SELECT EXISTS (
|
|
101
|
+
SELECT FROM information_schema.columns
|
|
102
|
+
WHERE table_schema = 'public'
|
|
103
|
+
AND table_name = %s
|
|
104
|
+
AND column_name = %s
|
|
105
|
+
)
|
|
106
|
+
"""
|
|
107
|
+
self.execute(query, (table, column))
|
|
108
|
+
return self.cursor.fetchone()[0]
|
|
109
|
+
|
|
110
|
+
def create_index(
|
|
111
|
+
self, table: str, columns: List[str], index_name: Optional[str] = None
|
|
112
|
+
) -> None:
|
|
113
|
+
"""Create an index on specified columns"""
|
|
114
|
+
self._check_writable()
|
|
115
|
+
if not index_name:
|
|
116
|
+
index_name = f"idx_{table}_{'_'.join(columns)}"
|
|
117
|
+
columns_str = ", ".join(columns)
|
|
118
|
+
self.execute(f"CREATE INDEX {index_name} ON {table} ({columns_str})")
|
|
119
|
+
|
|
120
|
+
def drop_index(self, index_name: str) -> None:
|
|
121
|
+
"""Drop an index"""
|
|
122
|
+
self._check_writable()
|
|
123
|
+
self.execute(f"DROP INDEX IF EXISTS {index_name}")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# EOF
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-02-27 22:15:38 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_dev/src/scitex/db/_PostgreSQLMixins/_TableMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_PostgreSQLMixins/_TableMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from typing import Any, Dict, List, Union
|
|
11
|
+
import psycopg2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _TableMixin:
|
|
15
|
+
def create_table(
|
|
16
|
+
self,
|
|
17
|
+
table_name: str,
|
|
18
|
+
columns: Dict[str, str],
|
|
19
|
+
foreign_keys: List[Dict[str, str]] = None,
|
|
20
|
+
if_not_exists: bool = True,
|
|
21
|
+
) -> None:
|
|
22
|
+
try:
|
|
23
|
+
exists_clause = "IF NOT EXISTS" if if_not_exists else ""
|
|
24
|
+
columns_def = [
|
|
25
|
+
f"{col_name} {col_type}" for col_name, col_type in columns.items()
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
if foreign_keys:
|
|
29
|
+
for fk in foreign_keys:
|
|
30
|
+
columns_def.append(
|
|
31
|
+
f"FOREIGN KEY ({fk['column']}) REFERENCES {fk['references']}({fk['referenced_column']})"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
columns_str = ", ".join(columns_def)
|
|
35
|
+
query = f"CREATE TABLE {exists_clause} {table_name} ({columns_str})"
|
|
36
|
+
self.execute(query)
|
|
37
|
+
|
|
38
|
+
except (Exception, psycopg2.Error) as err:
|
|
39
|
+
raise ValueError(f"Failed to create table: {err}")
|
|
40
|
+
|
|
41
|
+
def drop_table(self, table_name: str, if_exists: bool = True) -> None:
|
|
42
|
+
try:
|
|
43
|
+
exists_clause = "IF EXISTS" if if_exists else ""
|
|
44
|
+
self.execute(f"DROP TABLE {exists_clause} {table_name}")
|
|
45
|
+
|
|
46
|
+
except (Exception, psycopg2.Error) as err:
|
|
47
|
+
raise ValueError(f"Failed to drop table: {err}")
|
|
48
|
+
|
|
49
|
+
def rename_table(self, old_name: str, new_name: str) -> None:
|
|
50
|
+
try:
|
|
51
|
+
self.execute(f"ALTER TABLE {old_name} RENAME TO {new_name}")
|
|
52
|
+
|
|
53
|
+
except (Exception, psycopg2.Error) as err:
|
|
54
|
+
raise ValueError(f"Failed to rename table: {err}")
|
|
55
|
+
|
|
56
|
+
def add_columns(
|
|
57
|
+
self,
|
|
58
|
+
table_name: str,
|
|
59
|
+
columns: Dict[str, str],
|
|
60
|
+
default_values: Dict[str, Any] = None,
|
|
61
|
+
) -> None:
|
|
62
|
+
try:
|
|
63
|
+
for col_name, col_type in columns.items():
|
|
64
|
+
default_value = default_values.get(col_name) if default_values else None
|
|
65
|
+
default_clause = (
|
|
66
|
+
f" DEFAULT {default_value}" if default_value is not None else ""
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
self.execute(
|
|
70
|
+
f"ALTER TABLE {table_name} ADD COLUMN {col_name} {col_type}{default_clause}"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
except (Exception, psycopg2.Error) as err:
|
|
74
|
+
raise ValueError(f"Failed to add columns: {err}")
|
|
75
|
+
|
|
76
|
+
def add_column(
|
|
77
|
+
self,
|
|
78
|
+
table_name: str,
|
|
79
|
+
column_name: str,
|
|
80
|
+
column_type: str,
|
|
81
|
+
default_value: Any = None,
|
|
82
|
+
) -> None:
|
|
83
|
+
try:
|
|
84
|
+
default_clause = (
|
|
85
|
+
f" DEFAULT {default_value}" if default_value is not None else ""
|
|
86
|
+
)
|
|
87
|
+
self.execute(
|
|
88
|
+
f"ALTER TABLE {table_name} ADD COLUMN {column_name} {column_type}{default_clause}"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
except (Exception, psycopg2.Error) as err:
|
|
92
|
+
raise ValueError(f"Failed to add column: {err}")
|
|
93
|
+
|
|
94
|
+
def drop_columns(
|
|
95
|
+
self, table_name: str, columns: Union[str, List[str]], if_exists: bool = True
|
|
96
|
+
) -> None:
|
|
97
|
+
try:
|
|
98
|
+
if isinstance(columns, str):
|
|
99
|
+
columns = [columns]
|
|
100
|
+
|
|
101
|
+
exists_clause = "IF EXISTS" if if_exists else ""
|
|
102
|
+
for column in columns:
|
|
103
|
+
self.execute(
|
|
104
|
+
f"ALTER TABLE {table_name} DROP COLUMN {exists_clause} {column}"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
except (Exception, psycopg2.Error) as err:
|
|
108
|
+
raise ValueError(f"Failed to drop columns: {err}")
|
|
109
|
+
|
|
110
|
+
def get_table_names(self) -> List[str]:
|
|
111
|
+
try:
|
|
112
|
+
query = """
|
|
113
|
+
SELECT table_name
|
|
114
|
+
FROM information_schema.tables
|
|
115
|
+
WHERE table_schema = 'public'
|
|
116
|
+
"""
|
|
117
|
+
self.cursor.execute(query)
|
|
118
|
+
return [row[0] for row in self.cursor.fetchall()]
|
|
119
|
+
|
|
120
|
+
except (Exception, psycopg2.Error) as err:
|
|
121
|
+
raise ValueError(f"Failed to get table names: {err}")
|
|
122
|
+
|
|
123
|
+
def get_table_schema(self, table_name: str):
|
|
124
|
+
try:
|
|
125
|
+
query = f"""
|
|
126
|
+
SELECT column_name, data_type, is_nullable
|
|
127
|
+
FROM information_schema.columns
|
|
128
|
+
WHERE table_name = '{table_name}'
|
|
129
|
+
"""
|
|
130
|
+
return self.execute(query).fetchall()
|
|
131
|
+
|
|
132
|
+
except (Exception, psycopg2.Error) as err:
|
|
133
|
+
raise ValueError(f"Failed to get table schema: {err}")
|
|
134
|
+
|
|
135
|
+
def get_primary_key(self, table_name: str) -> str:
|
|
136
|
+
try:
|
|
137
|
+
query = f"""
|
|
138
|
+
SELECT a.attname
|
|
139
|
+
FROM pg_index i
|
|
140
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid
|
|
141
|
+
AND a.attnum = ANY(i.indkey)
|
|
142
|
+
WHERE i.indrelid = '{table_name}'::regclass
|
|
143
|
+
AND i.indisprimary
|
|
144
|
+
"""
|
|
145
|
+
result = self.execute(query).fetchone()
|
|
146
|
+
return result[0] if result else None
|
|
147
|
+
|
|
148
|
+
except (Exception, psycopg2.Error) as err:
|
|
149
|
+
raise ValueError(f"Failed to get primary key: {err}")
|
|
150
|
+
|
|
151
|
+
def get_table_stats(self, table_name: str) -> Dict[str, int]:
|
|
152
|
+
try:
|
|
153
|
+
stats = {}
|
|
154
|
+
stats["row_count"] = self.get_row_count(table_name)
|
|
155
|
+
|
|
156
|
+
size_query = f"""
|
|
157
|
+
SELECT pg_total_relation_size('{table_name}') as total_size,
|
|
158
|
+
pg_table_size('{table_name}') as table_size,
|
|
159
|
+
pg_indexes_size('{table_name}') as index_size
|
|
160
|
+
"""
|
|
161
|
+
size_result = self.execute(size_query).fetchone()
|
|
162
|
+
|
|
163
|
+
stats.update(
|
|
164
|
+
{
|
|
165
|
+
"total_size": size_result[0],
|
|
166
|
+
"table_size": size_result[1],
|
|
167
|
+
"index_size": size_result[2],
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
return stats
|
|
171
|
+
|
|
172
|
+
except (Exception, psycopg2.Error) as err:
|
|
173
|
+
raise ValueError(f"Failed to get table stats: {err}")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# EOF
|