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,243 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-11-29 04:36:14 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/db/_SQLite3Mixins/_BatchMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/db/_SQLite3Mixins/_BatchMixin.py"
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Functionality:
|
|
10
|
+
* Provides batch database operations for SQLite3
|
|
11
|
+
* Handles batch inserts, updates, replacements with transaction safety
|
|
12
|
+
* Supports foreign key inheritance and where clause filtering
|
|
13
|
+
|
|
14
|
+
Input:
|
|
15
|
+
* Table name, row data as dictionaries, and operation parameters
|
|
16
|
+
* Support for batch size control and conditional operations
|
|
17
|
+
|
|
18
|
+
Output:
|
|
19
|
+
* None, but executes database operations with transaction safety
|
|
20
|
+
|
|
21
|
+
Prerequisites:
|
|
22
|
+
* SQLite3 database connection
|
|
23
|
+
* Table schema must exist
|
|
24
|
+
* Foreign key constraints must be enabled if using inherit_foreign
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from typing import Any as _Any
|
|
28
|
+
from typing import Dict, List, Optional
|
|
29
|
+
from .._BaseMixins._BaseBatchMixin import _BaseBatchMixin
|
|
30
|
+
import sqlite3
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _BatchMixin:
|
|
34
|
+
"""Batch operations functionality"""
|
|
35
|
+
|
|
36
|
+
def _run_many(
|
|
37
|
+
self,
|
|
38
|
+
sql_command,
|
|
39
|
+
table_name: str,
|
|
40
|
+
rows: List[Dict[str, _Any]],
|
|
41
|
+
batch_size: int = 1000,
|
|
42
|
+
inherit_foreign: bool = True,
|
|
43
|
+
where: Optional[str] = None,
|
|
44
|
+
columns: Optional[List[str]] = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
try:
|
|
47
|
+
if batch_size <= 0:
|
|
48
|
+
raise ValueError("Batch size must be positive")
|
|
49
|
+
|
|
50
|
+
table_name = f'"{table_name.replace("`", "``")}"'
|
|
51
|
+
|
|
52
|
+
# Validate table exists and get schema
|
|
53
|
+
schema = self.get_table_schema(table_name)
|
|
54
|
+
table_columns = set(schema["name"])
|
|
55
|
+
|
|
56
|
+
# Replace the problematic code block with:
|
|
57
|
+
if columns:
|
|
58
|
+
valid_columns = [
|
|
59
|
+
col
|
|
60
|
+
for col in columns
|
|
61
|
+
if col in table_columns and col.isidentifier()
|
|
62
|
+
]
|
|
63
|
+
else:
|
|
64
|
+
valid_columns = [
|
|
65
|
+
col
|
|
66
|
+
for col in rows[0].keys()
|
|
67
|
+
if col in table_columns and col.isidentifier()
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
if not valid_columns:
|
|
71
|
+
raise ValueError("No valid columns found")
|
|
72
|
+
|
|
73
|
+
if not table_name or not isinstance(table_name, str):
|
|
74
|
+
raise ValueError("Invalid table name")
|
|
75
|
+
if not isinstance(rows, list):
|
|
76
|
+
raise ValueError("Rows must be a list of dictionaries")
|
|
77
|
+
if rows and not all(isinstance(row, dict) for row in rows):
|
|
78
|
+
raise ValueError("All rows must be dictionaries")
|
|
79
|
+
|
|
80
|
+
# Validate table exists
|
|
81
|
+
self.execute(f"SELECT 1 FROM {table_name} LIMIT 1")
|
|
82
|
+
|
|
83
|
+
assert sql_command.upper() in [
|
|
84
|
+
"INSERT",
|
|
85
|
+
"REPLACE",
|
|
86
|
+
"INSERT OR REPLACE",
|
|
87
|
+
"UPDATE",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
if not rows:
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
if sql_command.upper() == "UPDATE":
|
|
94
|
+
valid_columns = columns if columns else [col for col in rows[0].keys()]
|
|
95
|
+
set_clause = ",".join([f"{col}=?" for col in valid_columns])
|
|
96
|
+
where_clause = where if where else "1=1"
|
|
97
|
+
|
|
98
|
+
# Modified query construction
|
|
99
|
+
query = f"UPDATE {table_name} SET {set_clause} WHERE {where_clause}"
|
|
100
|
+
params = []
|
|
101
|
+
|
|
102
|
+
for row in rows:
|
|
103
|
+
row_params = [row[col] for col in valid_columns]
|
|
104
|
+
if where:
|
|
105
|
+
# Add any parameters needed for WHERE clause
|
|
106
|
+
row_params.extend(
|
|
107
|
+
[row[col] for col in where.split() if col in row]
|
|
108
|
+
)
|
|
109
|
+
params.append(tuple(row_params))
|
|
110
|
+
|
|
111
|
+
self.executemany(query, params)
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
if where:
|
|
115
|
+
filtered_rows = []
|
|
116
|
+
for row in rows:
|
|
117
|
+
try:
|
|
118
|
+
test_query = f"SELECT 1 FROM (SELECT {','.join('? as ' + k for k in row.keys())}) WHERE {where}"
|
|
119
|
+
values = tuple(row.values())
|
|
120
|
+
result = self.execute(test_query, values).fetchone()
|
|
121
|
+
if result:
|
|
122
|
+
filtered_rows.append(row)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"Warning: Where clause evaluation failed for row: {e}")
|
|
125
|
+
rows = filtered_rows
|
|
126
|
+
schema = self.get_table_schema(table_name)
|
|
127
|
+
table_columns = set(schema["name"])
|
|
128
|
+
valid_columns = [col for col in rows[0].keys()]
|
|
129
|
+
|
|
130
|
+
if inherit_foreign:
|
|
131
|
+
fk_query = f"PRAGMA foreign_key_list({table_name})"
|
|
132
|
+
foreign_keys = self.execute(fk_query).fetchall()
|
|
133
|
+
|
|
134
|
+
for row in rows:
|
|
135
|
+
for fk in foreign_keys:
|
|
136
|
+
ref_table, from_col, to_col = fk[2], fk[3], fk[4]
|
|
137
|
+
if from_col not in row or row[from_col] is None:
|
|
138
|
+
if to_col in row:
|
|
139
|
+
query = f"SELECT {from_col} FROM {ref_table} WHERE {to_col} = ?"
|
|
140
|
+
result = self.execute(query, (row[to_col],)).fetchone()
|
|
141
|
+
if result:
|
|
142
|
+
row[from_col] = result[0]
|
|
143
|
+
|
|
144
|
+
columns = valid_columns
|
|
145
|
+
placeholders = ",".join(["?" for _ in columns])
|
|
146
|
+
query = f"{sql_command} INTO {table_name} ({','.join(columns)}) VALUES ({placeholders})"
|
|
147
|
+
|
|
148
|
+
for idx in range(0, len(rows), batch_size):
|
|
149
|
+
batch = rows[idx : idx + batch_size]
|
|
150
|
+
values = [[row.get(col) for col in valid_columns] for row in batch]
|
|
151
|
+
self.executemany(query, values)
|
|
152
|
+
|
|
153
|
+
except sqlite3.Error as e:
|
|
154
|
+
self.rollback()
|
|
155
|
+
raise ValueError(f"Batch operation failed: {e}")
|
|
156
|
+
|
|
157
|
+
def update_many(
|
|
158
|
+
self,
|
|
159
|
+
table_name: str,
|
|
160
|
+
rows: List[Dict[str, _Any]],
|
|
161
|
+
batch_size: int = 1000,
|
|
162
|
+
where: Optional[str] = None,
|
|
163
|
+
columns: Optional[List[str]] = None,
|
|
164
|
+
) -> None:
|
|
165
|
+
with self.transaction():
|
|
166
|
+
self._run_many(
|
|
167
|
+
sql_command="UPDATE",
|
|
168
|
+
table_name=table_name,
|
|
169
|
+
rows=rows,
|
|
170
|
+
batch_size=batch_size,
|
|
171
|
+
inherit_foreign=False,
|
|
172
|
+
where=where,
|
|
173
|
+
columns=columns,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
def insert_many(
|
|
177
|
+
self,
|
|
178
|
+
table_name: str,
|
|
179
|
+
rows: List[Dict[str, _Any]],
|
|
180
|
+
batch_size: int = 1000,
|
|
181
|
+
inherit_foreign: bool = True,
|
|
182
|
+
where: Optional[str] = None,
|
|
183
|
+
) -> None:
|
|
184
|
+
with self.transaction():
|
|
185
|
+
self._run_many(
|
|
186
|
+
sql_command="INSERT",
|
|
187
|
+
table_name=table_name,
|
|
188
|
+
rows=rows,
|
|
189
|
+
batch_size=batch_size,
|
|
190
|
+
inherit_foreign=inherit_foreign,
|
|
191
|
+
where=where,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def replace_many(
|
|
195
|
+
self,
|
|
196
|
+
table_name: str,
|
|
197
|
+
rows: List[Dict[str, _Any]],
|
|
198
|
+
batch_size: int = 1000,
|
|
199
|
+
inherit_foreign: bool = True,
|
|
200
|
+
where: Optional[str] = None,
|
|
201
|
+
) -> None:
|
|
202
|
+
with self.transaction():
|
|
203
|
+
self._run_many(
|
|
204
|
+
sql_command="REPLACE",
|
|
205
|
+
table_name=table_name,
|
|
206
|
+
rows=rows,
|
|
207
|
+
batch_size=batch_size,
|
|
208
|
+
inherit_foreign=inherit_foreign,
|
|
209
|
+
where=where,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
def delete_where(
|
|
213
|
+
self, table_name: str, where: str, limit: Optional[int] = None
|
|
214
|
+
) -> None:
|
|
215
|
+
with self.transaction():
|
|
216
|
+
if not where or not isinstance(where, str):
|
|
217
|
+
raise ValueError("Invalid where clause")
|
|
218
|
+
params = []
|
|
219
|
+
query = f"DELETE FROM {table_name} WHERE {where}"
|
|
220
|
+
if limit is not None:
|
|
221
|
+
if not isinstance(limit, int) or limit <= 0:
|
|
222
|
+
raise ValueError("Limit must be a positive integer")
|
|
223
|
+
query += f" LIMIT {limit}"
|
|
224
|
+
self.execute(query, params)
|
|
225
|
+
|
|
226
|
+
def update_where(
|
|
227
|
+
self,
|
|
228
|
+
table_name: str,
|
|
229
|
+
updates: Dict[str, _Any],
|
|
230
|
+
where: str,
|
|
231
|
+
limit: Optional[int] = None,
|
|
232
|
+
) -> None:
|
|
233
|
+
with self.transaction():
|
|
234
|
+
if not updates:
|
|
235
|
+
raise ValueError("Updates dictionary cannot be empty")
|
|
236
|
+
set_clause = ", ".join([f"{col} = ?" for col in updates.keys()])
|
|
237
|
+
query = f"UPDATE {table_name} SET {set_clause} WHERE {where}"
|
|
238
|
+
if limit is not None:
|
|
239
|
+
query += f" LIMIT {limit}"
|
|
240
|
+
self.execute(query, tuple(updates.values()))
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# EOF
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-12-01 05:13:49 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/db/_SQLite3Mixins/_BlobMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/db/_SQLite3Mixins/_BlobMixin.py"
|
|
7
|
+
|
|
8
|
+
import sqlite3
|
|
9
|
+
from typing import Any as _Any
|
|
10
|
+
from typing import Dict, List, Optional, Tuple, Union
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from .._BaseMixins._BaseBlobMixin import _BaseBlobMixin
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _BlobMixin:
|
|
17
|
+
"""BLOB data handling functionality"""
|
|
18
|
+
|
|
19
|
+
def save_array(
|
|
20
|
+
self,
|
|
21
|
+
table_name: str,
|
|
22
|
+
data: np.ndarray,
|
|
23
|
+
column: str = "data",
|
|
24
|
+
ids: Optional[Union[int, List[int]]] = None,
|
|
25
|
+
where: str = None,
|
|
26
|
+
additional_columns: Dict[str, _Any] = None,
|
|
27
|
+
batch_size: int = 1000,
|
|
28
|
+
) -> None:
|
|
29
|
+
with self.lock:
|
|
30
|
+
if not isinstance(data, (np.ndarray, list)):
|
|
31
|
+
raise ValueError("Input must be a NumPy array or list of arrays")
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
if ids is not None:
|
|
35
|
+
if isinstance(ids, int):
|
|
36
|
+
ids = [ids]
|
|
37
|
+
data = [data]
|
|
38
|
+
if len(ids) != len(data):
|
|
39
|
+
raise ValueError("Length of ids must match number of arrays")
|
|
40
|
+
|
|
41
|
+
for id_, arr in zip(ids, data):
|
|
42
|
+
if not isinstance(arr, np.ndarray):
|
|
43
|
+
raise ValueError(
|
|
44
|
+
f"Element for id {id_} must be a NumPy array"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
binary = arr.tobytes()
|
|
48
|
+
columns = [
|
|
49
|
+
column,
|
|
50
|
+
f"{column}_dtype",
|
|
51
|
+
f"{column}_shape",
|
|
52
|
+
]
|
|
53
|
+
values = [binary, str(arr.dtype), str(arr.shape)]
|
|
54
|
+
|
|
55
|
+
if additional_columns:
|
|
56
|
+
columns = list(additional_columns.keys()) + columns
|
|
57
|
+
values = list(additional_columns.values()) + values
|
|
58
|
+
|
|
59
|
+
update_cols = [f"{col}=?" for col in columns]
|
|
60
|
+
query = f"UPDATE {table_name} SET {','.join(update_cols)} WHERE id=?"
|
|
61
|
+
values.append(id_)
|
|
62
|
+
self.execute(query, tuple(values))
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
if not isinstance(data, np.ndarray):
|
|
66
|
+
raise ValueError("Single input must be a NumPy array")
|
|
67
|
+
|
|
68
|
+
binary = data.tobytes()
|
|
69
|
+
columns = [column, f"{column}_dtype", f"{column}_shape"]
|
|
70
|
+
values = [binary, str(data.dtype), str(data.shape)]
|
|
71
|
+
|
|
72
|
+
if additional_columns:
|
|
73
|
+
columns = list(additional_columns.keys()) + columns
|
|
74
|
+
values = list(additional_columns.values()) + values
|
|
75
|
+
|
|
76
|
+
if where is not None:
|
|
77
|
+
update_cols = [f"{col}=?" for col in columns]
|
|
78
|
+
query = f"UPDATE {table_name} SET {','.join(update_cols)} WHERE {where}"
|
|
79
|
+
self.execute(query, tuple(values))
|
|
80
|
+
else:
|
|
81
|
+
placeholders = ",".join(["?" for _ in columns])
|
|
82
|
+
columns_str = ",".join(columns)
|
|
83
|
+
query = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
|
|
84
|
+
self.execute(query, tuple(values))
|
|
85
|
+
|
|
86
|
+
except Exception as err:
|
|
87
|
+
raise ValueError(f"Failed to save array: {err}")
|
|
88
|
+
|
|
89
|
+
def load_array(
|
|
90
|
+
self,
|
|
91
|
+
table_name: str,
|
|
92
|
+
column: str,
|
|
93
|
+
ids: Union[int, List[int], str] = "all",
|
|
94
|
+
where: str = None,
|
|
95
|
+
order_by: str = None,
|
|
96
|
+
batch_size: int = 128,
|
|
97
|
+
dtype: np.dtype = None,
|
|
98
|
+
shape: Optional[Tuple] = None,
|
|
99
|
+
) -> Optional[np.ndarray]:
|
|
100
|
+
try:
|
|
101
|
+
if ids == "all":
|
|
102
|
+
query = f"SELECT id FROM {table_name}"
|
|
103
|
+
if where:
|
|
104
|
+
query += f" WHERE {where}"
|
|
105
|
+
self.cursor.execute(query)
|
|
106
|
+
ids = [row[0] for row in self.cursor.fetchall()]
|
|
107
|
+
elif isinstance(ids, int):
|
|
108
|
+
ids = [ids]
|
|
109
|
+
|
|
110
|
+
id_to_data = {}
|
|
111
|
+
unique_ids = list(set(ids))
|
|
112
|
+
|
|
113
|
+
for idx in range(0, len(unique_ids), batch_size):
|
|
114
|
+
batch_ids = unique_ids[idx : idx + batch_size]
|
|
115
|
+
placeholders = ",".join("?" for _ in batch_ids)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
query = f"""
|
|
119
|
+
SELECT id, {column},
|
|
120
|
+
{column}_dtype,
|
|
121
|
+
{column}_shape
|
|
122
|
+
FROM {table_name}
|
|
123
|
+
WHERE id IN ({placeholders})
|
|
124
|
+
"""
|
|
125
|
+
self.cursor.execute(query, tuple(batch_ids))
|
|
126
|
+
has_metadata = True
|
|
127
|
+
except sqlite3.OperationalError:
|
|
128
|
+
query = f"SELECT id, {column} FROM {table_name} WHERE id IN ({placeholders})"
|
|
129
|
+
self.cursor.execute(query, tuple(batch_ids))
|
|
130
|
+
has_metadata = False
|
|
131
|
+
|
|
132
|
+
if where:
|
|
133
|
+
query += f" AND {where}"
|
|
134
|
+
if order_by:
|
|
135
|
+
query += f" ORDER BY {order_by}"
|
|
136
|
+
|
|
137
|
+
results = self.cursor.fetchall()
|
|
138
|
+
if results:
|
|
139
|
+
for result in results:
|
|
140
|
+
if has_metadata:
|
|
141
|
+
id_val, blob, dtype_str, shape_str = result
|
|
142
|
+
data = np.frombuffer(
|
|
143
|
+
blob, dtype=np.dtype(dtype_str)
|
|
144
|
+
).reshape(eval(shape_str))
|
|
145
|
+
else:
|
|
146
|
+
id_val, blob = result
|
|
147
|
+
data = (
|
|
148
|
+
np.frombuffer(blob, dtype=dtype)
|
|
149
|
+
if dtype
|
|
150
|
+
else np.frombuffer(blob)
|
|
151
|
+
)
|
|
152
|
+
if shape:
|
|
153
|
+
data = data.reshape(shape)
|
|
154
|
+
id_to_data[id_val] = data
|
|
155
|
+
|
|
156
|
+
all_data = [id_to_data[id_val] for id_val in ids if id_val in id_to_data]
|
|
157
|
+
return np.stack(all_data, axis=0) if all_data else None
|
|
158
|
+
|
|
159
|
+
except Exception as err:
|
|
160
|
+
raise ValueError(f"Failed to load array: {err}")
|
|
161
|
+
|
|
162
|
+
def binary_to_array(
|
|
163
|
+
self,
|
|
164
|
+
binary_data,
|
|
165
|
+
dtype_str=None,
|
|
166
|
+
shape_str=None,
|
|
167
|
+
dtype=None,
|
|
168
|
+
shape=None,
|
|
169
|
+
):
|
|
170
|
+
if binary_data is None:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
if dtype_str and shape_str:
|
|
174
|
+
return np.frombuffer(binary_data, dtype=np.dtype(dtype_str)).reshape(
|
|
175
|
+
eval(shape_str)
|
|
176
|
+
)
|
|
177
|
+
elif dtype and shape:
|
|
178
|
+
return np.frombuffer(binary_data, dtype=dtype).reshape(shape)
|
|
179
|
+
return binary_data
|
|
180
|
+
|
|
181
|
+
def get_array_dict(self, df, columns=None, dtype=None, shape=None):
|
|
182
|
+
result = {}
|
|
183
|
+
if columns is None:
|
|
184
|
+
columns = [
|
|
185
|
+
col
|
|
186
|
+
for col in df.columns
|
|
187
|
+
if not (col.endswith("_dtype") or col.endswith("_shape"))
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
for col in columns:
|
|
191
|
+
if f"{col}_dtype" in df.columns and f"{col}_shape" in df.columns:
|
|
192
|
+
arrays = [
|
|
193
|
+
self.binary_to_array(
|
|
194
|
+
row[col], row[f"{col}_dtype"], row[f"{col}_shape"]
|
|
195
|
+
)
|
|
196
|
+
for _, row in df.iterrows()
|
|
197
|
+
]
|
|
198
|
+
elif dtype and shape:
|
|
199
|
+
arrays = [
|
|
200
|
+
self.binary_to_array(x, dtype=dtype, shape=shape) for x in df[col]
|
|
201
|
+
]
|
|
202
|
+
result[col] = np.stack(arrays)
|
|
203
|
+
|
|
204
|
+
return result
|
|
205
|
+
|
|
206
|
+
def decode_array_columns(self, df, columns=None, dtype=None, shape=None):
|
|
207
|
+
if columns is None:
|
|
208
|
+
columns = [
|
|
209
|
+
col
|
|
210
|
+
for col in df.columns
|
|
211
|
+
if not (col.endswith("_dtype") or col.endswith("_shape"))
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
for col in columns:
|
|
215
|
+
if f"{col}_dtype" in df.columns and f"{col}_shape" in df.columns:
|
|
216
|
+
df[col] = df.apply(
|
|
217
|
+
lambda row: self.binary_to_array(
|
|
218
|
+
row[col], row[f"{col}_dtype"], row[f"{col}_shape"]
|
|
219
|
+
),
|
|
220
|
+
axis=1,
|
|
221
|
+
)
|
|
222
|
+
elif dtype and shape:
|
|
223
|
+
df[col] = df[col].apply(
|
|
224
|
+
lambda x: self.binary_to_array(x, dtype=dtype, shape=shape)
|
|
225
|
+
)
|
|
226
|
+
return df
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# EOF
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-11-29 04:33:58 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/db/_SQLite3Mixins/_ConnectionMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_SQLite3Mixins/_ConnectionMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
1. Functionality:
|
|
12
|
+
- Manages SQLite database connections with thread-safe operations
|
|
13
|
+
- Handles database journal files and transaction states
|
|
14
|
+
2. Input:
|
|
15
|
+
- Database file path
|
|
16
|
+
3. Output:
|
|
17
|
+
- Managed SQLite connection and cursor objects
|
|
18
|
+
4. Prerequisites:
|
|
19
|
+
- sqlite3
|
|
20
|
+
- threading
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import sqlite3
|
|
24
|
+
import threading
|
|
25
|
+
from typing import Optional
|
|
26
|
+
import os
|
|
27
|
+
import shutil
|
|
28
|
+
import tempfile
|
|
29
|
+
from .._BaseMixins._BaseConnectionMixin import _BaseConnectionMixin
|
|
30
|
+
import contextlib
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _ConnectionMixin:
|
|
34
|
+
"""Connection management functionality"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, db_path: str, use_temp_db: bool = False):
|
|
37
|
+
self.lock = threading.Lock()
|
|
38
|
+
self._maintenance_lock = threading.Lock()
|
|
39
|
+
self.db_path = db_path
|
|
40
|
+
self.conn = None
|
|
41
|
+
self.cursor = None
|
|
42
|
+
self.temp_path = None # Initialize temp_path attribute
|
|
43
|
+
if db_path:
|
|
44
|
+
self.connect(db_path, use_temp_db)
|
|
45
|
+
|
|
46
|
+
def __enter__(self):
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
50
|
+
self.close()
|
|
51
|
+
|
|
52
|
+
def _create_temp_copy(self, db_path: str) -> str:
|
|
53
|
+
"""Creates temporary copy of database."""
|
|
54
|
+
temp_dir = tempfile.gettempdir()
|
|
55
|
+
self.temp_path = os.path.join(temp_dir, f"temp_{os.path.basename(db_path)}")
|
|
56
|
+
shutil.copy2(db_path, self.temp_path)
|
|
57
|
+
return self.temp_path
|
|
58
|
+
|
|
59
|
+
def connect(self, db_path: str, use_temp_db: bool = False) -> None:
|
|
60
|
+
if self.conn:
|
|
61
|
+
self.close()
|
|
62
|
+
|
|
63
|
+
path_to_connect = self._create_temp_copy(db_path) if use_temp_db else db_path
|
|
64
|
+
|
|
65
|
+
self.conn = sqlite3.connect(path_to_connect, timeout=60.0)
|
|
66
|
+
self.cursor = self.conn.cursor()
|
|
67
|
+
|
|
68
|
+
with self.lock:
|
|
69
|
+
# WAL mode settings
|
|
70
|
+
self.cursor.execute("PRAGMA journal_mode = WAL")
|
|
71
|
+
self.cursor.execute("PRAGMA synchronous = NORMAL")
|
|
72
|
+
self.cursor.execute("PRAGMA busy_timeout = 60000")
|
|
73
|
+
self.cursor.execute("PRAGMA mmap_size = 30000000000")
|
|
74
|
+
self.cursor.execute("PRAGMA temp_store = MEMORY")
|
|
75
|
+
self.cursor.execute("PRAGMA cache_size = -2000")
|
|
76
|
+
self.conn.commit()
|
|
77
|
+
|
|
78
|
+
def close(self) -> None:
|
|
79
|
+
if self.cursor:
|
|
80
|
+
self.cursor.close()
|
|
81
|
+
if self.conn:
|
|
82
|
+
try:
|
|
83
|
+
self.conn.rollback()
|
|
84
|
+
self.conn.close()
|
|
85
|
+
except sqlite3.Error:
|
|
86
|
+
pass
|
|
87
|
+
self.cursor = None
|
|
88
|
+
self.conn = None
|
|
89
|
+
|
|
90
|
+
if (
|
|
91
|
+
hasattr(self, "temp_path")
|
|
92
|
+
and self.temp_path
|
|
93
|
+
and os.path.exists(self.temp_path)
|
|
94
|
+
):
|
|
95
|
+
try:
|
|
96
|
+
os.remove(self.temp_path)
|
|
97
|
+
self.temp_path = None
|
|
98
|
+
except OSError:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
def reconnect(self, use_temp_db: bool = False) -> None:
|
|
102
|
+
if self.db_path:
|
|
103
|
+
self.connect(self.db_path, use_temp_db)
|
|
104
|
+
else:
|
|
105
|
+
raise ValueError("No database path specified for reconnection")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# EOF
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-11-25 01:36:18 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/db/_SQLite3Mixins/_ImportExportMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = (
|
|
7
|
+
"/home/ywatanabe/proj/scitex_repo/src/scitex/db/_SQLite3Mixins/_ImportExportMixin.py"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from typing import List
|
|
11
|
+
|
|
12
|
+
import pandas as pd
|
|
13
|
+
|
|
14
|
+
from .._BaseMixins._BaseImportExportMixin import _BaseImportExportMixin
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _ImportExportMixin:
|
|
18
|
+
"""Import/Export functionality"""
|
|
19
|
+
|
|
20
|
+
def load_from_csv(
|
|
21
|
+
self,
|
|
22
|
+
table_name: str,
|
|
23
|
+
csv_path: str,
|
|
24
|
+
if_exists: str = "append",
|
|
25
|
+
batch_size: int = 10_000,
|
|
26
|
+
chunk_size: int = 100_000,
|
|
27
|
+
) -> None:
|
|
28
|
+
with self.transaction():
|
|
29
|
+
try:
|
|
30
|
+
for chunk in pd.read_csv(csv_path, chunksize=chunk_size):
|
|
31
|
+
chunk.to_sql(
|
|
32
|
+
table_name,
|
|
33
|
+
self.conn,
|
|
34
|
+
if_exists=if_exists,
|
|
35
|
+
index=False,
|
|
36
|
+
chunksize=batch_size,
|
|
37
|
+
)
|
|
38
|
+
if_exists = "append"
|
|
39
|
+
except FileNotFoundError:
|
|
40
|
+
raise FileNotFoundError(f"CSV file not found: {csv_path}")
|
|
41
|
+
except Exception as err:
|
|
42
|
+
raise ValueError(f"Failed to import from CSV: {err}")
|
|
43
|
+
|
|
44
|
+
def save_to_csv(
|
|
45
|
+
self,
|
|
46
|
+
table_name: str,
|
|
47
|
+
output_path: str,
|
|
48
|
+
columns: List[str] = ["*"],
|
|
49
|
+
where: str = None,
|
|
50
|
+
batch_size: int = 10_000,
|
|
51
|
+
) -> None:
|
|
52
|
+
try:
|
|
53
|
+
df = self.get_rows(
|
|
54
|
+
columns=columns,
|
|
55
|
+
table_name=table_name,
|
|
56
|
+
where=where,
|
|
57
|
+
limit=batch_size,
|
|
58
|
+
offset=0,
|
|
59
|
+
)
|
|
60
|
+
df.to_csv(output_path, index=False, mode="w")
|
|
61
|
+
|
|
62
|
+
offset = batch_size
|
|
63
|
+
while len(df) == batch_size:
|
|
64
|
+
df = self.get_rows(
|
|
65
|
+
columns=columns,
|
|
66
|
+
table_name=table_name,
|
|
67
|
+
where=where,
|
|
68
|
+
limit=batch_size,
|
|
69
|
+
offset=offset,
|
|
70
|
+
)
|
|
71
|
+
if len(df) > 0:
|
|
72
|
+
df.to_csv(output_path, index=False, mode="a", header=False)
|
|
73
|
+
offset += batch_size
|
|
74
|
+
except PermissionError:
|
|
75
|
+
raise PermissionError(f"Cannot write to: {output_path}")
|
|
76
|
+
except Exception as err:
|
|
77
|
+
raise ValueError(f"Failed to export to CSV: {err}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# EOF
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-11-25 01:36:45 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/db/_SQLite3Mixins/_IndexMixin.py
|
|
5
|
+
|
|
6
|
+
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/db/_SQLite3Mixins/_IndexMixin.py"
|
|
7
|
+
|
|
8
|
+
from typing import List
|
|
9
|
+
from .._BaseMixins._BaseIndexMixin import _BaseIndexMixin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _IndexMixin:
|
|
13
|
+
"""Index management functionality"""
|
|
14
|
+
|
|
15
|
+
def create_index(
|
|
16
|
+
self,
|
|
17
|
+
table_name: str,
|
|
18
|
+
column_names: List[str],
|
|
19
|
+
index_name: str = None,
|
|
20
|
+
unique: bool = False,
|
|
21
|
+
) -> None:
|
|
22
|
+
if index_name is None:
|
|
23
|
+
index_name = f"idx_{table_name}_{'_'.join(column_names)}"
|
|
24
|
+
unique_clause = "UNIQUE" if unique else ""
|
|
25
|
+
query = f"CREATE {unique_clause} INDEX IF NOT EXISTS {index_name} ON {table_name} ({','.join(column_names)})"
|
|
26
|
+
self.execute(query)
|
|
27
|
+
|
|
28
|
+
def drop_index(self, index_name: str) -> None:
|
|
29
|
+
self.execute(f"DROP INDEX IF EXISTS {index_name}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# EOF
|