scipy 1.15.3__cp313-cp313-win_amd64.whl → 1.16.0rc2__cp313-cp313-win_amd64.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.
- scipy/__config__.py +8 -8
- scipy/__init__.py +3 -6
- scipy/_cyutility.cp313-win_amd64.dll.a +0 -0
- scipy/_cyutility.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_array_api.py +486 -161
- scipy/_lib/_array_api_compat_vendor.py +9 -0
- scipy/_lib/_bunch.py +4 -0
- scipy/_lib/_ccallback_c.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_ccallback_c.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_docscrape.py +1 -1
- scipy/_lib/_elementwise_iterative_method.py +15 -26
- scipy/_lib/_fpumode.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_fpumode.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_ccallback.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_test_ccallback.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_call.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_call.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_def.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_def.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_testutils.py +6 -2
- scipy/_lib/_uarray/_uarray.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/_uarray/_uarray.cp313-win_amd64.pyd +0 -0
- scipy/_lib/_util.py +222 -125
- scipy/_lib/array_api_compat/__init__.py +4 -4
- scipy/_lib/array_api_compat/_internal.py +19 -6
- scipy/_lib/array_api_compat/common/__init__.py +1 -1
- scipy/_lib/array_api_compat/common/_aliases.py +365 -193
- scipy/_lib/array_api_compat/common/_fft.py +94 -64
- scipy/_lib/array_api_compat/common/_helpers.py +413 -180
- scipy/_lib/array_api_compat/common/_linalg.py +116 -40
- scipy/_lib/array_api_compat/common/_typing.py +179 -10
- scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
- scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
- scipy/_lib/array_api_compat/cupy/_info.py +16 -6
- scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
- scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
- scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
- scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
- scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
- scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
- scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
- scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
- scipy/_lib/array_api_compat/numpy/_info.py +36 -16
- scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
- scipy/_lib/array_api_compat/numpy/fft.py +11 -5
- scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
- scipy/_lib/array_api_compat/torch/__init__.py +3 -5
- scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
- scipy/_lib/array_api_compat/torch/_info.py +27 -16
- scipy/_lib/array_api_compat/torch/_typing.py +3 -0
- scipy/_lib/array_api_compat/torch/fft.py +17 -18
- scipy/_lib/array_api_compat/torch/linalg.py +16 -16
- scipy/_lib/array_api_extra/__init__.py +26 -3
- scipy/_lib/array_api_extra/_delegation.py +171 -0
- scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_at.py +463 -0
- scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
- scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
- scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
- scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
- scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
- scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
- scipy/_lib/array_api_extra/testing.py +359 -0
- scipy/_lib/decorator.py +2 -2
- scipy/_lib/doccer.py +1 -7
- scipy/_lib/messagestream.cp313-win_amd64.dll.a +0 -0
- scipy/_lib/messagestream.cp313-win_amd64.pyd +0 -0
- scipy/_lib/pyprima/__init__.py +212 -0
- scipy/_lib/pyprima/cobyla/__init__.py +0 -0
- scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
- scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
- scipy/_lib/pyprima/cobyla/geometry.py +226 -0
- scipy/_lib/pyprima/cobyla/initialize.py +215 -0
- scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
- scipy/_lib/pyprima/cobyla/update.py +289 -0
- scipy/_lib/pyprima/common/__init__.py +0 -0
- scipy/_lib/pyprima/common/_bounds.py +34 -0
- scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
- scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
- scipy/_lib/pyprima/common/_project.py +173 -0
- scipy/_lib/pyprima/common/checkbreak.py +93 -0
- scipy/_lib/pyprima/common/consts.py +47 -0
- scipy/_lib/pyprima/common/evaluate.py +99 -0
- scipy/_lib/pyprima/common/history.py +38 -0
- scipy/_lib/pyprima/common/infos.py +30 -0
- scipy/_lib/pyprima/common/linalg.py +435 -0
- scipy/_lib/pyprima/common/message.py +290 -0
- scipy/_lib/pyprima/common/powalg.py +131 -0
- scipy/_lib/pyprima/common/preproc.py +277 -0
- scipy/_lib/pyprima/common/present.py +5 -0
- scipy/_lib/pyprima/common/ratio.py +54 -0
- scipy/_lib/pyprima/common/redrho.py +47 -0
- scipy/_lib/pyprima/common/selectx.py +296 -0
- scipy/_lib/tests/test__util.py +105 -121
- scipy/_lib/tests/test_array_api.py +166 -35
- scipy/_lib/tests/test_bunch.py +7 -0
- scipy/_lib/tests/test_ccallback.py +2 -10
- scipy/_lib/tests/test_public_api.py +13 -0
- scipy/cluster/_hierarchy.cp313-win_amd64.dll.a +0 -0
- scipy/cluster/_hierarchy.cp313-win_amd64.pyd +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp313-win_amd64.dll.a +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp313-win_amd64.pyd +0 -0
- scipy/cluster/_vq.cp313-win_amd64.dll.a +0 -0
- scipy/cluster/_vq.cp313-win_amd64.pyd +0 -0
- scipy/cluster/hierarchy.py +393 -223
- scipy/cluster/tests/test_hierarchy.py +273 -335
- scipy/cluster/tests/test_vq.py +45 -61
- scipy/cluster/vq.py +39 -35
- scipy/conftest.py +263 -157
- scipy/constants/_constants.py +4 -1
- scipy/constants/tests/test_codata.py +2 -2
- scipy/constants/tests/test_constants.py +11 -18
- scipy/datasets/_download_all.py +15 -1
- scipy/datasets/_fetchers.py +7 -1
- scipy/datasets/_utils.py +1 -1
- scipy/differentiate/_differentiate.py +25 -25
- scipy/differentiate/tests/test_differentiate.py +24 -25
- scipy/fft/_basic.py +20 -0
- scipy/fft/_helper.py +3 -34
- scipy/fft/_pocketfft/helper.py +29 -1
- scipy/fft/_pocketfft/pypocketfft.cp313-win_amd64.dll.a +0 -0
- scipy/fft/_pocketfft/pypocketfft.cp313-win_amd64.pyd +0 -0
- scipy/fft/_pocketfft/tests/test_basic.py +2 -4
- scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
- scipy/fft/_realtransforms.py +13 -0
- scipy/fft/tests/test_basic.py +27 -25
- scipy/fft/tests/test_fftlog.py +16 -7
- scipy/fft/tests/test_helper.py +18 -34
- scipy/fft/tests/test_real_transforms.py +8 -10
- scipy/fftpack/convolve.cp313-win_amd64.dll.a +0 -0
- scipy/fftpack/convolve.cp313-win_amd64.pyd +0 -0
- scipy/fftpack/tests/test_basic.py +2 -4
- scipy/fftpack/tests/test_real_transforms.py +8 -9
- scipy/integrate/_bvp.py +9 -3
- scipy/integrate/_cubature.py +3 -2
- scipy/integrate/_dop.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_dop.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_lsoda.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_lsoda.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_odepack.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_quadpack.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_quadpack_py.py +11 -7
- scipy/integrate/_quadrature.py +3 -3
- scipy/integrate/_rules/_base.py +2 -2
- scipy/integrate/_tanhsinh.py +48 -47
- scipy/integrate/_test_multivariate.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_test_multivariate.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_test_odeint_banded.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_test_odeint_banded.cp313-win_amd64.pyd +0 -0
- scipy/integrate/_vode.cp313-win_amd64.dll.a +0 -0
- scipy/integrate/_vode.cp313-win_amd64.pyd +0 -0
- scipy/integrate/tests/test__quad_vec.py +0 -6
- scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
- scipy/integrate/tests/test_cubature.py +21 -35
- scipy/integrate/tests/test_quadrature.py +6 -8
- scipy/integrate/tests/test_tanhsinh.py +56 -48
- scipy/interpolate/__init__.py +70 -58
- scipy/interpolate/_bary_rational.py +22 -22
- scipy/interpolate/_bsplines.py +119 -66
- scipy/interpolate/_cubic.py +65 -50
- scipy/interpolate/_dfitpack.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_dfitpack.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_dierckx.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_dierckx.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_fitpack.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_fitpack.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_fitpack2.py +9 -6
- scipy/interpolate/_fitpack_impl.py +32 -26
- scipy/interpolate/_fitpack_repro.py +23 -19
- scipy/interpolate/_interpnd.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_interpnd.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_interpolate.py +30 -12
- scipy/interpolate/_ndbspline.py +13 -18
- scipy/interpolate/_ndgriddata.py +5 -8
- scipy/interpolate/_polyint.py +95 -31
- scipy/interpolate/_ppoly.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_ppoly.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_rbfinterp_pythran.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_rgi_cython.cp313-win_amd64.pyd +0 -0
- scipy/interpolate/dfitpack.py +0 -20
- scipy/interpolate/interpnd.py +1 -2
- scipy/interpolate/tests/test_bary_rational.py +2 -2
- scipy/interpolate/tests/test_bsplines.py +97 -1
- scipy/interpolate/tests/test_fitpack2.py +39 -1
- scipy/interpolate/tests/test_interpnd.py +32 -20
- scipy/interpolate/tests/test_interpolate.py +48 -4
- scipy/interpolate/tests/test_rgi.py +2 -1
- scipy/io/_fast_matrix_market/__init__.py +2 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp313-win_amd64.dll.a +0 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp313-win_amd64.pyd +0 -0
- scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
- scipy/io/_harwell_boeing/hb.py +7 -11
- scipy/io/_idl.py +5 -7
- scipy/io/_netcdf.py +15 -5
- scipy/io/_test_fortran.cp313-win_amd64.dll.a +0 -0
- scipy/io/_test_fortran.cp313-win_amd64.pyd +0 -0
- scipy/io/arff/tests/test_arffread.py +3 -3
- scipy/io/matlab/__init__.py +5 -3
- scipy/io/matlab/_mio.py +4 -1
- scipy/io/matlab/_mio5.py +19 -13
- scipy/io/matlab/_mio5_utils.cp313-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio5_utils.cp313-win_amd64.pyd +0 -0
- scipy/io/matlab/_mio_utils.cp313-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio_utils.cp313-win_amd64.pyd +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cp313-win_amd64.dll.a +0 -0
- scipy/io/matlab/_streams.cp313-win_amd64.pyd +0 -0
- scipy/io/matlab/tests/test_mio.py +46 -18
- scipy/io/matlab/tests/test_mio_funcs.py +1 -1
- scipy/io/tests/test_mmio.py +7 -1
- scipy/io/tests/test_wavfile.py +41 -0
- scipy/io/wavfile.py +57 -10
- scipy/linalg/_basic.py +113 -86
- scipy/linalg/_cythonized_array_utils.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_cythonized_array_utils.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_decomp.py +22 -9
- scipy/linalg/_decomp_cholesky.py +28 -13
- scipy/linalg/_decomp_cossin.py +45 -30
- scipy/linalg/_decomp_interpolative.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_interpolative.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_lu_cython.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_polar.py +2 -0
- scipy/linalg/_decomp_qr.py +6 -2
- scipy/linalg/_decomp_qz.py +3 -0
- scipy/linalg/_decomp_schur.py +3 -1
- scipy/linalg/_decomp_svd.py +13 -2
- scipy/linalg/_decomp_update.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_update.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_fblas.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_flapack.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_flapack.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_linalg_pythran.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_linalg_pythran.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_expm.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/_solve_toeplitz.cp313-win_amd64.pyd +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/cython_blas.cp313-win_amd64.pyd +0 -0
- scipy/linalg/cython_lapack.cp313-win_amd64.dll.a +0 -0
- scipy/linalg/cython_lapack.cp313-win_amd64.pyd +0 -0
- scipy/linalg/lapack.py +22 -2
- scipy/linalg/tests/_cython_examples/meson.build +7 -0
- scipy/linalg/tests/test_basic.py +31 -16
- scipy/linalg/tests/test_batch.py +588 -0
- scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
- scipy/linalg/tests/test_decomp.py +40 -3
- scipy/linalg/tests/test_decomp_cossin.py +14 -0
- scipy/linalg/tests/test_decomp_ldl.py +1 -1
- scipy/linalg/tests/test_lapack.py +115 -7
- scipy/linalg/tests/test_matfuncs.py +157 -102
- scipy/linalg/tests/test_procrustes.py +0 -7
- scipy/linalg/tests/test_solve_toeplitz.py +1 -1
- scipy/linalg/tests/test_special_matrices.py +1 -5
- scipy/ndimage/__init__.py +1 -0
- scipy/ndimage/_ctest.cp313-win_amd64.dll.a +0 -0
- scipy/ndimage/_ctest.cp313-win_amd64.pyd +0 -0
- scipy/ndimage/_cytest.cp313-win_amd64.dll.a +0 -0
- scipy/ndimage/_cytest.cp313-win_amd64.pyd +0 -0
- scipy/ndimage/_delegators.py +8 -2
- scipy/ndimage/_filters.py +453 -5
- scipy/ndimage/_interpolation.py +36 -6
- scipy/ndimage/_measurements.py +4 -2
- scipy/ndimage/_morphology.py +5 -0
- scipy/ndimage/_nd_image.cp313-win_amd64.dll.a +0 -0
- scipy/ndimage/_nd_image.cp313-win_amd64.pyd +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cp313-win_amd64.dll.a +0 -0
- scipy/ndimage/_ni_label.cp313-win_amd64.pyd +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cp313-win_amd64.dll.a +0 -0
- scipy/ndimage/_rank_filter_1d.cp313-win_amd64.pyd +0 -0
- scipy/ndimage/_support_alternative_backends.py +18 -6
- scipy/ndimage/tests/test_filters.py +370 -259
- scipy/ndimage/tests/test_fourier.py +7 -9
- scipy/ndimage/tests/test_interpolation.py +68 -61
- scipy/ndimage/tests/test_measurements.py +18 -35
- scipy/ndimage/tests/test_morphology.py +143 -131
- scipy/ndimage/tests/test_splines.py +1 -3
- scipy/odr/__odrpack.cp313-win_amd64.dll.a +0 -0
- scipy/odr/__odrpack.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_bglu_dense.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_bracket.py +17 -24
- scipy/optimize/_chandrupatla.py +9 -10
- scipy/optimize/_cobyla_py.py +104 -123
- scipy/optimize/_constraints.py +14 -10
- scipy/optimize/_differentiable_functions.py +371 -230
- scipy/optimize/_differentialevolution.py +4 -3
- scipy/optimize/_direct.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_direct.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_group_columns.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_core.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_core.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_highs_options.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_highs_options.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_lbfgsb.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_lbfgsb.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_lbfgsb_py.py +57 -16
- scipy/optimize/_linprog_doc.py +2 -2
- scipy/optimize/_linprog_highs.py +2 -2
- scipy/optimize/_linprog_ip.py +25 -10
- scipy/optimize/_linprog_util.py +14 -16
- scipy/optimize/_lsap.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_lsap.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_lsq/givens_elimination.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_lsq/least_squares.py +198 -126
- scipy/optimize/_lsq/lsq_linear.py +6 -6
- scipy/optimize/_lsq/trf.py +35 -8
- scipy/optimize/_milp.py +3 -1
- scipy/optimize/_minimize.py +105 -36
- scipy/optimize/_minpack.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_minpack.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_moduleTNC.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_nnls.py +20 -21
- scipy/optimize/_nonlin.py +34 -3
- scipy/optimize/_numdiff.py +288 -110
- scipy/optimize/_optimize.py +86 -48
- scipy/optimize/_pava_pybind.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_pava_pybind.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_remove_redundancy.py +5 -5
- scipy/optimize/_root_scalar.py +1 -1
- scipy/optimize/_shgo.py +6 -0
- scipy/optimize/_shgo_lib/_complex.py +1 -1
- scipy/optimize/_slsqp_py.py +216 -124
- scipy/optimize/_slsqplib.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_slsqplib.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_trlib/_trlib.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_trustregion.py +20 -6
- scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
- scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
- scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
- scipy/optimize/_trustregion_constr/projections.py +12 -8
- scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
- scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
- scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
- scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
- scipy/optimize/_trustregion_exact.py +0 -1
- scipy/optimize/_zeros.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_zeros.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/cython_optimize/_zeros.cp313-win_amd64.pyd +0 -0
- scipy/optimize/slsqp.py +0 -1
- scipy/optimize/tests/test__basinhopping.py +1 -1
- scipy/optimize/tests/test__differential_evolution.py +4 -4
- scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
- scipy/optimize/tests/test__numdiff.py +66 -22
- scipy/optimize/tests/test__remove_redundancy.py +2 -2
- scipy/optimize/tests/test__shgo.py +9 -1
- scipy/optimize/tests/test_bracket.py +36 -46
- scipy/optimize/tests/test_chandrupatla.py +133 -135
- scipy/optimize/tests/test_cobyla.py +74 -45
- scipy/optimize/tests/test_constraints.py +1 -1
- scipy/optimize/tests/test_differentiable_functions.py +226 -6
- scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
- scipy/optimize/tests/test_least_squares.py +125 -13
- scipy/optimize/tests/test_linear_assignment.py +3 -3
- scipy/optimize/tests/test_linprog.py +3 -3
- scipy/optimize/tests/test_lsq_linear.py +6 -6
- scipy/optimize/tests/test_minimize_constrained.py +2 -2
- scipy/optimize/tests/test_minpack.py +4 -4
- scipy/optimize/tests/test_nnls.py +43 -3
- scipy/optimize/tests/test_nonlin.py +36 -0
- scipy/optimize/tests/test_optimize.py +95 -17
- scipy/optimize/tests/test_slsqp.py +36 -4
- scipy/optimize/tests/test_zeros.py +34 -1
- scipy/signal/__init__.py +12 -23
- scipy/signal/_delegators.py +568 -0
- scipy/signal/_filter_design.py +459 -241
- scipy/signal/_fir_filter_design.py +262 -90
- scipy/signal/_lti_conversion.py +3 -2
- scipy/signal/_ltisys.py +118 -91
- scipy/signal/_max_len_seq_inner.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_max_len_seq_inner.cp313-win_amd64.pyd +0 -0
- scipy/signal/_peak_finding_utils.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_peak_finding_utils.cp313-win_amd64.pyd +0 -0
- scipy/signal/_polyutils.py +172 -0
- scipy/signal/_short_time_fft.py +519 -70
- scipy/signal/_signal_api.py +30 -0
- scipy/signal/_signaltools.py +719 -399
- scipy/signal/_sigtools.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_sigtools.cp313-win_amd64.pyd +0 -0
- scipy/signal/_sosfilt.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_sosfilt.cp313-win_amd64.pyd +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_spline.cp313-win_amd64.pyd +0 -0
- scipy/signal/_spline_filters.py +108 -68
- scipy/signal/_support_alternative_backends.py +73 -0
- scipy/signal/_upfirdn.py +4 -1
- scipy/signal/_upfirdn_apply.cp313-win_amd64.dll.a +0 -0
- scipy/signal/_upfirdn_apply.cp313-win_amd64.pyd +0 -0
- scipy/signal/_waveforms.py +2 -11
- scipy/signal/_wavelets.py +1 -1
- scipy/signal/fir_filter_design.py +1 -0
- scipy/signal/spline.py +4 -11
- scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
- scipy/signal/tests/test_bsplines.py +114 -79
- scipy/signal/tests/test_cont2discrete.py +9 -2
- scipy/signal/tests/test_filter_design.py +721 -481
- scipy/signal/tests/test_fir_filter_design.py +332 -140
- scipy/signal/tests/test_savitzky_golay.py +4 -3
- scipy/signal/tests/test_short_time_fft.py +221 -3
- scipy/signal/tests/test_signaltools.py +2144 -1348
- scipy/signal/tests/test_spectral.py +50 -6
- scipy/signal/tests/test_splines.py +161 -96
- scipy/signal/tests/test_upfirdn.py +84 -50
- scipy/signal/tests/test_waveforms.py +20 -0
- scipy/signal/tests/test_windows.py +607 -466
- scipy/signal/windows/_windows.py +287 -148
- scipy/sparse/__init__.py +23 -4
- scipy/sparse/_base.py +270 -108
- scipy/sparse/_bsr.py +7 -4
- scipy/sparse/_compressed.py +59 -231
- scipy/sparse/_construct.py +90 -38
- scipy/sparse/_coo.py +115 -181
- scipy/sparse/_csc.py +4 -4
- scipy/sparse/_csparsetools.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/_csparsetools.cp313-win_amd64.pyd +0 -0
- scipy/sparse/_csr.py +2 -2
- scipy/sparse/_data.py +48 -48
- scipy/sparse/_dia.py +105 -18
- scipy/sparse/_dok.py +0 -23
- scipy/sparse/_index.py +4 -4
- scipy/sparse/_matrix.py +23 -0
- scipy/sparse/_sparsetools.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/_sparsetools.cp313-win_amd64.pyd +0 -0
- scipy/sparse/_sputils.py +37 -22
- scipy/sparse/base.py +0 -9
- scipy/sparse/bsr.py +0 -14
- scipy/sparse/compressed.py +0 -23
- scipy/sparse/construct.py +0 -6
- scipy/sparse/coo.py +0 -14
- scipy/sparse/csc.py +0 -3
- scipy/sparse/csgraph/_flow.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_flow.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_matching.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_matching.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_reordering.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_reordering.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_shortest_path.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_shortest_path.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_tools.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_tools.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_traversal.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_traversal.cp313-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/tests/test_matching.py +14 -2
- scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
- scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
- scipy/sparse/csr.py +0 -5
- scipy/sparse/data.py +1 -6
- scipy/sparse/dia.py +0 -7
- scipy/sparse/dok.py +0 -10
- scipy/sparse/linalg/_dsolve/_superlu.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
- scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
- scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
- scipy/sparse/linalg/_interface.py +17 -18
- scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
- scipy/sparse/linalg/_isolve/iterative.py +51 -45
- scipy/sparse/linalg/_isolve/lgmres.py +6 -6
- scipy/sparse/linalg/_isolve/minres.py +5 -5
- scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
- scipy/sparse/linalg/_isolve/utils.py +2 -8
- scipy/sparse/linalg/_matfuncs.py +1 -1
- scipy/sparse/linalg/_norm.py +1 -1
- scipy/sparse/linalg/_propack/_cpropack.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_cpropack.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp313-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp313-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
- scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
- scipy/sparse/tests/test_arithmetic1d.py +5 -2
- scipy/sparse/tests/test_base.py +214 -42
- scipy/sparse/tests/test_common1d.py +7 -7
- scipy/sparse/tests/test_construct.py +1 -1
- scipy/sparse/tests/test_coo.py +272 -4
- scipy/sparse/tests/test_sparsetools.py +5 -0
- scipy/sparse/tests/test_sputils.py +36 -7
- scipy/spatial/_ckdtree.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_ckdtree.cp313-win_amd64.pyd +0 -0
- scipy/spatial/_distance_pybind.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_pybind.cp313-win_amd64.pyd +0 -0
- scipy/spatial/_distance_wrap.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_wrap.cp313-win_amd64.pyd +0 -0
- scipy/spatial/_hausdorff.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_hausdorff.cp313-win_amd64.pyd +0 -0
- scipy/spatial/_qhull.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_qhull.cp313-win_amd64.pyd +0 -0
- scipy/spatial/_voronoi.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/_voronoi.cp313-win_amd64.pyd +0 -0
- scipy/spatial/distance.py +49 -42
- scipy/spatial/tests/test_distance.py +15 -1
- scipy/spatial/tests/test_kdtree.py +1 -0
- scipy/spatial/tests/test_qhull.py +7 -2
- scipy/spatial/transform/__init__.py +5 -3
- scipy/spatial/transform/_rigid_transform.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/transform/_rigid_transform.cp313-win_amd64.pyd +0 -0
- scipy/spatial/transform/_rotation.cp313-win_amd64.dll.a +0 -0
- scipy/spatial/transform/_rotation.cp313-win_amd64.pyd +0 -0
- scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
- scipy/spatial/transform/tests/test_rotation.py +1213 -832
- scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
- scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
- scipy/special/__init__.py +1 -47
- scipy/special/_add_newdocs.py +34 -772
- scipy/special/_basic.py +22 -25
- scipy/special/_comb.cp313-win_amd64.dll.a +0 -0
- scipy/special/_comb.cp313-win_amd64.pyd +0 -0
- scipy/special/_ellip_harm_2.cp313-win_amd64.dll.a +0 -0
- scipy/special/_ellip_harm_2.cp313-win_amd64.pyd +0 -0
- scipy/special/_gufuncs.cp313-win_amd64.dll.a +0 -0
- scipy/special/_gufuncs.cp313-win_amd64.pyd +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cp313-win_amd64.dll.a +0 -0
- scipy/special/_specfun.cp313-win_amd64.pyd +0 -0
- scipy/special/_special_ufuncs.cp313-win_amd64.dll.a +0 -0
- scipy/special/_special_ufuncs.cp313-win_amd64.pyd +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cp313-win_amd64.dll.a +0 -0
- scipy/special/_test_internal.cp313-win_amd64.pyd +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cp313-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs.cp313-win_amd64.pyd +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cp313-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs_cxx.cp313-win_amd64.pyd +0 -0
- scipy/special/_ufuncs_cxx.pxd +2 -15
- scipy/special/_ufuncs_cxx.pyx +5 -44
- scipy/special/_ufuncs_cxx_defs.h +2 -16
- scipy/special/_ufuncs_defs.h +0 -8
- scipy/special/cython_special.cp313-win_amd64.dll.a +0 -0
- scipy/special/cython_special.cp313-win_amd64.pyd +0 -0
- scipy/special/cython_special.pxd +1 -1
- scipy/special/tests/_cython_examples/meson.build +10 -1
- scipy/special/tests/test_basic.py +153 -20
- scipy/special/tests/test_boost_ufuncs.py +3 -0
- scipy/special/tests/test_cdflib.py +35 -11
- scipy/special/tests/test_gammainc.py +16 -0
- scipy/special/tests/test_hyp2f1.py +2 -2
- scipy/special/tests/test_log1mexp.py +85 -0
- scipy/special/tests/test_logsumexp.py +206 -64
- scipy/special/tests/test_mpmath.py +1 -0
- scipy/special/tests/test_nan_inputs.py +1 -1
- scipy/special/tests/test_orthogonal.py +17 -18
- scipy/special/tests/test_sf_error.py +3 -2
- scipy/special/tests/test_sph_harm.py +6 -7
- scipy/special/tests/test_support_alternative_backends.py +211 -76
- scipy/stats/__init__.py +4 -1
- scipy/stats/_ansari_swilk_statistics.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_ansari_swilk_statistics.cp313-win_amd64.pyd +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_biasedurn.cp313-win_amd64.pyd +0 -0
- scipy/stats/_continued_fraction.py +387 -0
- scipy/stats/_continuous_distns.py +277 -310
- scipy/stats/_correlation.py +1 -1
- scipy/stats/_covariance.py +6 -3
- scipy/stats/_discrete_distns.py +39 -32
- scipy/stats/_distn_infrastructure.py +39 -12
- scipy/stats/_distribution_infrastructure.py +900 -238
- scipy/stats/_entropy.py +9 -10
- scipy/{_lib → stats}/_finite_differences.py +1 -1
- scipy/stats/_hypotests.py +83 -50
- scipy/stats/_kde.py +53 -49
- scipy/stats/_ksstats.py +1 -1
- scipy/stats/_levy_stable/__init__.py +7 -15
- scipy/stats/_levy_stable/levyst.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_levy_stable/levyst.cp313-win_amd64.pyd +0 -0
- scipy/stats/_morestats.py +118 -73
- scipy/stats/_mstats_basic.py +13 -17
- scipy/stats/_mstats_extras.py +8 -8
- scipy/stats/_multivariate.py +89 -113
- scipy/stats/_new_distributions.py +97 -20
- scipy/stats/_page_trend_test.py +12 -5
- scipy/stats/_probability_distribution.py +265 -43
- scipy/stats/_qmc.py +14 -9
- scipy/stats/_qmc_cy.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_qmc_cy.cp313-win_amd64.pyd +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_qmvnt_cy.cp313-win_amd64.pyd +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_rcont/rcont.cp313-win_amd64.pyd +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_sobol.cp313-win_amd64.pyd +0 -0
- scipy/stats/_stats.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_stats.cp313-win_amd64.pyd +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_stats_pythran.cp313-win_amd64.pyd +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp313-win_amd64.pyd +0 -0
- scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
- scipy/stats/_variation.py +6 -8
- scipy/stats/_wilcoxon.py +13 -7
- scipy/stats/tests/common_tests.py +6 -4
- scipy/stats/tests/test_axis_nan_policy.py +62 -24
- scipy/stats/tests/test_continued_fraction.py +173 -0
- scipy/stats/tests/test_continuous.py +379 -60
- scipy/stats/tests/test_continuous_basic.py +18 -12
- scipy/stats/tests/test_discrete_basic.py +14 -8
- scipy/stats/tests/test_discrete_distns.py +16 -16
- scipy/stats/tests/test_distributions.py +95 -75
- scipy/stats/tests/test_entropy.py +40 -48
- scipy/stats/tests/test_fit.py +4 -3
- scipy/stats/tests/test_hypotests.py +153 -24
- scipy/stats/tests/test_kdeoth.py +109 -41
- scipy/stats/tests/test_marray.py +289 -0
- scipy/stats/tests/test_morestats.py +79 -47
- scipy/stats/tests/test_mstats_basic.py +3 -3
- scipy/stats/tests/test_multivariate.py +434 -83
- scipy/stats/tests/test_qmc.py +13 -10
- scipy/stats/tests/test_quantile.py +199 -0
- scipy/stats/tests/test_rank.py +119 -112
- scipy/stats/tests/test_resampling.py +47 -56
- scipy/stats/tests/test_sampling.py +9 -4
- scipy/stats/tests/test_stats.py +799 -939
- scipy/stats/tests/test_variation.py +8 -6
- scipy/version.py +2 -2
- scipy-1.16.0rc2.dist-info/DELVEWHEEL +2 -0
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +685 -693
- scipy/_lib/array_api_extra/_funcs.py +0 -484
- scipy/_lib/array_api_extra/_typing.py +0 -8
- scipy/interpolate/_bspl.cp313-win_amd64.dll.a +0 -0
- scipy/interpolate/_bspl.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_cobyla.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_cobyla.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_cython_nnls.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_cython_nnls.cp313-win_amd64.pyd +0 -0
- scipy/optimize/_slsqp.cp313-win_amd64.dll.a +0 -0
- scipy/optimize/_slsqp.cp313-win_amd64.pyd +0 -0
- scipy/spatial/qhull_src/COPYING.txt +0 -38
- scipy/special/libsf_error_state.dll +0 -0
- scipy/special/libsf_error_state.dll.a +0 -0
- scipy/special/tests/test_log_softmax.py +0 -109
- scipy/special/tests/test_xsf_cuda.py +0 -114
- scipy/special/xsf/binom.h +0 -89
- scipy/special/xsf/cdflib.h +0 -100
- scipy/special/xsf/cephes/airy.h +0 -307
- scipy/special/xsf/cephes/besselpoly.h +0 -51
- scipy/special/xsf/cephes/beta.h +0 -257
- scipy/special/xsf/cephes/cbrt.h +0 -131
- scipy/special/xsf/cephes/chbevl.h +0 -85
- scipy/special/xsf/cephes/chdtr.h +0 -193
- scipy/special/xsf/cephes/const.h +0 -87
- scipy/special/xsf/cephes/ellie.h +0 -293
- scipy/special/xsf/cephes/ellik.h +0 -251
- scipy/special/xsf/cephes/ellpe.h +0 -107
- scipy/special/xsf/cephes/ellpk.h +0 -117
- scipy/special/xsf/cephes/expn.h +0 -260
- scipy/special/xsf/cephes/gamma.h +0 -398
- scipy/special/xsf/cephes/hyp2f1.h +0 -596
- scipy/special/xsf/cephes/hyperg.h +0 -361
- scipy/special/xsf/cephes/i0.h +0 -149
- scipy/special/xsf/cephes/i1.h +0 -158
- scipy/special/xsf/cephes/igam.h +0 -421
- scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
- scipy/special/xsf/cephes/igami.h +0 -313
- scipy/special/xsf/cephes/j0.h +0 -225
- scipy/special/xsf/cephes/j1.h +0 -198
- scipy/special/xsf/cephes/jv.h +0 -715
- scipy/special/xsf/cephes/k0.h +0 -164
- scipy/special/xsf/cephes/k1.h +0 -163
- scipy/special/xsf/cephes/kn.h +0 -243
- scipy/special/xsf/cephes/lanczos.h +0 -112
- scipy/special/xsf/cephes/ndtr.h +0 -275
- scipy/special/xsf/cephes/poch.h +0 -85
- scipy/special/xsf/cephes/polevl.h +0 -167
- scipy/special/xsf/cephes/psi.h +0 -194
- scipy/special/xsf/cephes/rgamma.h +0 -111
- scipy/special/xsf/cephes/scipy_iv.h +0 -811
- scipy/special/xsf/cephes/shichi.h +0 -248
- scipy/special/xsf/cephes/sici.h +0 -224
- scipy/special/xsf/cephes/sindg.h +0 -221
- scipy/special/xsf/cephes/tandg.h +0 -139
- scipy/special/xsf/cephes/trig.h +0 -58
- scipy/special/xsf/cephes/unity.h +0 -186
- scipy/special/xsf/cephes/zeta.h +0 -172
- scipy/special/xsf/config.h +0 -304
- scipy/special/xsf/digamma.h +0 -205
- scipy/special/xsf/error.h +0 -57
- scipy/special/xsf/evalpoly.h +0 -47
- scipy/special/xsf/expint.h +0 -266
- scipy/special/xsf/hyp2f1.h +0 -694
- scipy/special/xsf/iv_ratio.h +0 -173
- scipy/special/xsf/lambertw.h +0 -150
- scipy/special/xsf/loggamma.h +0 -163
- scipy/special/xsf/sici.h +0 -200
- scipy/special/xsf/tools.h +0 -427
- scipy/special/xsf/trig.h +0 -164
- scipy/special/xsf/wright_bessel.h +0 -843
- scipy/special/xsf/zlog1.h +0 -35
- scipy/stats/_mvn.cp313-win_amd64.dll.a +0 -0
- scipy/stats/_mvn.cp313-win_amd64.pyd +0 -0
- scipy-1.15.3.dist-info/DELVEWHEEL +0 -2
- /scipy-1.15.3-cp313-cp313-win_amd64.whl → /scipy-1.16.0rc2-cp313-cp313-win_amd64.whl +0 -0
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/WHEEL +0 -0
scipy/signal/windows/_windows.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
"""The suite of window functions."""
|
2
2
|
|
3
|
+
import math
|
3
4
|
import operator
|
4
5
|
import warnings
|
6
|
+
from scipy._lib import doccer
|
5
7
|
|
6
|
-
import numpy as np
|
7
8
|
from scipy import linalg, special, fft as sp_fft
|
9
|
+
from scipy._lib.array_api_compat import numpy as np_compat
|
10
|
+
from scipy._lib._array_api import array_namespace, xp_device
|
11
|
+
from scipy._lib import array_api_extra as xpx
|
8
12
|
|
9
13
|
__all__ = ['boxcar', 'triang', 'parzen', 'bohman', 'blackman', 'nuttall',
|
10
14
|
'blackmanharris', 'flattop', 'bartlett', 'barthann',
|
@@ -37,6 +41,28 @@ def _truncate(w, needed):
|
|
37
41
|
return w
|
38
42
|
|
39
43
|
|
44
|
+
def _namespace(xp):
|
45
|
+
"""A shim for the `device` arg of `np.asarray(x, device=device)` and acos/arccos.
|
46
|
+
|
47
|
+
Will be able to replace with `np_compat if xp is None else xp` when we drop
|
48
|
+
support for numpy 1.x and cupy 13.x
|
49
|
+
"""
|
50
|
+
return np_compat if xp is None else array_namespace(xp.empty(0))
|
51
|
+
|
52
|
+
|
53
|
+
def _general_cosine_impl(M, a, xp, device, sym=True):
|
54
|
+
if _len_guards(M):
|
55
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
56
|
+
M, needs_trunc = _extend(M, sym)
|
57
|
+
|
58
|
+
fac = xp.linspace(-xp.pi, xp.pi, M, dtype=xp.float64, device=device)
|
59
|
+
w = xp.zeros(M, dtype=xp.float64, device=device)
|
60
|
+
for k in range(a.shape[0]):
|
61
|
+
w += a[k] * xp.cos(k * fac)
|
62
|
+
|
63
|
+
return _truncate(w, needs_trunc)
|
64
|
+
|
65
|
+
|
40
66
|
def general_cosine(M, a, sym=True):
|
41
67
|
r"""
|
42
68
|
Generic weighted sum of cosine terms window
|
@@ -113,19 +139,13 @@ def general_cosine(M, a, sym=True):
|
|
113
139
|
>>> plt.axhline(-90.2, color='red')
|
114
140
|
>>> plt.show()
|
115
141
|
"""
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
fac = np.linspace(-np.pi, np.pi, M)
|
121
|
-
w = np.zeros(M)
|
122
|
-
for k in range(len(a)):
|
123
|
-
w += a[k] * np.cos(k * fac)
|
124
|
-
|
125
|
-
return _truncate(w, needs_trunc)
|
142
|
+
xp = array_namespace(a)
|
143
|
+
a = xp.asarray(a)
|
144
|
+
device = xp_device(a)
|
145
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
126
146
|
|
127
147
|
|
128
|
-
def boxcar(M, sym=True):
|
148
|
+
def boxcar(M, sym=True, *, xp=None, device=None):
|
129
149
|
"""Return a boxcar or rectangular window.
|
130
150
|
|
131
151
|
Also known as a rectangular window or Dirichlet window, this is equivalent
|
@@ -138,6 +158,7 @@ def boxcar(M, sym=True):
|
|
138
158
|
is returned. An exception is thrown when it is negative.
|
139
159
|
sym : bool, optional
|
140
160
|
Whether the window is symmetric. (Has no effect for boxcar.)
|
161
|
+
%(xp_device_snippet)s
|
141
162
|
|
142
163
|
Returns
|
143
164
|
-------
|
@@ -170,16 +191,18 @@ def boxcar(M, sym=True):
|
|
170
191
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
171
192
|
|
172
193
|
"""
|
194
|
+
xp = _namespace(xp)
|
195
|
+
|
173
196
|
if _len_guards(M):
|
174
|
-
return
|
197
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
175
198
|
M, needs_trunc = _extend(M, sym)
|
176
199
|
|
177
|
-
w =
|
200
|
+
w = xp.ones(M, dtype=xp.float64, device=device)
|
178
201
|
|
179
202
|
return _truncate(w, needs_trunc)
|
180
203
|
|
181
204
|
|
182
|
-
def triang(M, sym=True):
|
205
|
+
def triang(M, sym=True, *, xp=None, device=None):
|
183
206
|
"""Return a triangular window.
|
184
207
|
|
185
208
|
Parameters
|
@@ -191,6 +214,7 @@ def triang(M, sym=True):
|
|
191
214
|
When True (default), generates a symmetric window, for use in filter
|
192
215
|
design.
|
193
216
|
When False, generates a periodic window, for use in spectral analysis.
|
217
|
+
%(xp_device_snippet)s
|
194
218
|
|
195
219
|
Returns
|
196
220
|
-------
|
@@ -229,22 +253,24 @@ def triang(M, sym=True):
|
|
229
253
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
230
254
|
|
231
255
|
"""
|
256
|
+
xp = _namespace(xp)
|
257
|
+
|
232
258
|
if _len_guards(M):
|
233
|
-
return
|
259
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
234
260
|
M, needs_trunc = _extend(M, sym)
|
235
261
|
|
236
|
-
n =
|
262
|
+
n = xp.arange(1, (M + 1) // 2 + 1, dtype=xp.float64, device=device)
|
237
263
|
if M % 2 == 0:
|
238
264
|
w = (2 * n - 1.0) / M
|
239
|
-
w =
|
265
|
+
w = xp.concat([w, xp.flip(w)])
|
240
266
|
else:
|
241
267
|
w = 2 * n / (M + 1.0)
|
242
|
-
w =
|
268
|
+
w = xp.concat([w, xp.flip(w[:-1])])
|
243
269
|
|
244
270
|
return _truncate(w, needs_trunc)
|
245
271
|
|
246
272
|
|
247
|
-
def parzen(M, sym=True):
|
273
|
+
def parzen(M, sym=True, *, xp=None, device=None):
|
248
274
|
"""Return a Parzen window.
|
249
275
|
|
250
276
|
Parameters
|
@@ -256,6 +282,7 @@ def parzen(M, sym=True):
|
|
256
282
|
When True (default), generates a symmetric window, for use in filter
|
257
283
|
design.
|
258
284
|
When False, generates a periodic window, for use in spectral analysis.
|
285
|
+
%(xp_device_snippet)s
|
259
286
|
|
260
287
|
Returns
|
261
288
|
-------
|
@@ -294,22 +321,22 @@ def parzen(M, sym=True):
|
|
294
321
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
295
322
|
|
296
323
|
"""
|
324
|
+
xp = _namespace(xp)
|
325
|
+
|
297
326
|
if _len_guards(M):
|
298
|
-
return
|
327
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
299
328
|
M, needs_trunc = _extend(M, sym)
|
300
329
|
|
301
|
-
n =
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
w = np.r_[wa, wb, wa[::-1]]
|
308
|
-
|
330
|
+
n = xp.arange(-(M - 1) / 2.0, (M - 1) / 2.0 + 0.5, 1.0,
|
331
|
+
dtype=xp.float64, device=device)
|
332
|
+
w = xp.where(abs(n) <= (M - 1) / 4.0,
|
333
|
+
(1 - 6 * (abs(n) / (M / 2.0)) ** 2.0 +
|
334
|
+
6 * (abs(n) / (M / 2.0)) ** 3.0),
|
335
|
+
2 * (1 - abs(n) / (M / 2.0)) ** 3.0)
|
309
336
|
return _truncate(w, needs_trunc)
|
310
337
|
|
311
338
|
|
312
|
-
def bohman(M, sym=True):
|
339
|
+
def bohman(M, sym=True, *, xp=None, device=None):
|
313
340
|
"""Return a Bohman window.
|
314
341
|
|
315
342
|
Parameters
|
@@ -321,6 +348,7 @@ def bohman(M, sym=True):
|
|
321
348
|
When True (default), generates a symmetric window, for use in filter
|
322
349
|
design.
|
323
350
|
When False, generates a periodic window, for use in spectral analysis.
|
351
|
+
%(xp_device_snippet)s
|
324
352
|
|
325
353
|
Returns
|
326
354
|
-------
|
@@ -354,18 +382,21 @@ def bohman(M, sym=True):
|
|
354
382
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
355
383
|
|
356
384
|
"""
|
385
|
+
xp = _namespace(xp)
|
386
|
+
|
357
387
|
if _len_guards(M):
|
358
|
-
return
|
388
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
359
389
|
M, needs_trunc = _extend(M, sym)
|
360
390
|
|
361
|
-
fac =
|
362
|
-
w = (1 - fac) *
|
363
|
-
|
391
|
+
fac = abs(xp.linspace(-1, 1, M, dtype=xp.float64, device=device)[1:-1])
|
392
|
+
w = (1 - fac) * xp.cos(xp.pi * fac) + 1.0 / xp.pi * xp.sin(xp.pi * fac)
|
393
|
+
one = xp.zeros(1, dtype=xp.float64, device=device)
|
394
|
+
w = xp.concat([one, w, one])
|
364
395
|
|
365
396
|
return _truncate(w, needs_trunc)
|
366
397
|
|
367
398
|
|
368
|
-
def blackman(M, sym=True):
|
399
|
+
def blackman(M, sym=True, *, xp=None, device=None):
|
369
400
|
r"""
|
370
401
|
Return a Blackman window.
|
371
402
|
|
@@ -383,6 +414,7 @@ def blackman(M, sym=True):
|
|
383
414
|
When True (default), generates a symmetric window, for use in filter
|
384
415
|
design.
|
385
416
|
When False, generates a periodic window, for use in spectral analysis.
|
417
|
+
%(xp_device_snippet)s
|
386
418
|
|
387
419
|
Returns
|
388
420
|
-------
|
@@ -448,10 +480,13 @@ def blackman(M, sym=True):
|
|
448
480
|
|
449
481
|
"""
|
450
482
|
# Docstring adapted from NumPy's blackman function
|
451
|
-
|
483
|
+
xp = _namespace(xp)
|
484
|
+
a = xp.asarray([0.42, 0.50, 0.08], dtype=xp.float64, device=device)
|
485
|
+
device = xp_device(a)
|
486
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
452
487
|
|
453
488
|
|
454
|
-
def nuttall(M, sym=True):
|
489
|
+
def nuttall(M, sym=True, *, xp=None, device=None):
|
455
490
|
"""Return a minimum 4-term Blackman-Harris window according to Nuttall.
|
456
491
|
|
457
492
|
This variation is called "Nuttall4c" by Heinzel. [2]_
|
@@ -465,6 +500,7 @@ def nuttall(M, sym=True):
|
|
465
500
|
When True (default), generates a symmetric window, for use in filter
|
466
501
|
design.
|
467
502
|
When False, generates a periodic window, for use in spectral analysis.
|
503
|
+
%(xp_device_snippet)s
|
468
504
|
|
469
505
|
Returns
|
470
506
|
-------
|
@@ -508,10 +544,15 @@ def nuttall(M, sym=True):
|
|
508
544
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
509
545
|
|
510
546
|
"""
|
511
|
-
|
547
|
+
xp = _namespace(xp)
|
548
|
+
a = xp.asarray(
|
549
|
+
[0.3635819, 0.4891775, 0.1365995, 0.0106411], dtype=xp.float64, device=device
|
550
|
+
)
|
551
|
+
device = xp_device(a)
|
552
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
512
553
|
|
513
554
|
|
514
|
-
def blackmanharris(M, sym=True):
|
555
|
+
def blackmanharris(M, sym=True, *, xp=None, device=None):
|
515
556
|
"""Return a minimum 4-term Blackman-Harris window.
|
516
557
|
|
517
558
|
Parameters
|
@@ -523,6 +564,7 @@ def blackmanharris(M, sym=True):
|
|
523
564
|
When True (default), generates a symmetric window, for use in filter
|
524
565
|
design.
|
525
566
|
When False, generates a periodic window, for use in spectral analysis.
|
567
|
+
%(xp_device_snippet)s
|
526
568
|
|
527
569
|
Returns
|
528
570
|
-------
|
@@ -556,10 +598,15 @@ def blackmanharris(M, sym=True):
|
|
556
598
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
557
599
|
|
558
600
|
"""
|
559
|
-
|
601
|
+
xp = _namespace(xp)
|
602
|
+
a = xp.asarray(
|
603
|
+
[0.35875, 0.48829, 0.14128, 0.01168], dtype=xp.float64, device=device
|
604
|
+
)
|
605
|
+
device = xp_device(a)
|
606
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
560
607
|
|
561
608
|
|
562
|
-
def flattop(M, sym=True):
|
609
|
+
def flattop(M, sym=True, *, xp=None, device=None):
|
563
610
|
"""Return a flat top window.
|
564
611
|
|
565
612
|
Parameters
|
@@ -571,6 +618,7 @@ def flattop(M, sym=True):
|
|
571
618
|
When True (default), generates a symmetric window, for use in filter
|
572
619
|
design.
|
573
620
|
When False, generates a periodic window, for use in spectral analysis.
|
621
|
+
%(xp_device_snippet)s
|
574
622
|
|
575
623
|
Returns
|
576
624
|
-------
|
@@ -618,11 +666,16 @@ def flattop(M, sym=True):
|
|
618
666
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
619
667
|
|
620
668
|
"""
|
621
|
-
|
622
|
-
|
669
|
+
xp = _namespace(xp)
|
670
|
+
a = xp.asarray(
|
671
|
+
[0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368],
|
672
|
+
dtype=xp.float64, device=device
|
673
|
+
)
|
674
|
+
device = xp_device(a)
|
675
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
623
676
|
|
624
677
|
|
625
|
-
def bartlett(M, sym=True):
|
678
|
+
def bartlett(M, sym=True, *, xp=None, device=None):
|
626
679
|
r"""
|
627
680
|
Return a Bartlett window.
|
628
681
|
|
@@ -640,6 +693,7 @@ def bartlett(M, sym=True):
|
|
640
693
|
When True (default), generates a symmetric window, for use in filter
|
641
694
|
design.
|
642
695
|
When False, generates a periodic window, for use in spectral analysis.
|
696
|
+
%(xp_device_snippet)s
|
643
697
|
|
644
698
|
Returns
|
645
699
|
-------
|
@@ -710,18 +764,22 @@ def bartlett(M, sym=True):
|
|
710
764
|
|
711
765
|
"""
|
712
766
|
# Docstring adapted from NumPy's bartlett function
|
767
|
+
xp = _namespace(xp)
|
768
|
+
|
713
769
|
if _len_guards(M):
|
714
|
-
return
|
770
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
715
771
|
M, needs_trunc = _extend(M, sym)
|
716
772
|
|
717
|
-
n =
|
718
|
-
|
773
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device)
|
774
|
+
|
775
|
+
# cf https://github.com/data-apis/array-api-strict/issues/77
|
776
|
+
w = xp.where(n <= (M - 1) / 2.0,
|
719
777
|
2.0 * n / (M - 1), 2.0 - 2.0 * n / (M - 1))
|
720
778
|
|
721
779
|
return _truncate(w, needs_trunc)
|
722
780
|
|
723
781
|
|
724
|
-
def hann(M, sym=True):
|
782
|
+
def hann(M, sym=True, *, xp=None, device=None):
|
725
783
|
r"""
|
726
784
|
Return a Hann window.
|
727
785
|
|
@@ -737,6 +795,7 @@ def hann(M, sym=True):
|
|
737
795
|
When True (default), generates a symmetric window, for use in filter
|
738
796
|
design.
|
739
797
|
When False, generates a periodic window, for use in spectral analysis.
|
798
|
+
%(xp_device_snippet)s
|
740
799
|
|
741
800
|
Returns
|
742
801
|
-------
|
@@ -801,10 +860,10 @@ def hann(M, sym=True):
|
|
801
860
|
|
802
861
|
"""
|
803
862
|
# Docstring adapted from NumPy's hanning function
|
804
|
-
return general_hamming(M, 0.5, sym)
|
863
|
+
return general_hamming(M, 0.5, sym, xp=xp, device=device)
|
805
864
|
|
806
865
|
|
807
|
-
def tukey(M, alpha=0.5, sym=True):
|
866
|
+
def tukey(M, alpha=0.5, sym=True, *, xp=None, device=None):
|
808
867
|
r"""Return a Tukey window, also known as a tapered cosine window.
|
809
868
|
|
810
869
|
Parameters
|
@@ -821,6 +880,7 @@ def tukey(M, alpha=0.5, sym=True):
|
|
821
880
|
When True (default), generates a symmetric window, for use in filter
|
822
881
|
design.
|
823
882
|
When False, generates a periodic window, for use in spectral analysis.
|
883
|
+
%(xp_device_snippet)s
|
824
884
|
|
825
885
|
Returns
|
826
886
|
-------
|
@@ -863,32 +923,34 @@ def tukey(M, alpha=0.5, sym=True):
|
|
863
923
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
864
924
|
|
865
925
|
"""
|
926
|
+
xp = _namespace(xp)
|
927
|
+
|
866
928
|
if _len_guards(M):
|
867
|
-
return
|
929
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
868
930
|
|
869
931
|
if alpha <= 0:
|
870
|
-
return
|
932
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
871
933
|
elif alpha >= 1.0:
|
872
|
-
return hann(M, sym=sym)
|
934
|
+
return hann(M, sym=sym, xp=xp, device=device)
|
873
935
|
|
874
936
|
M, needs_trunc = _extend(M, sym)
|
875
937
|
|
876
|
-
n =
|
877
|
-
width = int(
|
938
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device)
|
939
|
+
width = int(math.floor(alpha*(M-1)/2.0))
|
878
940
|
n1 = n[0:width+1]
|
879
941
|
n2 = n[width+1:M-width-1]
|
880
942
|
n3 = n[M-width-1:]
|
881
943
|
|
882
|
-
w1 = 0.5 * (1 +
|
883
|
-
w2 =
|
884
|
-
w3 = 0.5 * (1 +
|
944
|
+
w1 = 0.5 * (1 + xp.cos(xp.pi * (-1 + 2.0*n1/alpha/(M-1))))
|
945
|
+
w2 = xp.ones(n2.shape, device=device)
|
946
|
+
w3 = 0.5 * (1 + xp.cos(xp.pi * (-2.0/alpha + 1 + 2.0*n3/alpha/(M-1))))
|
885
947
|
|
886
|
-
w =
|
948
|
+
w = xp.concat((w1, w2, w3))
|
887
949
|
|
888
950
|
return _truncate(w, needs_trunc)
|
889
951
|
|
890
952
|
|
891
|
-
def barthann(M, sym=True):
|
953
|
+
def barthann(M, sym=True, *, xp=None, device=None):
|
892
954
|
"""Return a modified Bartlett-Hann window.
|
893
955
|
|
894
956
|
Parameters
|
@@ -900,6 +962,7 @@ def barthann(M, sym=True):
|
|
900
962
|
When True (default), generates a symmetric window, for use in filter
|
901
963
|
design.
|
902
964
|
When False, generates a periodic window, for use in spectral analysis.
|
965
|
+
%(xp_device_snippet)s
|
903
966
|
|
904
967
|
Returns
|
905
968
|
-------
|
@@ -933,18 +996,20 @@ def barthann(M, sym=True):
|
|
933
996
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
934
997
|
|
935
998
|
"""
|
999
|
+
xp = _namespace(xp)
|
1000
|
+
|
936
1001
|
if _len_guards(M):
|
937
|
-
return
|
1002
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
938
1003
|
M, needs_trunc = _extend(M, sym)
|
939
1004
|
|
940
|
-
n =
|
941
|
-
fac =
|
942
|
-
w = 0.62 - 0.48 * fac + 0.38 *
|
1005
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device)
|
1006
|
+
fac = abs(n / (M - 1.0) - 0.5)
|
1007
|
+
w = 0.62 - 0.48 * fac + 0.38 * xp.cos(2 * xp.pi * fac)
|
943
1008
|
|
944
1009
|
return _truncate(w, needs_trunc)
|
945
1010
|
|
946
1011
|
|
947
|
-
def general_hamming(M, alpha, sym=True):
|
1012
|
+
def general_hamming(M, alpha, sym=True, *, xp=None, device=None):
|
948
1013
|
r"""Return a generalized Hamming window.
|
949
1014
|
|
950
1015
|
The generalized Hamming window is constructed by multiplying a rectangular
|
@@ -961,6 +1026,7 @@ def general_hamming(M, alpha, sym=True):
|
|
961
1026
|
When True (default), generates a symmetric window, for use in filter
|
962
1027
|
design.
|
963
1028
|
When False, generates a periodic window, for use in spectral analysis.
|
1029
|
+
%(xp_device_snippet)s
|
964
1030
|
|
965
1031
|
Returns
|
966
1032
|
-------
|
@@ -1030,10 +1096,13 @@ def general_hamming(M, alpha, sym=True):
|
|
1030
1096
|
>>> spatial_plot.legend(loc="upper right")
|
1031
1097
|
|
1032
1098
|
"""
|
1033
|
-
|
1099
|
+
xp = _namespace(xp)
|
1100
|
+
a = xp.asarray([alpha, 1. - alpha], dtype=xp.float64, device=device)
|
1101
|
+
device = xp_device(a)
|
1102
|
+
return _general_cosine_impl(M, a, xp, device, sym=sym)
|
1034
1103
|
|
1035
1104
|
|
1036
|
-
def hamming(M, sym=True):
|
1105
|
+
def hamming(M, sym=True, *, xp=None, device=None):
|
1037
1106
|
r"""Return a Hamming window.
|
1038
1107
|
|
1039
1108
|
The Hamming window is a taper formed by using a raised cosine with
|
@@ -1048,6 +1117,7 @@ def hamming(M, sym=True):
|
|
1048
1117
|
When True (default), generates a symmetric window, for use in filter
|
1049
1118
|
design.
|
1050
1119
|
When False, generates a periodic window, for use in spectral analysis.
|
1120
|
+
%(xp_device_snippet)s
|
1051
1121
|
|
1052
1122
|
Returns
|
1053
1123
|
-------
|
@@ -1109,10 +1179,10 @@ def hamming(M, sym=True):
|
|
1109
1179
|
|
1110
1180
|
"""
|
1111
1181
|
# Docstring adapted from NumPy's hamming function
|
1112
|
-
return general_hamming(M, 0.54, sym)
|
1182
|
+
return general_hamming(M, 0.54, sym, xp=xp, device=device)
|
1113
1183
|
|
1114
1184
|
|
1115
|
-
def kaiser(M, beta, sym=True):
|
1185
|
+
def kaiser(M, beta, sym=True, *, xp=None, device=None):
|
1116
1186
|
r"""Return a Kaiser window.
|
1117
1187
|
|
1118
1188
|
The Kaiser window is a taper formed by using a Bessel function.
|
@@ -1129,6 +1199,7 @@ def kaiser(M, beta, sym=True):
|
|
1129
1199
|
When True (default), generates a symmetric window, for use in filter
|
1130
1200
|
design.
|
1131
1201
|
When False, generates a periodic window, for use in spectral analysis.
|
1202
|
+
%(xp_device_snippet)s
|
1132
1203
|
|
1133
1204
|
Returns
|
1134
1205
|
-------
|
@@ -1218,20 +1289,22 @@ def kaiser(M, beta, sym=True):
|
|
1218
1289
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
1219
1290
|
|
1220
1291
|
"""
|
1292
|
+
xp = _namespace(xp)
|
1293
|
+
|
1221
1294
|
# Docstring adapted from NumPy's kaiser function
|
1222
1295
|
if _len_guards(M):
|
1223
|
-
return
|
1296
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1224
1297
|
M, needs_trunc = _extend(M, sym)
|
1225
1298
|
|
1226
|
-
n =
|
1299
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device)
|
1227
1300
|
alpha = (M - 1) / 2.0
|
1228
|
-
w = (special.i0(beta *
|
1229
|
-
special.i0(beta))
|
1301
|
+
w = (special.i0(beta * xp.sqrt(1 - ((n - alpha) / alpha) ** 2.0)) /
|
1302
|
+
special.i0(xp.asarray(beta, dtype=xp.float64)))
|
1230
1303
|
|
1231
1304
|
return _truncate(w, needs_trunc)
|
1232
1305
|
|
1233
1306
|
|
1234
|
-
def kaiser_bessel_derived(M, beta, *, sym=True):
|
1307
|
+
def kaiser_bessel_derived(M, beta, *, sym=True, xp=None, device=None):
|
1235
1308
|
"""Return a Kaiser-Bessel derived window.
|
1236
1309
|
|
1237
1310
|
Parameters
|
@@ -1248,6 +1321,7 @@ def kaiser_bessel_derived(M, beta, *, sym=True):
|
|
1248
1321
|
the other window functions and to be callable by `get_window`.
|
1249
1322
|
When True (default), generates a symmetric window, for use in filter
|
1250
1323
|
design.
|
1324
|
+
%(xp_device_snippet)s
|
1251
1325
|
|
1252
1326
|
Returns
|
1253
1327
|
-------
|
@@ -1297,27 +1371,29 @@ def kaiser_bessel_derived(M, beta, *, sym=True):
|
|
1297
1371
|
>>> fig.tight_layout()
|
1298
1372
|
>>> fig.show()
|
1299
1373
|
"""
|
1374
|
+
xp = _namespace(xp)
|
1375
|
+
|
1300
1376
|
if not sym:
|
1301
1377
|
raise ValueError(
|
1302
1378
|
"Kaiser-Bessel Derived windows are only defined for symmetric "
|
1303
1379
|
"shapes"
|
1304
1380
|
)
|
1305
1381
|
elif M < 1:
|
1306
|
-
return
|
1382
|
+
return xp.asarray([])
|
1307
1383
|
elif M % 2:
|
1308
1384
|
raise ValueError(
|
1309
1385
|
"Kaiser-Bessel Derived windows are only defined for even number "
|
1310
1386
|
"of points"
|
1311
1387
|
)
|
1312
1388
|
|
1313
|
-
kaiser_window = kaiser(M // 2 + 1, beta)
|
1314
|
-
csum =
|
1315
|
-
half_window =
|
1316
|
-
w =
|
1317
|
-
return w
|
1389
|
+
kaiser_window = kaiser(M // 2 + 1, beta, xp=xp, device=device)
|
1390
|
+
csum = xp.cumulative_sum(kaiser_window)
|
1391
|
+
half_window = xp.sqrt(csum[:-1] / csum[-1])
|
1392
|
+
w = xp.concat((half_window, xp.flip(half_window)), axis=0)
|
1393
|
+
return xp.asarray(w, device=device)
|
1318
1394
|
|
1319
1395
|
|
1320
|
-
def gaussian(M, std, sym=True):
|
1396
|
+
def gaussian(M, std, sym=True, *, xp=None, device=None):
|
1321
1397
|
r"""Return a Gaussian window.
|
1322
1398
|
|
1323
1399
|
Parameters
|
@@ -1331,6 +1407,7 @@ def gaussian(M, std, sym=True):
|
|
1331
1407
|
When True (default), generates a symmetric window, for use in filter
|
1332
1408
|
design.
|
1333
1409
|
When False, generates a periodic window, for use in spectral analysis.
|
1410
|
+
%(xp_device_snippet)s
|
1334
1411
|
|
1335
1412
|
Returns
|
1336
1413
|
-------
|
@@ -1370,18 +1447,20 @@ def gaussian(M, std, sym=True):
|
|
1370
1447
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
1371
1448
|
|
1372
1449
|
"""
|
1450
|
+
xp = _namespace(xp)
|
1451
|
+
|
1373
1452
|
if _len_guards(M):
|
1374
|
-
return
|
1453
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1375
1454
|
M, needs_trunc = _extend(M, sym)
|
1376
1455
|
|
1377
|
-
n =
|
1456
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device) - (M - 1.0) / 2.0
|
1378
1457
|
sig2 = 2 * std * std
|
1379
|
-
w =
|
1458
|
+
w = xp.exp(-n ** 2 / sig2)
|
1380
1459
|
|
1381
1460
|
return _truncate(w, needs_trunc)
|
1382
1461
|
|
1383
1462
|
|
1384
|
-
def general_gaussian(M, p, sig, sym=True):
|
1463
|
+
def general_gaussian(M, p, sig, sym=True, *, xp=None, device=None):
|
1385
1464
|
r"""Return a window with a generalized Gaussian shape.
|
1386
1465
|
|
1387
1466
|
Parameters
|
@@ -1398,6 +1477,7 @@ def general_gaussian(M, p, sig, sym=True):
|
|
1398
1477
|
When True (default), generates a symmetric window, for use in filter
|
1399
1478
|
design.
|
1400
1479
|
When False, generates a periodic window, for use in spectral analysis.
|
1480
|
+
%(xp_device_snippet)s
|
1401
1481
|
|
1402
1482
|
Returns
|
1403
1483
|
-------
|
@@ -1442,18 +1522,20 @@ def general_gaussian(M, p, sig, sym=True):
|
|
1442
1522
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
1443
1523
|
|
1444
1524
|
"""
|
1525
|
+
xp = _namespace(xp)
|
1526
|
+
|
1445
1527
|
if _len_guards(M):
|
1446
|
-
return
|
1528
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1447
1529
|
M, needs_trunc = _extend(M, sym)
|
1448
1530
|
|
1449
|
-
n =
|
1450
|
-
w =
|
1531
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device) - (M - 1.0) / 2.0
|
1532
|
+
w = xp.exp(-0.5 * abs(n / sig) ** (2 * p))
|
1451
1533
|
|
1452
1534
|
return _truncate(w, needs_trunc)
|
1453
1535
|
|
1454
1536
|
|
1455
1537
|
# `chebwin` contributed by Kumar Appaiah.
|
1456
|
-
def chebwin(M, at, sym=True):
|
1538
|
+
def chebwin(M, at, sym=True, *, xp=None, device=None):
|
1457
1539
|
r"""Return a Dolph-Chebyshev window.
|
1458
1540
|
|
1459
1541
|
Parameters
|
@@ -1467,6 +1549,7 @@ def chebwin(M, at, sym=True):
|
|
1467
1549
|
When True (default), generates a symmetric window, for use in filter
|
1468
1550
|
design.
|
1469
1551
|
When False, generates a periodic window, for use in spectral analysis.
|
1552
|
+
%(xp_device_snippet)s
|
1470
1553
|
|
1471
1554
|
Returns
|
1472
1555
|
-------
|
@@ -1539,7 +1622,9 @@ def chebwin(M, at, sym=True):
|
|
1539
1622
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
1540
1623
|
|
1541
1624
|
"""
|
1542
|
-
|
1625
|
+
xp = _namespace(xp)
|
1626
|
+
|
1627
|
+
if abs(at) < 45:
|
1543
1628
|
warnings.warn("This window is not suitable for spectral analysis "
|
1544
1629
|
"for attenuation values lower than about 45dB because "
|
1545
1630
|
"the equivalent noise bandwidth of a Chebyshev window "
|
@@ -1548,40 +1633,41 @@ def chebwin(M, at, sym=True):
|
|
1548
1633
|
"about 45 dB.",
|
1549
1634
|
stacklevel=2)
|
1550
1635
|
if _len_guards(M):
|
1551
|
-
return
|
1636
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1552
1637
|
M, needs_trunc = _extend(M, sym)
|
1553
1638
|
|
1554
1639
|
# compute the parameter beta
|
1555
1640
|
order = M - 1.0
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1641
|
+
_val = xp.asarray(10 ** (abs(at) / 20.), dtype=xp.float64, device=device)
|
1642
|
+
beta = xp.cosh(1.0 / order * xp.acosh(_val))
|
1643
|
+
k = xp.arange(M, dtype=xp.float64, device=device)
|
1644
|
+
x = beta * xp.cos(xp.pi * k / M)
|
1559
1645
|
# Find the window's DFT coefficients
|
1560
1646
|
# Use analytic definition of Chebyshev polynomial instead of expansion
|
1561
1647
|
# from scipy.special. Using the expansion in scipy.special leads to errors.
|
1562
|
-
p =
|
1563
|
-
p[x > 1] =
|
1564
|
-
p[x < -1] = (2 * (M % 2) - 1) *
|
1565
|
-
p[
|
1648
|
+
p = xp.zeros_like(x)
|
1649
|
+
p[x > 1] = xp.cosh(order * xp.acosh(x[x > 1]))
|
1650
|
+
p[x < -1] = (2 * (M % 2) - 1) * xp.cosh(order * xp.acosh(-x[x < -1]))
|
1651
|
+
p[abs(x) <= 1] = xp.cos(order * xp.acos(x[abs(x) <= 1]))
|
1566
1652
|
|
1567
1653
|
# Appropriate IDFT and filling up
|
1568
1654
|
# depending on even/odd M
|
1569
1655
|
if M % 2:
|
1570
|
-
w =
|
1656
|
+
w = xp.real(sp_fft.fft(p))
|
1571
1657
|
n = (M + 1) // 2
|
1572
1658
|
w = w[:n]
|
1573
|
-
w =
|
1659
|
+
w = xp.concat((xp.flip(w[1:n]), w))
|
1574
1660
|
else:
|
1575
|
-
p = p *
|
1576
|
-
w =
|
1661
|
+
p = p * xp.exp(1j * xp.pi / M * xp.arange(M, dtype=xp.float64, device=device))
|
1662
|
+
w = xp.real(sp_fft.fft(p))
|
1577
1663
|
n = M // 2 + 1
|
1578
|
-
w =
|
1579
|
-
w = w / max(w)
|
1664
|
+
w = xp.concat((xp.flip(w[1:n]), w[1:n]))
|
1665
|
+
w = w / xp.max(w)
|
1580
1666
|
|
1581
1667
|
return _truncate(w, needs_trunc)
|
1582
1668
|
|
1583
1669
|
|
1584
|
-
def cosine(M, sym=True):
|
1670
|
+
def cosine(M, sym=True, *, xp=None, device=None):
|
1585
1671
|
"""Return a window with a simple cosine shape.
|
1586
1672
|
|
1587
1673
|
Parameters
|
@@ -1593,6 +1679,7 @@ def cosine(M, sym=True):
|
|
1593
1679
|
When True (default), generates a symmetric window, for use in filter
|
1594
1680
|
design.
|
1595
1681
|
When False, generates a periodic window, for use in spectral analysis.
|
1682
|
+
%(xp_device_snippet)s
|
1596
1683
|
|
1597
1684
|
Returns
|
1598
1685
|
-------
|
@@ -1632,16 +1719,18 @@ def cosine(M, sym=True):
|
|
1632
1719
|
>>> plt.show()
|
1633
1720
|
|
1634
1721
|
"""
|
1722
|
+
xp = _namespace(xp)
|
1723
|
+
|
1635
1724
|
if _len_guards(M):
|
1636
|
-
return
|
1725
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1637
1726
|
M, needs_trunc = _extend(M, sym)
|
1638
1727
|
|
1639
|
-
w =
|
1728
|
+
w = xp.sin(xp.pi / M * (xp.arange(M, dtype=xp.float64, device=device) + .5))
|
1640
1729
|
|
1641
1730
|
return _truncate(w, needs_trunc)
|
1642
1731
|
|
1643
1732
|
|
1644
|
-
def exponential(M, center=None, tau=1., sym=True):
|
1733
|
+
def exponential(M, center=None, tau=1., sym=True, *, xp=None, device=None):
|
1645
1734
|
r"""Return an exponential (or Poisson) window.
|
1646
1735
|
|
1647
1736
|
Parameters
|
@@ -1661,6 +1750,7 @@ def exponential(M, center=None, tau=1., sym=True):
|
|
1661
1750
|
When True (default), generates a symmetric window, for use in filter
|
1662
1751
|
design.
|
1663
1752
|
When False, generates a periodic window, for use in spectral analysis.
|
1753
|
+
%(xp_device_snippet)s
|
1664
1754
|
|
1665
1755
|
Returns
|
1666
1756
|
-------
|
@@ -1715,22 +1805,24 @@ def exponential(M, center=None, tau=1., sym=True):
|
|
1715
1805
|
>>> plt.ylabel("Amplitude")
|
1716
1806
|
>>> plt.xlabel("Sample")
|
1717
1807
|
"""
|
1808
|
+
xp = _namespace(xp)
|
1809
|
+
|
1718
1810
|
if sym and center is not None:
|
1719
1811
|
raise ValueError("If sym==True, center must be None.")
|
1720
1812
|
if _len_guards(M):
|
1721
|
-
return
|
1813
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1722
1814
|
M, needs_trunc = _extend(M, sym)
|
1723
1815
|
|
1724
1816
|
if center is None:
|
1725
1817
|
center = (M-1) / 2
|
1726
1818
|
|
1727
|
-
n =
|
1728
|
-
w =
|
1819
|
+
n = xp.arange(0, M, dtype=xp.float64, device=device)
|
1820
|
+
w = xp.exp(-abs(n-center) / tau)
|
1729
1821
|
|
1730
1822
|
return _truncate(w, needs_trunc)
|
1731
1823
|
|
1732
1824
|
|
1733
|
-
def taylor(M, nbar=4, sll=30, norm=True, sym=True):
|
1825
|
+
def taylor(M, nbar=4, sll=30, norm=True, sym=True, *, xp=None, device=None):
|
1734
1826
|
"""
|
1735
1827
|
Return a Taylor window.
|
1736
1828
|
|
@@ -1763,6 +1855,7 @@ def taylor(M, nbar=4, sll=30, norm=True, sym=True):
|
|
1763
1855
|
When True (default), generates a symmetric window, for use in filter
|
1764
1856
|
design.
|
1765
1857
|
When False, generates a periodic window, for use in spectral analysis.
|
1858
|
+
%(xp_device_snippet)s
|
1766
1859
|
|
1767
1860
|
Returns
|
1768
1861
|
-------
|
@@ -1810,33 +1903,35 @@ def taylor(M, nbar=4, sll=30, norm=True, sym=True):
|
|
1810
1903
|
>>> plt.xlabel("Normalized frequency [cycles per sample]")
|
1811
1904
|
|
1812
1905
|
""" # noqa: E501
|
1906
|
+
xp = _namespace(xp)
|
1907
|
+
|
1813
1908
|
if _len_guards(M):
|
1814
|
-
return
|
1909
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
1815
1910
|
M, needs_trunc = _extend(M, sym)
|
1816
1911
|
|
1817
1912
|
# Original text uses a negative sidelobe level parameter and then negates
|
1818
1913
|
# it in the calculation of B. To keep consistent with other methods we
|
1819
1914
|
# assume the sidelobe level parameter to be positive.
|
1820
|
-
B = 10**(sll / 20)
|
1821
|
-
A =
|
1915
|
+
B = xp.asarray(10**(sll / 20), device=device)
|
1916
|
+
A = xp.acosh(B) / xp.pi
|
1822
1917
|
s2 = nbar**2 / (A**2 + (nbar - 0.5)**2)
|
1823
|
-
ma =
|
1918
|
+
ma = xp.arange(1, nbar, dtype=xp.float64, device=device)
|
1824
1919
|
|
1825
|
-
Fm =
|
1826
|
-
signs =
|
1920
|
+
Fm = xp.empty(nbar - 1, dtype=xp.float64, device=device)
|
1921
|
+
signs = xp.empty_like(ma)
|
1827
1922
|
signs[::2] = 1
|
1828
1923
|
signs[1::2] = -1
|
1829
1924
|
m2 = ma*ma
|
1830
1925
|
for mi, m in enumerate(ma):
|
1831
|
-
numer = signs[mi] *
|
1832
|
-
denom = 2 *
|
1926
|
+
numer = signs[mi] * xp.prod(1 - m2[mi]/s2/(A**2 + (ma - 0.5)**2))
|
1927
|
+
denom = 2 * xp.prod(1 - m2[mi]/m2[:mi]) * xp.prod(1 - m2[mi]/m2[mi+1:])
|
1833
1928
|
Fm[mi] = numer / denom
|
1834
1929
|
|
1835
1930
|
def W(n):
|
1836
|
-
return 1 + 2*
|
1837
|
-
2*
|
1931
|
+
return 1 + 2*xp.matmul(Fm, xp.cos(
|
1932
|
+
2*xp.pi*ma[:, xp.newaxis]*(n-M/2.+0.5)/M))
|
1838
1933
|
|
1839
|
-
w = W(
|
1934
|
+
w = W(xp.arange(M, dtype=xp.float64, device=device))
|
1840
1935
|
|
1841
1936
|
# normalize (Note that this is not described in the original text [1])
|
1842
1937
|
if norm:
|
@@ -1846,7 +1941,8 @@ def taylor(M, nbar=4, sll=30, norm=True, sym=True):
|
|
1846
1941
|
return _truncate(w, needs_trunc)
|
1847
1942
|
|
1848
1943
|
|
1849
|
-
def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False
|
1944
|
+
def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False,
|
1945
|
+
*, xp=None, device=None):
|
1850
1946
|
"""
|
1851
1947
|
Compute the Discrete Prolate Spheroidal Sequences (DPSS).
|
1852
1948
|
|
@@ -1880,6 +1976,7 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
1880
1976
|
return_ratios : bool, optional
|
1881
1977
|
If True, also return the concentration ratios in addition to the
|
1882
1978
|
windows.
|
1979
|
+
%(xp_device_snippet)s
|
1883
1980
|
|
1884
1981
|
Returns
|
1885
1982
|
-------
|
@@ -1937,12 +2034,12 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
1937
2034
|
... for win, c in ((win_dpss, 'k'), (win_kaiser, 'r')):
|
1938
2035
|
... win /= win.sum()
|
1939
2036
|
... axes[ai, 0].plot(win, color=c, lw=1.)
|
1940
|
-
... axes[ai, 0].set(xlim=[0, M-1], title=
|
2037
|
+
... axes[ai, 0].set(xlim=[0, M-1], title=rf'$\\alpha$ = {alpha}',
|
1941
2038
|
... ylabel='Amplitude')
|
1942
2039
|
... w, h = freqz(win)
|
1943
2040
|
... axes[ai, 1].plot(w, 20 * np.log10(np.abs(h)), color=c, lw=1.)
|
1944
2041
|
... axes[ai, 1].set(xlim=[0, np.pi],
|
1945
|
-
... title=
|
2042
|
+
... title=rf'$\\beta$ = {beta:0.2f}',
|
1946
2043
|
... ylabel='Magnitude (dB)')
|
1947
2044
|
>>> for ax in axes.ravel():
|
1948
2045
|
... ax.grid(True)
|
@@ -1959,8 +2056,8 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
1959
2056
|
>>> fig, ax = plt.subplots(1)
|
1960
2057
|
>>> ax.plot(win.T, linewidth=1.)
|
1961
2058
|
>>> ax.set(xlim=[0, M-1], ylim=[-0.1, 0.1], xlabel='Samples',
|
1962
|
-
... title='DPSS, M
|
1963
|
-
>>> ax.legend(['win[
|
2059
|
+
... title=f'DPSS, {M:d}, {NW:0.1f}')
|
2060
|
+
>>> ax.legend([f'win[{ii}] ({ratio:0.4f})'
|
1964
2061
|
... for ii, ratio in enumerate(eigvals)])
|
1965
2062
|
>>> fig.tight_layout()
|
1966
2063
|
>>> plt.show()
|
@@ -2009,8 +2106,8 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2009
2106
|
>>> fig.tight_layout()
|
2010
2107
|
|
2011
2108
|
"""
|
2012
|
-
|
2013
|
-
|
2109
|
+
xp = _namespace(xp)
|
2110
|
+
|
2014
2111
|
if norm is None:
|
2015
2112
|
norm = 'approximate' if Kmax is None else 2
|
2016
2113
|
known_norms = (2, 'approximate', 'subsample')
|
@@ -2021,6 +2118,13 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2021
2118
|
Kmax = 1
|
2022
2119
|
else:
|
2023
2120
|
singleton = False
|
2121
|
+
if _len_guards(M):
|
2122
|
+
if not return_ratios:
|
2123
|
+
return xp.ones(M, dtype=xp.float64)
|
2124
|
+
elif singleton:
|
2125
|
+
return xp.ones(M, dtype=xp.float64), 1.
|
2126
|
+
else:
|
2127
|
+
return xp.ones(M, dtype=xp.float64), xp.ones(1, dtype=xp.float64)
|
2024
2128
|
Kmax = operator.index(Kmax)
|
2025
2129
|
if not 0 < Kmax <= M:
|
2026
2130
|
raise ValueError('Kmax must be greater than 0 and less than M')
|
@@ -2030,7 +2134,7 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2030
2134
|
raise ValueError('NW must be positive')
|
2031
2135
|
M, needs_trunc = _extend(M, sym)
|
2032
2136
|
W = float(NW) / M
|
2033
|
-
nidx =
|
2137
|
+
nidx = xp.arange(M, dtype=xp.float64, device=device)
|
2034
2138
|
|
2035
2139
|
# Here we want to set up an optimization problem to find a sequence
|
2036
2140
|
# whose energy is maximally concentrated within band [-W,W].
|
@@ -2050,7 +2154,7 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2050
2154
|
# the main diagonal = ([M-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,M-1]
|
2051
2155
|
# and the first off-diagonal = t(M-t)/2, t=[1,2,...,M-1]
|
2052
2156
|
# [see Percival and Walden, 1993]
|
2053
|
-
d = ((M - 1 - 2 * nidx) / 2.) ** 2 *
|
2157
|
+
d = ((M - 1 - 2 * nidx) / 2.) ** 2 * xp.cos(xp.asarray(2 * xp.pi * W))
|
2054
2158
|
e = nidx[1:] * (M - nidx[1:]) / 2.
|
2055
2159
|
|
2056
2160
|
# only calculate the highest Kmax eigenvalues
|
@@ -2061,7 +2165,7 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2061
2165
|
|
2062
2166
|
# By convention (Percival and Walden, 1993 pg 379)
|
2063
2167
|
# * symmetric tapers (k=0,2,4,...) should have a positive average.
|
2064
|
-
fix_even = (windows[::2].sum(axis=1) < 0)
|
2168
|
+
fix_even = (windows[::2, ...].sum(axis=1) < 0)
|
2065
2169
|
for i, f in enumerate(fix_even):
|
2066
2170
|
if f:
|
2067
2171
|
windows[2 * i] *= -1
|
@@ -2072,19 +2176,20 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2072
2176
|
# algorithm that uses max(abs(w)), which is susceptible to numerical
|
2073
2177
|
# noise problems)
|
2074
2178
|
thresh = max(1e-7, 1. / M)
|
2075
|
-
for i, w in enumerate(windows[1::2]):
|
2179
|
+
for i, w in enumerate(windows[1::2, ...]):
|
2076
2180
|
if w[w * w > thresh][0] < 0:
|
2077
2181
|
windows[2 * i + 1] *= -1
|
2078
2182
|
|
2079
2183
|
# Now find the eigenvalues of the original spectral concentration problem
|
2080
2184
|
# Use the autocorr sequence technique from Percival and Walden, 1993 pg 390
|
2081
2185
|
if return_ratios:
|
2082
|
-
dpss_rxx = _fftautocorr(windows)
|
2083
|
-
r = 4 * W *
|
2186
|
+
dpss_rxx = _fftautocorr(xp.asarray(windows))
|
2187
|
+
r = 4 * W * xpx.sinc(xp.asarray(2 * W * nidx), xp=xp)
|
2084
2188
|
r[0] = 2 * W
|
2085
|
-
ratios =
|
2189
|
+
ratios = xp.matmul(dpss_rxx, r)
|
2086
2190
|
if singleton:
|
2087
2191
|
ratios = ratios[0]
|
2192
|
+
ratios = xp.asarray(ratios, device=device)
|
2088
2193
|
# Deal with sym and Kmax=None
|
2089
2194
|
if norm != 2:
|
2090
2195
|
windows /= windows.max()
|
@@ -2093,8 +2198,8 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2093
2198
|
correction = M**2 / float(M**2 + NW)
|
2094
2199
|
else:
|
2095
2200
|
s = sp_fft.rfft(windows[0])
|
2096
|
-
shift = -(1 - 1./M) *
|
2097
|
-
s[1:] *= 2 *
|
2201
|
+
shift = -(1 - 1./M) * xp.arange(1, M//2 + 1, dtype=xp.float64)
|
2202
|
+
s[1:] *= 2 * xp.exp(-1j * xp.pi * shift)
|
2098
2203
|
correction = M / s.real.sum()
|
2099
2204
|
windows *= correction
|
2100
2205
|
# else we're already l2 normed, so do nothing
|
@@ -2102,10 +2207,11 @@ def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False):
|
|
2102
2207
|
windows = windows[:, :-1]
|
2103
2208
|
if singleton:
|
2104
2209
|
windows = windows[0]
|
2210
|
+
windows = xp.asarray(windows, device=device)
|
2105
2211
|
return (windows, ratios) if return_ratios else windows
|
2106
2212
|
|
2107
2213
|
|
2108
|
-
def lanczos(M, *, sym=True):
|
2214
|
+
def lanczos(M, *, sym=True, xp=None, device=None):
|
2109
2215
|
r"""Return a Lanczos window also known as a sinc window.
|
2110
2216
|
|
2111
2217
|
Parameters
|
@@ -2117,6 +2223,7 @@ def lanczos(M, *, sym=True):
|
|
2117
2223
|
When True (default), generates a symmetric window, for use in filter
|
2118
2224
|
design.
|
2119
2225
|
When False, generates a periodic window, for use in spectral analysis.
|
2226
|
+
%(xp_device_snippet)s
|
2120
2227
|
|
2121
2228
|
Returns
|
2122
2229
|
-------
|
@@ -2183,22 +2290,24 @@ def lanczos(M, *, sym=True):
|
|
2183
2290
|
>>> fig.tight_layout()
|
2184
2291
|
>>> plt.show()
|
2185
2292
|
"""
|
2293
|
+
xp = _namespace(xp)
|
2294
|
+
|
2186
2295
|
if _len_guards(M):
|
2187
|
-
return
|
2296
|
+
return xp.ones(M, dtype=xp.float64, device=device)
|
2188
2297
|
M, needs_trunc = _extend(M, sym)
|
2189
2298
|
|
2190
2299
|
# To make sure that the window is symmetric, we concatenate the right hand
|
2191
2300
|
# half of the window and the flipped one which is the left hand half of
|
2192
2301
|
# the window.
|
2193
2302
|
def _calc_right_side_lanczos(n, m):
|
2194
|
-
return
|
2303
|
+
return xpx.sinc(2. * xp.arange(n, m, dtype=xp.float64) / (m - 1) - 1.0, xp=xp)
|
2195
2304
|
|
2196
2305
|
if M % 2 == 0:
|
2197
2306
|
wh = _calc_right_side_lanczos(M/2, M)
|
2198
|
-
w =
|
2307
|
+
w = xp.concat([xp.flip(wh), wh])
|
2199
2308
|
else:
|
2200
2309
|
wh = _calc_right_side_lanczos((M+1)/2, M)
|
2201
|
-
w =
|
2310
|
+
w = xp.concat([xp.flip(wh), xp.ones(1), wh])
|
2202
2311
|
|
2203
2312
|
return _truncate(w, needs_trunc)
|
2204
2313
|
|
@@ -2210,8 +2319,8 @@ def _fftautocorr(x):
|
|
2210
2319
|
x_fft = sp_fft.rfft(x, use_N, axis=-1)
|
2211
2320
|
cxy = sp_fft.irfft(x_fft * x_fft.conj(), n=use_N)[:, :N]
|
2212
2321
|
# Or equivalently (but in most cases slower):
|
2213
|
-
# cxy =
|
2214
|
-
#
|
2322
|
+
# cxy = xp.asarray([xp.convolve(xx, yy[::-1], mode='full')
|
2323
|
+
# for xx, yy in zip(x, x)])[:, N-1:2*N-1]
|
2215
2324
|
return cxy
|
2216
2325
|
|
2217
2326
|
|
@@ -2258,7 +2367,7 @@ for k, v in _win_equiv_raw.items():
|
|
2258
2367
|
_needs_param.update(k)
|
2259
2368
|
|
2260
2369
|
|
2261
|
-
def get_window(window, Nx, fftbins=True):
|
2370
|
+
def get_window(window, Nx, fftbins=True, *, xp=None, device=None):
|
2262
2371
|
"""
|
2263
2372
|
Return a window of a given length and type.
|
2264
2373
|
|
@@ -2273,6 +2382,7 @@ def get_window(window, Nx, fftbins=True):
|
|
2273
2382
|
`ifftshift` and be multiplied by the result of an FFT (see also
|
2274
2383
|
:func:`~scipy.fft.fftfreq`).
|
2275
2384
|
If False, create a "symmetric" window, for use in filter design.
|
2385
|
+
%(xp_device_snippet)s
|
2276
2386
|
|
2277
2387
|
Returns
|
2278
2388
|
-------
|
@@ -2358,6 +2468,11 @@ def get_window(window, Nx, fftbins=True):
|
|
2358
2468
|
raise ValueError(
|
2359
2469
|
f"{str(type(window))} as window type is not supported.") from e
|
2360
2470
|
|
2471
|
+
if winstr == 'general_cosine' and (xp is not None or device is not None):
|
2472
|
+
raise ValueError(
|
2473
|
+
'general_cosine window does not accept xp and device kwargs '
|
2474
|
+
)
|
2475
|
+
|
2361
2476
|
try:
|
2362
2477
|
winfunc = _win_equiv[winstr]
|
2363
2478
|
except KeyError as e:
|
@@ -2371,4 +2486,28 @@ def get_window(window, Nx, fftbins=True):
|
|
2371
2486
|
winfunc = kaiser
|
2372
2487
|
params = (Nx, beta)
|
2373
2488
|
|
2374
|
-
|
2489
|
+
if winfunc == general_cosine:
|
2490
|
+
return winfunc(*params, sym=sym)
|
2491
|
+
else:
|
2492
|
+
return winfunc(*params, sym=sym, xp=xp, device=device)
|
2493
|
+
|
2494
|
+
|
2495
|
+
########## complete the docstrings, on import
|
2496
|
+
_xp_device_snippet = {'xp_device_snippet':
|
2497
|
+
"""\
|
2498
|
+
xp : array_namespace, optional
|
2499
|
+
Optional array namespace.
|
2500
|
+
Should be compatible with the array API standard, or supported by array-api-compat.
|
2501
|
+
Default: ``numpy``
|
2502
|
+
device: any
|
2503
|
+
optional device specification for output. Should match one of the
|
2504
|
+
supported device specification in ``xp``.
|
2505
|
+
"""
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
|
2509
|
+
_names = [x for x in __all__ if x != 'general_cosine']
|
2510
|
+
for name in _names:
|
2511
|
+
window = vars()[name]
|
2512
|
+
window.__doc__ = doccer.docformat(window.__doc__, _xp_device_snippet)
|
2513
|
+
|