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
scitex/dsp/_listen.py
ADDED
|
@@ -0,0 +1,702 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Time-stamp: "2024-11-08 09:15:59 (ywatanabe)"
|
|
4
|
+
# File: ./scitex_repo/src/scitex/dsp/_listen.py
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import sounddevice as sd
|
|
11
|
+
|
|
12
|
+
os.environ["PULSE_SERVER"] = "unix:/mnt/wslg/PulseServer"
|
|
13
|
+
|
|
14
|
+
# # WSL2 Sound Support
|
|
15
|
+
# export PULSE_SERVER=unix:/mnt/wslg/PulseServer
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def list_and_select_device() -> int:
|
|
19
|
+
"""
|
|
20
|
+
List available audio devices and prompt user to select one.
|
|
21
|
+
|
|
22
|
+
Example
|
|
23
|
+
-------
|
|
24
|
+
>>> device_id = list_and_select_device()
|
|
25
|
+
Available audio devices:
|
|
26
|
+
...
|
|
27
|
+
Enter the ID of the device you want to use:
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
int
|
|
32
|
+
Selected device ID
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
print("Available audio devices:")
|
|
36
|
+
devices = sd.query_devices()
|
|
37
|
+
print(devices)
|
|
38
|
+
device_id = int(input("Enter the ID of the device you want to use: "))
|
|
39
|
+
if device_id not in range(len(devices)):
|
|
40
|
+
raise ValueError(f"Invalid device ID: {device_id}")
|
|
41
|
+
return device_id
|
|
42
|
+
except (ValueError, sd.PortAudioError) as err:
|
|
43
|
+
print(f"Error during device selection: {err}")
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
import scitex
|
|
49
|
+
|
|
50
|
+
CONFIG, sys.stdout, sys.stderr, plt, CC = scitex.gen.start(sys, plt)
|
|
51
|
+
|
|
52
|
+
signal, time_points, sampling_freq = scitex.dsp.demo_sig("chirp")
|
|
53
|
+
|
|
54
|
+
device_id = list_and_select_device()
|
|
55
|
+
sd.default.device = device_id
|
|
56
|
+
|
|
57
|
+
listen(signal, sampling_freq)
|
|
58
|
+
|
|
59
|
+
scitex.gen.close(CONFIG)
|
|
60
|
+
|
|
61
|
+
# def play_audio(
|
|
62
|
+
# samples: np.ndarray, fs: int = 44100, channels: int = 1
|
|
63
|
+
# ) -> None:
|
|
64
|
+
# """Play audio using PyAudio"""
|
|
65
|
+
# print("Initializing PyAudio...")
|
|
66
|
+
# p = pyaudio.PyAudio()
|
|
67
|
+
|
|
68
|
+
# # List available devices
|
|
69
|
+
# print("\nAvailable audio devices:")
|
|
70
|
+
# for i in range(p.get_device_count()):
|
|
71
|
+
# dev = p.get_device_info_by_index(i)
|
|
72
|
+
# print(f"Device {i}: {dev['name']}")
|
|
73
|
+
|
|
74
|
+
# try:
|
|
75
|
+
# # Rest of the code remains the same
|
|
76
|
+
# if samples.dtype != np.float32:
|
|
77
|
+
# print(f"Converting from {samples.dtype} to float32...")
|
|
78
|
+
# samples = samples.astype(np.float32)
|
|
79
|
+
|
|
80
|
+
# if len(samples) == 0:
|
|
81
|
+
# print("No input samples, creating test tone...")
|
|
82
|
+
# duration = 1
|
|
83
|
+
# t = np.linspace(0, duration, int(fs * duration))
|
|
84
|
+
# samples = np.sin(2 * np.pi * 440 * t)
|
|
85
|
+
|
|
86
|
+
# print(f"Opening audio stream (fs={fs}Hz, channels={channels})...")
|
|
87
|
+
# stream = p.open(
|
|
88
|
+
# format=pyaudio.paFloat32, channels=channels, rate=fs, output=True
|
|
89
|
+
# )
|
|
90
|
+
|
|
91
|
+
# print("Playing audio...")
|
|
92
|
+
# stream.write(samples.tobytes())
|
|
93
|
+
|
|
94
|
+
# except Exception as e:
|
|
95
|
+
# print(f"Error: {e}")
|
|
96
|
+
# finally:
|
|
97
|
+
# print("Cleaning up...")
|
|
98
|
+
# if "stream" in locals():
|
|
99
|
+
# stream.stop_stream()
|
|
100
|
+
# stream.close()
|
|
101
|
+
# p.terminate()
|
|
102
|
+
# print("Done.")
|
|
103
|
+
|
|
104
|
+
# if __name__ == "__main__":
|
|
105
|
+
# # Test with a simple sine wave
|
|
106
|
+
# duration = 2
|
|
107
|
+
# fs = 44100
|
|
108
|
+
# t = np.linspace(0, duration, int(fs * duration))
|
|
109
|
+
# test_signal = np.sin(2 * np.pi * 440 * t) # 440 Hz
|
|
110
|
+
# play_audio(test_signal, fs)
|
|
111
|
+
|
|
112
|
+
# # def record_audio(
|
|
113
|
+
# # duration: float = 5.0, fs: int = 44100, channels: int = 1
|
|
114
|
+
# # ) -> np.ndarray:
|
|
115
|
+
# # """Record audio using PyAudio with WSL2 compatibility"""
|
|
116
|
+
# # chunk = 1024
|
|
117
|
+
# # format = pyaudio.paFloat32
|
|
118
|
+
|
|
119
|
+
# # p = pyaudio.PyAudio()
|
|
120
|
+
|
|
121
|
+
# # # List available devices
|
|
122
|
+
# # for i in range(p.get_device_count()):
|
|
123
|
+
# # print(p.get_device_info_by_index(i))
|
|
124
|
+
|
|
125
|
+
# # try:
|
|
126
|
+
# # stream = p.open(
|
|
127
|
+
# # format=format,
|
|
128
|
+
# # channels=channels,
|
|
129
|
+
# # rate=fs,
|
|
130
|
+
# # input=True,
|
|
131
|
+
# # frames_per_buffer=chunk,
|
|
132
|
+
# # input_device_index=None, # Use default device
|
|
133
|
+
# # )
|
|
134
|
+
|
|
135
|
+
# # frames = []
|
|
136
|
+
# # print("Recording...")
|
|
137
|
+
|
|
138
|
+
# # for _ in range(0, int(fs / chunk * duration)):
|
|
139
|
+
# # data = stream.read(chunk)
|
|
140
|
+
# # frames.append(data)
|
|
141
|
+
|
|
142
|
+
# # print("Done recording")
|
|
143
|
+
# # return np.frombuffer(b"".join(frames), dtype=np.float32)
|
|
144
|
+
|
|
145
|
+
# # finally:
|
|
146
|
+
# # if "stream" in locals():
|
|
147
|
+
# # stream.stop_stream()
|
|
148
|
+
# # stream.close()
|
|
149
|
+
# # p.terminate()
|
|
150
|
+
|
|
151
|
+
# # def record_audio(
|
|
152
|
+
# # duration: float = 5.0, fs: int = 44100, channels: int = 1
|
|
153
|
+
# # ) -> np.ndarray:
|
|
154
|
+
# # """
|
|
155
|
+
# # Record audio using PyAudio.
|
|
156
|
+
# # """
|
|
157
|
+
# # chunk = 1024
|
|
158
|
+
# # format = pyaudio.paFloat32
|
|
159
|
+
|
|
160
|
+
# # p = pyaudio.PyAudio()
|
|
161
|
+
|
|
162
|
+
# # stream = p.open(
|
|
163
|
+
# # format=format,
|
|
164
|
+
# # channels=channels,
|
|
165
|
+
# # rate=fs,
|
|
166
|
+
# # input=True,
|
|
167
|
+
# # frames_per_buffer=chunk,
|
|
168
|
+
# # )
|
|
169
|
+
|
|
170
|
+
# # frames = []
|
|
171
|
+
|
|
172
|
+
# # for _ in range(0, int(fs / chunk * duration)):
|
|
173
|
+
# # data = stream.read(chunk)
|
|
174
|
+
# # frames.append(data)
|
|
175
|
+
|
|
176
|
+
# # stream.stop_stream()
|
|
177
|
+
# # stream.close()
|
|
178
|
+
# # p.terminate()
|
|
179
|
+
|
|
180
|
+
# # return np.frombuffer(b"".join(frames), dtype=np.float32)
|
|
181
|
+
|
|
182
|
+
# # if __name__ == "__main__":
|
|
183
|
+
# # # Test recording
|
|
184
|
+
# # audio = record_audio(duration=3.0)
|
|
185
|
+
# # print(f"Recorded {len(audio)} samples")
|
|
186
|
+
|
|
187
|
+
# # # #!/usr/bin/env python3
|
|
188
|
+
# # # # -*- coding: utf-8 -*-
|
|
189
|
+
# # # # Time-stamp: "2024-11-08 08:56:12 (ywatanabe)"
|
|
190
|
+
# # # # File: ./scitex_repo/src/scitex/dsp/_listen.py
|
|
191
|
+
|
|
192
|
+
# # # import os
|
|
193
|
+
# # # import sys
|
|
194
|
+
# # # from typing import Any, Dict, Literal, Tuple
|
|
195
|
+
|
|
196
|
+
# # # import matplotlib.pyplot as plt
|
|
197
|
+
# # # import scitex
|
|
198
|
+
# # # import numpy as np
|
|
199
|
+
# # # from scipy.signal import resample
|
|
200
|
+
|
|
201
|
+
# # # os.environ["DISPLAY"] = ":0" # Set a default display
|
|
202
|
+
|
|
203
|
+
# # # # Avoid GUI/clipboard dependencies
|
|
204
|
+
# # # def dummy_clipboard_get():
|
|
205
|
+
# # # raise NotImplementedError(
|
|
206
|
+
# # # "Clipboard not available in headless environment"
|
|
207
|
+
# # # )
|
|
208
|
+
|
|
209
|
+
# # # try:
|
|
210
|
+
# # # from IPython import get_ipython
|
|
211
|
+
|
|
212
|
+
# # # ipython = get_ipython()
|
|
213
|
+
# # # if ipython is not None:
|
|
214
|
+
# # # ipython.hooks.clipboard_get = dummy_clipboard_get
|
|
215
|
+
# # # except ImportError:
|
|
216
|
+
# # # pass
|
|
217
|
+
|
|
218
|
+
# # # """
|
|
219
|
+
# # # Functionality:
|
|
220
|
+
# # # - Provides audio playback and signal sonification functionality
|
|
221
|
+
# # # - Supports multiple sonification methods (frequency shift, AM/FM Modulation)
|
|
222
|
+
# # # - Includes device selection and audio information display utilities
|
|
223
|
+
# # # Input:
|
|
224
|
+
# # # - Multichannel signal arrays (numpy.ndarray)
|
|
225
|
+
# # # - Sampling frequency and sonification parameters
|
|
226
|
+
# # # Output:
|
|
227
|
+
# # # - Audio playback through specified output device
|
|
228
|
+
# # # Prerequisites:
|
|
229
|
+
# # # - PortAudio library (install with: sudo apt-get install portaudio19-dev)
|
|
230
|
+
# # # - sounddevice package
|
|
231
|
+
# # # """
|
|
232
|
+
|
|
233
|
+
# # # """Imports"""
|
|
234
|
+
# # # """Config"""
|
|
235
|
+
# # # CONFIG = scitex.gen.load_configs()
|
|
236
|
+
|
|
237
|
+
# # # """Functions"""
|
|
238
|
+
|
|
239
|
+
# # # def frequency_shift(
|
|
240
|
+
# # # signal: np.ndarray,
|
|
241
|
+
# # # shift_factor: int = 200,
|
|
242
|
+
# # # ) -> np.ndarray:
|
|
243
|
+
# # # """
|
|
244
|
+
# # # Shift signal frequencies by resampling.
|
|
245
|
+
|
|
246
|
+
# # # Example
|
|
247
|
+
# # # -------
|
|
248
|
+
# # # >>> signal = np.sin(2 * np.pi * 10 * np.linspace(0, 1, 1000))
|
|
249
|
+
# # # >>> shifted = frequency_shift(signal, shift_factor=200)
|
|
250
|
+
|
|
251
|
+
# # # Parameters
|
|
252
|
+
# # # ----------
|
|
253
|
+
# # # signal : np.ndarray
|
|
254
|
+
# # # Input signal to be frequency shifted
|
|
255
|
+
# # # shift_factor : int
|
|
256
|
+
# # # Frequency multiplication factor
|
|
257
|
+
|
|
258
|
+
# # # Returns
|
|
259
|
+
# # # -------
|
|
260
|
+
# # # np.ndarray
|
|
261
|
+
# # # Frequency shifted signal
|
|
262
|
+
# # # """
|
|
263
|
+
# # # num_samples = int(len(signal) * shift_factor)
|
|
264
|
+
# # # return resample(signal, num_samples)
|
|
265
|
+
|
|
266
|
+
# # # def am_Modulation(
|
|
267
|
+
# # # signal: np.ndarray, carrier_freq: float = 440, fs: int = 44_100
|
|
268
|
+
# # # ) -> np.ndarray:
|
|
269
|
+
# # # """
|
|
270
|
+
# # # Perform amplitude Modulation on input signal.
|
|
271
|
+
|
|
272
|
+
# # # Example
|
|
273
|
+
# # # -------
|
|
274
|
+
# # # >>> signal = np.sin(2 * np.pi * 10 * np.linspace(0, 1, 1000))
|
|
275
|
+
# # # >>> modulated = am_Modulation(signal, carrier_freq=440, fs=44100)
|
|
276
|
+
|
|
277
|
+
# # # Parameters
|
|
278
|
+
# # # ----------
|
|
279
|
+
# # # signal : np.ndarray
|
|
280
|
+
# # # Input signal to modulate
|
|
281
|
+
# # # carrier_freq : float
|
|
282
|
+
# # # Carrier frequency in Hz
|
|
283
|
+
# # # fs : int
|
|
284
|
+
# # # Sampling frequency in Hz
|
|
285
|
+
|
|
286
|
+
# # # Returns
|
|
287
|
+
# # # -------
|
|
288
|
+
# # # np.ndarray
|
|
289
|
+
# # # Amplitude modulated signal
|
|
290
|
+
# # # """
|
|
291
|
+
# # # t = np.arange(len(signal)) / fs
|
|
292
|
+
# # # carrier = np.sin(2 * np.pi * carrier_freq * t)
|
|
293
|
+
# # # return (1 + signal) * carrier
|
|
294
|
+
|
|
295
|
+
# # # def fm_Modulation(
|
|
296
|
+
# # # signal: np.ndarray,
|
|
297
|
+
# # # carrier_freq: float = 440,
|
|
298
|
+
# # # sensitivity: float = 0.5,
|
|
299
|
+
# # # fs: int = 44_100,
|
|
300
|
+
# # # ) -> np.ndarray:
|
|
301
|
+
# # # """
|
|
302
|
+
# # # Perform frequency Modulation on input signal.
|
|
303
|
+
|
|
304
|
+
# # # Example
|
|
305
|
+
# # # -------
|
|
306
|
+
# # # >>> signal = np.sin(2 * np.pi * 10 * np.linspace(0, 1, 1000))
|
|
307
|
+
# # # >>> modulated = fm_Modulation(signal, carrier_freq=440, sensitivity=0.5, fs=44100)
|
|
308
|
+
|
|
309
|
+
# # # Parameters
|
|
310
|
+
# # # ----------
|
|
311
|
+
# # # signal : np.ndarray
|
|
312
|
+
# # # Input signal to modulate
|
|
313
|
+
# # # carrier_freq : float
|
|
314
|
+
# # # Carrier frequency in Hz
|
|
315
|
+
# # # sensitivity : float
|
|
316
|
+
# # # Frequency sensitivity factor
|
|
317
|
+
# # # fs : int
|
|
318
|
+
# # # Sampling frequency in Hz
|
|
319
|
+
|
|
320
|
+
# # # Returns
|
|
321
|
+
# # # -------
|
|
322
|
+
# # # np.ndarray
|
|
323
|
+
# # # Frequency modulated signal
|
|
324
|
+
# # # """
|
|
325
|
+
# # # t = np.arange(len(signal)) / fs
|
|
326
|
+
# # # phase = 2 * np.pi * carrier_freq * t + sensitivity * np.cumsum(signal) / fs
|
|
327
|
+
# # # return np.sin(phase)
|
|
328
|
+
|
|
329
|
+
# # # def sonify_eeg(
|
|
330
|
+
# # # signal_array: np.ndarray,
|
|
331
|
+
# # # sampling_freq: int,
|
|
332
|
+
# # # method: Literal["shift", "am", "fm"] = "shift",
|
|
333
|
+
# # # channels: Tuple[int, ...] = (0, 1),
|
|
334
|
+
# # # target_fs: int = 44_100,
|
|
335
|
+
# # # **kwargs: Dict[str, Any],
|
|
336
|
+
# # # ) -> None:
|
|
337
|
+
# # # """
|
|
338
|
+
# # # Convert EEG signal to audio using various sonification methods.
|
|
339
|
+
|
|
340
|
+
# # # Example
|
|
341
|
+
# # # -------
|
|
342
|
+
# # # >>> eeg_data = np.random.randn(1, 32, 1000) # Mock EEG data
|
|
343
|
+
# # # >>> sonify_eeg(eeg_data, 250, method='fm', channels=(0,1))
|
|
344
|
+
|
|
345
|
+
# # # Parameters
|
|
346
|
+
# # # ----------
|
|
347
|
+
# # # signal_array : np.ndarray
|
|
348
|
+
# # # EEG signal array of shape (batch_size, n_channels, sequence_length)
|
|
349
|
+
# # # sampling_freq : int
|
|
350
|
+
# # # Original sampling frequency of the EEG signal
|
|
351
|
+
# # # method : {'shift', 'am', 'fm'}
|
|
352
|
+
# # # Sonification method to use
|
|
353
|
+
# # # channels : Tuple[int, ...]
|
|
354
|
+
# # # Channels to include in sonification
|
|
355
|
+
# # # target_fs : int
|
|
356
|
+
# # # Target audio sampling frequency
|
|
357
|
+
# # # **kwargs : Dict[str, Any]
|
|
358
|
+
# # # Additional parameters for specific sonification methods
|
|
359
|
+
|
|
360
|
+
# # # Returns
|
|
361
|
+
# # # -------
|
|
362
|
+
# # # None
|
|
363
|
+
# # # """
|
|
364
|
+
|
|
365
|
+
# # # if not isinstance(signal_array, np.ndarray):
|
|
366
|
+
# # # signal_array = np.array(signal_array)
|
|
367
|
+
|
|
368
|
+
# # # if len(signal_array.shape) != 3:
|
|
369
|
+
# # # raise ValueError(f"Expected 3D array, got shape {signal_array.shape}")
|
|
370
|
+
|
|
371
|
+
# # # if max(channels) >= signal_array.shape[1]:
|
|
372
|
+
# # # raise ValueError(
|
|
373
|
+
# # # f"Channel index {max(channels)} out of range (max: {signal_array.shape[1]-1})"
|
|
374
|
+
# # # )
|
|
375
|
+
|
|
376
|
+
# # # selected_channels = signal_array[:, channels, :].mean(axis=1)
|
|
377
|
+
# # # signal = selected_channels.mean(axis=0)
|
|
378
|
+
|
|
379
|
+
# # # # Normalize
|
|
380
|
+
# # # signal = signal / np.max(np.abs(signal))
|
|
381
|
+
|
|
382
|
+
# # # # Apply selected method
|
|
383
|
+
# # # if method == "shift":
|
|
384
|
+
# # # audio = frequency_shift(signal, kwargs.get("shift_factor", 200))
|
|
385
|
+
# # # elif method == "am":
|
|
386
|
+
# # # audio = am_Modulation(
|
|
387
|
+
# # # signal, kwargs.get("carrier_freq", 440), target_fs
|
|
388
|
+
# # # )
|
|
389
|
+
# # # elif method == "fm":
|
|
390
|
+
# # # audio = fm_Modulation(
|
|
391
|
+
# # # signal,
|
|
392
|
+
# # # kwargs.get("carrier_freq", 440),
|
|
393
|
+
# # # kwargs.get("sensitivity", 0.5),
|
|
394
|
+
# # # target_fs,
|
|
395
|
+
# # # )
|
|
396
|
+
# # # else:
|
|
397
|
+
# # # raise ValueError(f"Unknown method: {method}")
|
|
398
|
+
|
|
399
|
+
# # # if len(audio) < 100:
|
|
400
|
+
# # # raise ValueError("Audio signal too short after processing")
|
|
401
|
+
|
|
402
|
+
# # # sd.play(audio, target_fs)
|
|
403
|
+
# # # sd.wait()
|
|
404
|
+
|
|
405
|
+
# # # def listen(
|
|
406
|
+
# # # signal_array: np.ndarray,
|
|
407
|
+
# # # sampling_freq: int,
|
|
408
|
+
# # # channels: Tuple[int, ...] = (0, 1),
|
|
409
|
+
# # # target_fs: int = 44_100,
|
|
410
|
+
# # # ) -> None:
|
|
411
|
+
# # # """
|
|
412
|
+
# # # Play selected channels of a multichannel signal array as audio.
|
|
413
|
+
|
|
414
|
+
# # # Example
|
|
415
|
+
# # # -------
|
|
416
|
+
# # # >>> signal = np.random.randn(1, 2, 1000) # Random stereo signal
|
|
417
|
+
# # # >>> listen(signal, 16000, channels=(0, 1))
|
|
418
|
+
|
|
419
|
+
# # # Parameters
|
|
420
|
+
# # # ----------
|
|
421
|
+
# # # signal_array : np.ndarray
|
|
422
|
+
# # # Signal array of shape (batch_size, n_channels, sequence_length)
|
|
423
|
+
# # # sampling_freq : int
|
|
424
|
+
# # # Original sampling frequency of the signal
|
|
425
|
+
# # # channels : Tuple[int, ...]
|
|
426
|
+
# # # Tuple of channel indices to listen to
|
|
427
|
+
# # # target_fs : int
|
|
428
|
+
# # # Target sampling frequency for playback
|
|
429
|
+
|
|
430
|
+
# # # Returns
|
|
431
|
+
# # # -------
|
|
432
|
+
# # # None
|
|
433
|
+
# # # """
|
|
434
|
+
# # # if not isinstance(signal_array, np.ndarray):
|
|
435
|
+
# # # signal_array = np.array(signal_array)
|
|
436
|
+
|
|
437
|
+
# # # if len(signal_array.shape) != 3:
|
|
438
|
+
# # # raise ValueError(f"Expected 3D array, got shape {signal_array.shape}")
|
|
439
|
+
|
|
440
|
+
# # # if max(channels) >= signal_array.shape[1]:
|
|
441
|
+
# # # raise ValueError(
|
|
442
|
+
# # # f"Channel index {max(channels)} out of range (max: {signal_array.shape[1]-1})"
|
|
443
|
+
# # # )
|
|
444
|
+
|
|
445
|
+
# # # selected_channels = signal_array[:, channels, :].mean(axis=1)
|
|
446
|
+
# # # audio_signal = selected_channels.mean(axis=0)
|
|
447
|
+
|
|
448
|
+
# # # if sampling_freq != target_fs:
|
|
449
|
+
# # # num_samples = int(round(len(audio_signal) * target_fs / sampling_freq))
|
|
450
|
+
# # # audio_signal = resample(audio_signal, num_samples)
|
|
451
|
+
|
|
452
|
+
# # # sd.play(audio_signal, target_fs)
|
|
453
|
+
# # # sd.wait()
|
|
454
|
+
|
|
455
|
+
# # # def print_device_info() -> None:
|
|
456
|
+
# # # """
|
|
457
|
+
# # # Display information about the default audio output device.
|
|
458
|
+
|
|
459
|
+
# # # Example
|
|
460
|
+
# # # -------
|
|
461
|
+
# # # >>> print_device_info()
|
|
462
|
+
# # # Default Output Device Info:
|
|
463
|
+
# # # <device info details>
|
|
464
|
+
# # # """
|
|
465
|
+
# # # try:
|
|
466
|
+
# # # device_info = sd.query_devices(kind="output")
|
|
467
|
+
# # # print(f"Default Output Device Info: \n{device_info}")
|
|
468
|
+
# # # except sd.PortAudioError as err:
|
|
469
|
+
# # # print(f"Error querying audio devices: {err}")
|
|
470
|
+
|
|
471
|
+
# # # if __name__ == "__main__":
|
|
472
|
+
# # # import scitex
|
|
473
|
+
|
|
474
|
+
# # # CONFIG, sys.stdout, sys.stderr, plt, CC = scitex.gen.start(sys, plt)
|
|
475
|
+
|
|
476
|
+
# # # # Generate a test signal if demo_sig fails
|
|
477
|
+
# # # try:
|
|
478
|
+
# # # signal, time_points, sampling_freq = scitex.dsp.demo_sig("chirp")
|
|
479
|
+
# # # except Exception as err:
|
|
480
|
+
# # # print(f"Failed to load demo signal: {err}")
|
|
481
|
+
# # # # Generate a simple test signal
|
|
482
|
+
# # # duration = 2 # seconds
|
|
483
|
+
# # # sampling_freq = 1000 # Hz
|
|
484
|
+
# # # t = np.linspace(0, duration, int(duration * sampling_freq))
|
|
485
|
+
# # # test_signal = np.sin(2 * np.pi * 10 * t) # 10 Hz sine wave
|
|
486
|
+
# # # signal = test_signal.reshape(1, 1, -1)
|
|
487
|
+
|
|
488
|
+
# # # # Try to get audio device
|
|
489
|
+
# # # try:
|
|
490
|
+
# # # device_id = list_and_select_device()
|
|
491
|
+
# # # sd.default.device = device_id
|
|
492
|
+
# # # except Exception as err:
|
|
493
|
+
# # # print(f"Failed to set audio device: {err}")
|
|
494
|
+
# # # print("Using default audio device")
|
|
495
|
+
# # # device_id = None
|
|
496
|
+
|
|
497
|
+
# # # # Test different sonification methods with error handling
|
|
498
|
+
# # # methods = ["shift", "am", "fm"]
|
|
499
|
+
# # # for method in methods:
|
|
500
|
+
# # # try:
|
|
501
|
+
# # # print(f"\nTesting {method} sonification...")
|
|
502
|
+
# # # sonify_eeg(signal, sampling_freq, method=method)
|
|
503
|
+
# # # except Exception as err:
|
|
504
|
+
# # # print(f"Failed to play {method} sonification: {err}")
|
|
505
|
+
|
|
506
|
+
# # # scitex.gen.close(CONFIG)
|
|
507
|
+
|
|
508
|
+
# # # # EOF
|
|
509
|
+
|
|
510
|
+
# # # # #!/usr/bin/env python3
|
|
511
|
+
# # # # # -*- coding: utf-8 -*-
|
|
512
|
+
# # # # # Time-stamp: "2024-11-07 18:58:37 (ywatanabe)"
|
|
513
|
+
# # # # # File: ./scitex_repo/src/scitex/dsp/_listen.py
|
|
514
|
+
|
|
515
|
+
# # # # import sys
|
|
516
|
+
# # # # from typing import Tuple
|
|
517
|
+
|
|
518
|
+
# # # # import matplotlib.pyplot as plt
|
|
519
|
+
# # # # import scitex
|
|
520
|
+
# # # # import numpy as np
|
|
521
|
+
# # # # import sounddevice as sd
|
|
522
|
+
# # # # from scipy.signal import resample
|
|
523
|
+
|
|
524
|
+
# # # # """
|
|
525
|
+
# # # # Functionality:
|
|
526
|
+
# # # # - Provides audio playback functionality for multichannel signal arrays
|
|
527
|
+
# # # # - Includes device selection and audio information display utilities
|
|
528
|
+
# # # # Input:
|
|
529
|
+
# # # # - Multichannel signal arrays (numpy.ndarray)
|
|
530
|
+
# # # # - Sampling frequency and channel selection
|
|
531
|
+
# # # # Output:
|
|
532
|
+
# # # # - Audio playback through specified output device
|
|
533
|
+
# # # # Prerequisites:
|
|
534
|
+
# # # # - PortAudio library (install with: sudo apt-get install portaudio19-dev)
|
|
535
|
+
# # # # - sounddevice package
|
|
536
|
+
# # # # """
|
|
537
|
+
|
|
538
|
+
# # # # """Imports"""
|
|
539
|
+
# # # # """Config"""
|
|
540
|
+
# # # # CONFIG = scitex.gen.load_configs()
|
|
541
|
+
|
|
542
|
+
# # # # """Functions"""
|
|
543
|
+
# # # # def listen(
|
|
544
|
+
# # # # signal_array: np.ndarray,
|
|
545
|
+
# # # # sampling_freq: int,
|
|
546
|
+
# # # # channels: Tuple[int, ...] = (0, 1),
|
|
547
|
+
# # # # target_fs: int = 44_100,
|
|
548
|
+
# # # # ) -> None:
|
|
549
|
+
# # # # """
|
|
550
|
+
# # # # Play selected channels of a multichannel signal array as audio.
|
|
551
|
+
|
|
552
|
+
# # # # Example
|
|
553
|
+
# # # # -------
|
|
554
|
+
# # # # >>> signal = np.random.randn(1, 2, 1000) # Random stereo signal
|
|
555
|
+
# # # # >>> listen(signal, 16000, channels=(0, 1))
|
|
556
|
+
|
|
557
|
+
# # # # Parameters
|
|
558
|
+
# # # # ----------
|
|
559
|
+
# # # # signal_array : np.ndarray
|
|
560
|
+
# # # # Signal array of shape (batch_size, n_channels, sequence_length)
|
|
561
|
+
# # # # sampling_freq : int
|
|
562
|
+
# # # # Original sampling frequency of the signal
|
|
563
|
+
# # # # channels : Tuple[int, ...]
|
|
564
|
+
# # # # Tuple of channel indices to listen to
|
|
565
|
+
# # # # target_fs : int
|
|
566
|
+
# # # # Target sampling frequency for playback
|
|
567
|
+
|
|
568
|
+
# # # # Returns
|
|
569
|
+
# # # # -------
|
|
570
|
+
# # # # None
|
|
571
|
+
# # # # """
|
|
572
|
+
# # # # if not isinstance(signal_array, np.ndarray):
|
|
573
|
+
# # # # signal_array = np.array(signal_array)
|
|
574
|
+
|
|
575
|
+
# # # # if len(signal_array.shape) != 3:
|
|
576
|
+
# # # # raise ValueError(f"Expected 3D array, got shape {signal_array.shape}")
|
|
577
|
+
|
|
578
|
+
# # # # if max(channels) >= signal_array.shape[1]:
|
|
579
|
+
# # # # raise ValueError(f"Channel index {max(channels)} out of range (max: {signal_array.shape[1]-1})")
|
|
580
|
+
|
|
581
|
+
# # # # selected_channels = signal_array[:, channels, :].mean(axis=1)
|
|
582
|
+
# # # # audio_signal = selected_channels.mean(axis=0)
|
|
583
|
+
|
|
584
|
+
# # # # if sampling_freq != target_fs:
|
|
585
|
+
# # # # num_samples = int(round(len(audio_signal) * target_fs / sampling_freq))
|
|
586
|
+
# # # # audio_signal = resample(audio_signal, num_samples)
|
|
587
|
+
|
|
588
|
+
# # # # sd.play(audio_signal, target_fs)
|
|
589
|
+
# # # # sd.wait()
|
|
590
|
+
|
|
591
|
+
# # # # def print_device_info() -> None:
|
|
592
|
+
# # # # """
|
|
593
|
+
# # # # Display information about the default audio output device.
|
|
594
|
+
|
|
595
|
+
# # # # Example
|
|
596
|
+
# # # # -------
|
|
597
|
+
# # # # >>> print_device_info()
|
|
598
|
+
# # # # Default Output Device Info:
|
|
599
|
+
# # # # <device info details>
|
|
600
|
+
# # # # """
|
|
601
|
+
# # # # try:
|
|
602
|
+
# # # # device_info = sd.query_devices(kind="output")
|
|
603
|
+
# # # # print(f"Default Output Device Info: \n{device_info}")
|
|
604
|
+
# # # # except sd.PortAudioError as err:
|
|
605
|
+
# # # # print(f"Error querying audio devices: {err}")
|
|
606
|
+
|
|
607
|
+
# # # # def list_and_select_device() -> int:
|
|
608
|
+
# # # # """
|
|
609
|
+
# # # # List available audio devices and prompt user to select one.
|
|
610
|
+
|
|
611
|
+
# # # # Example
|
|
612
|
+
# # # # -------
|
|
613
|
+
# # # # >>> device_id = list_and_select_device()
|
|
614
|
+
# # # # Available audio devices:
|
|
615
|
+
# # # # ...
|
|
616
|
+
# # # # Enter the ID of the device you want to use:
|
|
617
|
+
|
|
618
|
+
# # # # Returns
|
|
619
|
+
# # # # -------
|
|
620
|
+
# # # # int
|
|
621
|
+
# # # # Selected device ID
|
|
622
|
+
# # # # """
|
|
623
|
+
# # # # try:
|
|
624
|
+
# # # # print("Available audio devices:")
|
|
625
|
+
# # # # devices = sd.query_devices()
|
|
626
|
+
# # # # print(devices)
|
|
627
|
+
# # # # device_id = int(input("Enter the ID of the device you want to use: "))
|
|
628
|
+
# # # # if device_id not in range(len(devices)):
|
|
629
|
+
# # # # raise ValueError(f"Invalid device ID: {device_id}")
|
|
630
|
+
# # # # return device_id
|
|
631
|
+
# # # # except (ValueError, sd.PortAudioError) as err:
|
|
632
|
+
# # # # print(f"Error during device selection: {err}")
|
|
633
|
+
# # # # return 0
|
|
634
|
+
|
|
635
|
+
# # # # def frequency_shift(signal: np.ndarray, shift_factor: int = 200) -> np.ndarray:
|
|
636
|
+
# # # # """Direct frequency shifting"""
|
|
637
|
+
# # # # num_samples = int(len(signal) * shift_factor)
|
|
638
|
+
# # # # return resample(signal, num_samples)
|
|
639
|
+
|
|
640
|
+
# # # # def am_Modulation(signal: np.ndarray, carrier_freq: float = 440, fs: int = 44100) -> np.ndarray:
|
|
641
|
+
# # # # """Amplitude Modulation"""
|
|
642
|
+
# # # # t = np.arange(len(signal)) / fs
|
|
643
|
+
# # # # carrier = np.sin(2 * np.pi * carrier_freq * t)
|
|
644
|
+
# # # # return (1 + signal) * carrier
|
|
645
|
+
|
|
646
|
+
# # # # def fm_Modulation(signal: np.ndarray, carrier_freq: float = 440, sens: float = 0.5, fs: int = 44100) -> np.ndarray:
|
|
647
|
+
# # # # """Frequency Modulation"""
|
|
648
|
+
# # # # t = np.arange(len(signal)) / fs
|
|
649
|
+
# # # # phase = 2 * np.pi * carrier_freq * t + sens * np.cumsum(signal) / fs
|
|
650
|
+
# # # # return np.sin(phase)
|
|
651
|
+
|
|
652
|
+
# # # # def sonify_eeg(
|
|
653
|
+
# # # # signal_array: np.ndarray,
|
|
654
|
+
# # # # sampling_freq: int,
|
|
655
|
+
# # # # method: str = 'shift',
|
|
656
|
+
# # # # channels: Tuple[int, ...] = (0, 1),
|
|
657
|
+
# # # # target_fs: int = 44100,
|
|
658
|
+
# # # # **kwargs
|
|
659
|
+
# # # # ) -> None:
|
|
660
|
+
# # # # """Main sonification function"""
|
|
661
|
+
# # # # selected_channels = signal_array[:, channels, :].mean(axis=1)
|
|
662
|
+
# # # # signal = selected_channels.mean(axis=0)
|
|
663
|
+
|
|
664
|
+
# # # # # Normalize
|
|
665
|
+
# # # # signal = signal / np.max(np.abs(signal))
|
|
666
|
+
|
|
667
|
+
# # # # # Apply selected method
|
|
668
|
+
# # # # if method == 'shift':
|
|
669
|
+
# # # # audio = frequency_shift(signal, kwargs.get('shift_factor', 200))
|
|
670
|
+
# # # # elif method == 'am':
|
|
671
|
+
# # # # audio = am_Modulation(signal, kwargs.get('carrier_freq', 440), target_fs)
|
|
672
|
+
# # # # elif method == 'fm':
|
|
673
|
+
# # # # audio = fm_Modulation(signal, kwargs.get('carrier_freq', 440), kwargs.get('sensitivity', 0.5), target_fs)
|
|
674
|
+
# # # # else:
|
|
675
|
+
# # # # raise ValueError(f"Unknown method: {method}")
|
|
676
|
+
|
|
677
|
+
# # # # sd.play(audio, target_fs)
|
|
678
|
+
# # # # sd.wait()
|
|
679
|
+
|
|
680
|
+
# # # # if __name__ == "__main__":
|
|
681
|
+
# # # # import scitex
|
|
682
|
+
|
|
683
|
+
# # # # CONFIG, sys.stdout, sys.stderr, plt, CC = scitex.gen.start(sys, plt)
|
|
684
|
+
|
|
685
|
+
# # # # signal, time_points, sampling_freq = scitex.dsp.demo_sig("chirp")
|
|
686
|
+
|
|
687
|
+
# # # # device_id = list_and_select_device()
|
|
688
|
+
# # # # sd.default.device = device_id
|
|
689
|
+
|
|
690
|
+
# # # # listen(signal, sampling_freq)
|
|
691
|
+
|
|
692
|
+
# # # # scitex.gen.close(CONFIG)
|
|
693
|
+
|
|
694
|
+
# # # #
|
|
695
|
+
|
|
696
|
+
# # #
|
|
697
|
+
|
|
698
|
+
# #
|
|
699
|
+
|
|
700
|
+
#
|
|
701
|
+
|
|
702
|
+
# EOF
|