scipy 1.15.3__cp311-cp311-win_amd64.whl → 1.16.0rc2__cp311-cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/_cyutility.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_ccallback_c.cp311-win_amd64.pyd +0 -0
- scipy/_lib/_docscrape.py +1 -1
- scipy/_lib/_elementwise_iterative_method.py +15 -26
- scipy/_lib/_fpumode.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_fpumode.cp311-win_amd64.pyd +0 -0
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_ccallback.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_test_ccallback.cp311-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_call.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_call.cp311-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_def.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_def.cp311-win_amd64.pyd +0 -0
- scipy/_lib/_testutils.py +6 -2
- scipy/_lib/_uarray/_uarray.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/_uarray/_uarray.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/_lib/messagestream.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/cluster/_hierarchy.cp311-win_amd64.pyd +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp311-win_amd64.dll.a +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp311-win_amd64.pyd +0 -0
- scipy/cluster/_vq.cp311-win_amd64.dll.a +0 -0
- scipy/cluster/_vq.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/fft/_pocketfft/pypocketfft.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/fftpack/convolve.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_dop.cp311-win_amd64.pyd +0 -0
- scipy/integrate/_lsoda.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_lsoda.cp311-win_amd64.pyd +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_odepack.cp311-win_amd64.pyd +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_quadpack.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_test_multivariate.cp311-win_amd64.pyd +0 -0
- scipy/integrate/_test_odeint_banded.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_test_odeint_banded.cp311-win_amd64.pyd +0 -0
- scipy/integrate/_vode.cp311-win_amd64.dll.a +0 -0
- scipy/integrate/_vode.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_dfitpack.cp311-win_amd64.pyd +0 -0
- scipy/interpolate/_dierckx.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_dierckx.cp311-win_amd64.pyd +0 -0
- scipy/interpolate/_fitpack.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_fitpack.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_interpnd.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_ppoly.cp311-win_amd64.pyd +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_rbfinterp_pythran.cp311-win_amd64.pyd +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_rgi_cython.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/io/_test_fortran.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio5_utils.cp311-win_amd64.pyd +0 -0
- scipy/io/matlab/_mio_utils.cp311-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio_utils.cp311-win_amd64.pyd +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cp311-win_amd64.dll.a +0 -0
- scipy/io/matlab/_streams.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_cythonized_array_utils.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_interpolative.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_lu_cython.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_update.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_fblas.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_flapack.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_flapack.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_linalg_pythran.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_linalg_pythran.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_expm.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/_solve_toeplitz.cp311-win_amd64.pyd +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/cython_blas.cp311-win_amd64.pyd +0 -0
- scipy/linalg/cython_lapack.cp311-win_amd64.dll.a +0 -0
- scipy/linalg/cython_lapack.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/ndimage/_ctest.cp311-win_amd64.pyd +0 -0
- scipy/ndimage/_cytest.cp311-win_amd64.dll.a +0 -0
- scipy/ndimage/_cytest.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/ndimage/_nd_image.cp311-win_amd64.pyd +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cp311-win_amd64.dll.a +0 -0
- scipy/ndimage/_ni_label.cp311-win_amd64.pyd +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cp311-win_amd64.dll.a +0 -0
- scipy/ndimage/_rank_filter_1d.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/odr/__odrpack.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_bglu_dense.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_direct.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_group_columns.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_core.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_core.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_highs_options.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_highs_options.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_lbfgsb.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_lbfgsb.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_lsap.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_lsq/givens_elimination.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_minpack.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_moduleTNC.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_pava_pybind.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_slsqplib.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_trlib/_trlib.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_zeros.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/cython_optimize/_zeros.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_max_len_seq_inner.cp311-win_amd64.pyd +0 -0
- scipy/signal/_peak_finding_utils.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_peak_finding_utils.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_sigtools.cp311-win_amd64.pyd +0 -0
- scipy/signal/_sosfilt.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_sosfilt.cp311-win_amd64.pyd +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_spline.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/signal/_upfirdn_apply.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/_csparsetools.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/_sparsetools.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_flow.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_matching.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_matching.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_reordering.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_reordering.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_shortest_path.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_shortest_path.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_tools.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_tools.cp311-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_traversal.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_traversal.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_cpropack.cp311-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp311-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp311-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp311-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_ckdtree.cp311-win_amd64.pyd +0 -0
- scipy/spatial/_distance_pybind.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_pybind.cp311-win_amd64.pyd +0 -0
- scipy/spatial/_distance_wrap.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_wrap.cp311-win_amd64.pyd +0 -0
- scipy/spatial/_hausdorff.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_hausdorff.cp311-win_amd64.pyd +0 -0
- scipy/spatial/_qhull.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_qhull.cp311-win_amd64.pyd +0 -0
- scipy/spatial/_voronoi.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/_voronoi.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/transform/_rigid_transform.cp311-win_amd64.pyd +0 -0
- scipy/spatial/transform/_rotation.cp311-win_amd64.dll.a +0 -0
- scipy/spatial/transform/_rotation.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/special/_comb.cp311-win_amd64.pyd +0 -0
- scipy/special/_ellip_harm_2.cp311-win_amd64.dll.a +0 -0
- scipy/special/_ellip_harm_2.cp311-win_amd64.pyd +0 -0
- scipy/special/_gufuncs.cp311-win_amd64.dll.a +0 -0
- scipy/special/_gufuncs.cp311-win_amd64.pyd +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cp311-win_amd64.dll.a +0 -0
- scipy/special/_specfun.cp311-win_amd64.pyd +0 -0
- scipy/special/_special_ufuncs.cp311-win_amd64.dll.a +0 -0
- scipy/special/_special_ufuncs.cp311-win_amd64.pyd +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cp311-win_amd64.dll.a +0 -0
- scipy/special/_test_internal.cp311-win_amd64.pyd +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cp311-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs.cp311-win_amd64.pyd +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cp311-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs_cxx.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/special/cython_special.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_ansari_swilk_statistics.cp311-win_amd64.pyd +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_biasedurn.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_levy_stable/levyst.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_qmc_cy.cp311-win_amd64.pyd +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_qmvnt_cy.cp311-win_amd64.pyd +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_rcont/rcont.cp311-win_amd64.pyd +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_sobol.cp311-win_amd64.pyd +0 -0
- scipy/stats/_stats.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_stats.cp311-win_amd64.pyd +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_stats_pythran.cp311-win_amd64.pyd +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/interpolate/_bspl.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_cobyla.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_cobyla.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_cython_nnls.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_cython_nnls.cp311-win_amd64.pyd +0 -0
- scipy/optimize/_slsqp.cp311-win_amd64.dll.a +0 -0
- scipy/optimize/_slsqp.cp311-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.cp311-win_amd64.dll.a +0 -0
- scipy/stats/_mvn.cp311-win_amd64.pyd +0 -0
- scipy-1.15.3.dist-info/DELVEWHEEL +0 -2
- /scipy-1.15.3-cp311-cp311-win_amd64.whl → /scipy-1.16.0rc2-cp311-cp311-win_amd64.whl +0 -0
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/WHEEL +0 -0
scipy/ndimage/_filters.py
CHANGED
@@ -33,8 +33,10 @@ import numbers
|
|
33
33
|
import warnings
|
34
34
|
import numpy as np
|
35
35
|
import operator
|
36
|
+
import math
|
36
37
|
|
37
38
|
from scipy._lib._util import normalize_axis_index
|
39
|
+
from scipy._lib._array_api import array_namespace, is_cupy, xp_size
|
38
40
|
from . import _ni_support
|
39
41
|
from . import _nd_image
|
40
42
|
from . import _ni_docstrings
|
@@ -47,7 +49,433 @@ __all__ = ['correlate1d', 'convolve1d', 'gaussian_filter1d', 'gaussian_filter',
|
|
47
49
|
'uniform_filter1d', 'uniform_filter', 'minimum_filter1d',
|
48
50
|
'maximum_filter1d', 'minimum_filter', 'maximum_filter',
|
49
51
|
'rank_filter', 'median_filter', 'percentile_filter',
|
50
|
-
'generic_filter1d', 'generic_filter']
|
52
|
+
'generic_filter1d', 'generic_filter', 'vectorized_filter']
|
53
|
+
|
54
|
+
|
55
|
+
def _vectorized_filter_iv(input, function, size, footprint, output, mode, cval, origin,
|
56
|
+
axes, batch_memory):
|
57
|
+
xp = array_namespace(input, footprint, output)
|
58
|
+
|
59
|
+
# vectorized_filter input validation and standardization
|
60
|
+
input = xp.asarray(input)
|
61
|
+
|
62
|
+
if not callable(function):
|
63
|
+
raise ValueError("`function` must be a callable.")
|
64
|
+
|
65
|
+
if size is None and footprint is None:
|
66
|
+
raise ValueError("Either `size` or `footprint` must be provided.")
|
67
|
+
|
68
|
+
if size is not None and footprint is not None:
|
69
|
+
raise ValueError("Either `size` or `footprint` may be provided, not both.")
|
70
|
+
|
71
|
+
if axes is None:
|
72
|
+
axes = tuple(range(-input.ndim, 0))
|
73
|
+
elif np.isscalar(axes):
|
74
|
+
axes = (axes,)
|
75
|
+
n_axes = len(axes)
|
76
|
+
n_batch = input.ndim - n_axes
|
77
|
+
|
78
|
+
if n_axes > input.ndim:
|
79
|
+
message = ("The length of `axes` may not exceed the dimensionality of `input`"
|
80
|
+
"(`input.ndim`).")
|
81
|
+
raise ValueError(message)
|
82
|
+
|
83
|
+
# Either footprint or size must be provided
|
84
|
+
footprinted_function = function
|
85
|
+
if size is not None:
|
86
|
+
# If provided, size must be an integer or tuple of integers.
|
87
|
+
size = (size,)*n_axes if np.isscalar(size) else tuple(size)
|
88
|
+
valid = [xp.isdtype(xp.asarray(i).dtype, 'integral') and i > 0 for i in size]
|
89
|
+
if not all(valid):
|
90
|
+
raise ValueError("All elements of `size` must be positive integers.")
|
91
|
+
else:
|
92
|
+
# If provided, `footprint` must be array-like
|
93
|
+
footprint = xp.asarray(footprint, dtype=xp.bool)
|
94
|
+
size = footprint.shape
|
95
|
+
def footprinted_function(input, *args, axis=-1, **kwargs):
|
96
|
+
return function(input[..., footprint], *args, axis=-1, **kwargs)
|
97
|
+
|
98
|
+
# And by now, the dimensionality of the footprint must equal the number of axes
|
99
|
+
if n_axes != len(size):
|
100
|
+
message = ("`axes` must be compatible with the dimensionality "
|
101
|
+
"of the window specified by `size` or `footprint`.")
|
102
|
+
raise ValueError(message)
|
103
|
+
|
104
|
+
# If this is not *equal* to the dimensionality of `input`, then `axes`
|
105
|
+
# must be a provided tuple, and its length must equal the core dimensionality.
|
106
|
+
elif n_axes < input.ndim:
|
107
|
+
if axes is None:
|
108
|
+
message = ("`axes` must be provided if the dimensionality of the window "
|
109
|
+
"(`len(size)` or `footprint.ndim`) does not equal the number "
|
110
|
+
"of axes of `input` (`input.ndim`).")
|
111
|
+
raise ValueError(message)
|
112
|
+
else:
|
113
|
+
axes = tuple(range(-n_axes, 0)) if axes is None else axes
|
114
|
+
|
115
|
+
axes = (axes,) if np.isscalar(axes) else axes
|
116
|
+
|
117
|
+
# If `origin` is provided, then it must be "broadcastable" to a tuple with length
|
118
|
+
# equal to the core dimensionality.
|
119
|
+
if origin is None:
|
120
|
+
origin = (0,) * n_axes
|
121
|
+
else:
|
122
|
+
origin = (origin,)*n_axes if np.isscalar(origin) else tuple(origin)
|
123
|
+
integral = [xp.isdtype(xp.asarray(i).dtype, 'integral') for i in origin]
|
124
|
+
if not all(integral):
|
125
|
+
raise ValueError("All elements of `origin` must be integers.")
|
126
|
+
if not len(origin) == n_axes:
|
127
|
+
message = ("`origin` must be an integer or tuple of integers with length "
|
128
|
+
"equal to the number of axes.")
|
129
|
+
raise ValueError(message)
|
130
|
+
|
131
|
+
# mode must be one of the allowed strings, and we should convert it to the
|
132
|
+
# value required by `np.pad`/`cp.pad` here.
|
133
|
+
valid_modes = {'reflect', 'constant', 'nearest', 'mirror', 'wrap',
|
134
|
+
'grid-mirror', 'grid-constant', 'grid-wrap', 'valid'}
|
135
|
+
if mode not in valid_modes:
|
136
|
+
raise ValueError(f"`mode` must be one of {valid_modes}.")
|
137
|
+
mode_map = {'nearest': 'edge', 'reflect': 'symmetric', 'mirror': 'reflect',
|
138
|
+
'grid-mirror': 'reflect', 'grid-constant': 'constant',
|
139
|
+
'grid-wrap': 'wrap'}
|
140
|
+
mode = mode_map.get(mode, mode)
|
141
|
+
|
142
|
+
if mode == 'valid' and any(origin):
|
143
|
+
raise ValueError("`mode='valid'` is incompatible with use of `origin`.")
|
144
|
+
|
145
|
+
if cval is None:
|
146
|
+
cval = 0.0
|
147
|
+
elif mode != 'constant':
|
148
|
+
raise ValueError("Use of `cval` is compatible only with `mode='constant'`.")
|
149
|
+
|
150
|
+
# `cval` must be a scalar or "broadcastable" to a tuple with the same
|
151
|
+
# dimensionality of `input`. (Full input validation done by `np.pad`/`cp.pad`.)
|
152
|
+
if not xp.isdtype(xp.asarray(cval).dtype, 'numeric'):
|
153
|
+
raise ValueError("`cval` must include only numbers.")
|
154
|
+
|
155
|
+
# `batch_memory` must be a positive number.
|
156
|
+
temp = xp.asarray(batch_memory)
|
157
|
+
if temp.ndim != 0 or (not xp.isdtype(temp.dtype, 'numeric')) or temp <= 0:
|
158
|
+
raise ValueError("`batch_memory` must be positive number.")
|
159
|
+
|
160
|
+
# For simplicity, work with `axes` at the end.
|
161
|
+
working_axes = tuple(range(-n_axes, 0))
|
162
|
+
input = xp.moveaxis(input, axes, working_axes)
|
163
|
+
output = (xp.moveaxis(output, axes, working_axes)
|
164
|
+
if output is not None else output)
|
165
|
+
|
166
|
+
# Wrap the function to limit maximum memory usage, deal with `footprint`,
|
167
|
+
# and populate `output`. The latter requires some verbosity because we
|
168
|
+
# don't know the output dtype.
|
169
|
+
def wrapped_function(view, output=output):
|
170
|
+
kwargs = {'axis': working_axes}
|
171
|
+
|
172
|
+
if working_axes == ():
|
173
|
+
return footprinted_function(xp.asarray(view), **kwargs)
|
174
|
+
|
175
|
+
# for now, assume we only have to iterate over zeroth axis
|
176
|
+
chunk_size = math.prod(view.shape[1:]) * view.dtype.itemsize
|
177
|
+
slices_per_batch = min(view.shape[0], batch_memory // chunk_size)
|
178
|
+
if slices_per_batch < 1:
|
179
|
+
raise ValueError("`batch_memory` is insufficient for minimum chunk size.")
|
180
|
+
|
181
|
+
elif slices_per_batch == view.shape[0]:
|
182
|
+
if output is None:
|
183
|
+
return footprinted_function(xp.asarray(view), **kwargs)
|
184
|
+
else:
|
185
|
+
output[...] = footprinted_function(xp.asarray(view), **kwargs)
|
186
|
+
return output
|
187
|
+
|
188
|
+
for i in range(0, view.shape[0], slices_per_batch):
|
189
|
+
i2 = min(i + slices_per_batch, view.shape[0])
|
190
|
+
if output is None:
|
191
|
+
# Look at the dtype before allocating the array. (In a follow-up, we
|
192
|
+
# can also look at the shape to support non-scalar elements.)
|
193
|
+
temp = footprinted_function(xp.asarray(view[i:i2]), **kwargs)
|
194
|
+
output = xp.empty(view.shape[:-n_axes], dtype=temp.dtype)
|
195
|
+
output[i:i2, ...] = temp
|
196
|
+
else:
|
197
|
+
output[i:i2, ...] = footprinted_function(xp.asarray(view[i:i2]),
|
198
|
+
**kwargs)
|
199
|
+
return output
|
200
|
+
|
201
|
+
return (input, wrapped_function, size, mode, cval, origin,
|
202
|
+
working_axes, axes, n_axes, n_batch, xp)
|
203
|
+
|
204
|
+
|
205
|
+
@_ni_docstrings.docfiller
|
206
|
+
def vectorized_filter(input, function, *, size=None, footprint=None, output=None,
|
207
|
+
mode='reflect', cval=None, origin=None, axes=None,
|
208
|
+
batch_memory=2**30):
|
209
|
+
"""Filter an array with a vectorized Python callable as the kernel
|
210
|
+
|
211
|
+
Parameters
|
212
|
+
----------
|
213
|
+
%(input)s
|
214
|
+
function : callable
|
215
|
+
Kernel to apply over a window centered at each element of `input`.
|
216
|
+
Callable must have signature::
|
217
|
+
|
218
|
+
function(window: ndarray, *, axis: int | tuple) -> scalar
|
219
|
+
|
220
|
+
where ``axis`` specifies the axis (or axes) of ``window`` along which
|
221
|
+
the filter function is evaluated.
|
222
|
+
size : scalar or tuple, optional
|
223
|
+
See `footprint` below. Ignored if `footprint` is given.
|
224
|
+
footprint : array, optional
|
225
|
+
Either `size` or `footprint` must be defined. `size` gives
|
226
|
+
the shape that is taken from the input array, at every element
|
227
|
+
position, to define the input to the filter function.
|
228
|
+
`footprint` is a boolean array that specifies (implicitly) a
|
229
|
+
shape, but also which of the elements within this shape will get
|
230
|
+
passed to the filter function. Thus ``size=(n, m)`` is equivalent
|
231
|
+
to ``footprint=np.ones((n, m))``.
|
232
|
+
We adjust `size` to the number of dimensions indicated by `axes`.
|
233
|
+
For instance, if `axes` is ``(0, 2, 1)`` and ``n`` is passed for ``size``,
|
234
|
+
then the effective `size` is ``(n, n, n)``.
|
235
|
+
%(output)s
|
236
|
+
mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
|
237
|
+
The `mode` parameter determines how the input array is extended
|
238
|
+
beyond its boundaries. Default is 'reflect'. Behavior for each valid
|
239
|
+
value is as follows:
|
240
|
+
|
241
|
+
'reflect' (`d c b a | a b c d | d c b a`)
|
242
|
+
The input is extended by reflecting about the edge of the last
|
243
|
+
pixel. This mode is also sometimes referred to as half-sample
|
244
|
+
symmetric.
|
245
|
+
|
246
|
+
'constant' (`k k k k | a b c d | k k k k`)
|
247
|
+
The input is extended by filling all values beyond the edge with
|
248
|
+
the same constant value, defined by the `cval` parameter.
|
249
|
+
|
250
|
+
'nearest' (`a a a a | a b c d | d d d d`)
|
251
|
+
The input is extended by replicating the last pixel.
|
252
|
+
|
253
|
+
'mirror' (`d c b | a b c d | c b a`)
|
254
|
+
The input is extended by reflecting about the center of the last
|
255
|
+
pixel. This mode is also sometimes referred to as whole-sample
|
256
|
+
symmetric.
|
257
|
+
|
258
|
+
'wrap' (`a b c d | a b c d | a b c d`)
|
259
|
+
The input is extended by wrapping around to the opposite edge.
|
260
|
+
|
261
|
+
'valid' (`| a b c d |`)
|
262
|
+
The input is not extended; rather, the output shape is reduced depending
|
263
|
+
on the window size according to the following calculation::
|
264
|
+
|
265
|
+
window_size = np.asarray(size if size is not None else footprint.shape)
|
266
|
+
output_shape = np.asarray(input.shape)
|
267
|
+
output_shape[np.asarray(axes)] -= (window_size - 1)
|
268
|
+
|
269
|
+
%(cval)s
|
270
|
+
%(origin_multiple)s
|
271
|
+
axes : tuple of int, optional
|
272
|
+
If None, `input` is filtered along all axes. Otherwise, `input` is filtered
|
273
|
+
along the specified axes. When `axes` is specified, the dimensionality of
|
274
|
+
`footprint` and the length of any tuples used for `size` or `origin` must
|
275
|
+
match the length of `axes`. The ith axis of `footprint` and the ith element
|
276
|
+
in these tuples corresponds to the ith element of `axes`.
|
277
|
+
batch_memory : int, default: 2**30
|
278
|
+
The maximum number of bytes occupied by data in the ``window``
|
279
|
+
array passed to ``function``.
|
280
|
+
|
281
|
+
Returns
|
282
|
+
-------
|
283
|
+
output : ndarray
|
284
|
+
Filtered array. The dtype is the output dtype of `function`. If `function` is
|
285
|
+
scalar-valued when applied to a single window, the shape of the output is that
|
286
|
+
of `input` (unless ``mode=='valid'``; see `mode` documentation). If `function`
|
287
|
+
is multi-valued when applied to a single window, the placement of the
|
288
|
+
corresponding dimensions within the output shape depends entirely on the
|
289
|
+
behavior of `function`; see Examples.
|
290
|
+
|
291
|
+
See Also
|
292
|
+
--------
|
293
|
+
scipy.ndimage.generic_filter
|
294
|
+
|
295
|
+
Notes
|
296
|
+
-----
|
297
|
+
This function works by padding `input` according to `mode`, then calling the
|
298
|
+
provided `function` on chunks of a sliding window view over the padded array.
|
299
|
+
This approach is very simple and flexible, and so the function has many features
|
300
|
+
not offered by some other filter functions (e.g. memory control, ``float16``
|
301
|
+
and complex dtype support, and any NaN-handling features provided by the
|
302
|
+
`function` argument).
|
303
|
+
|
304
|
+
However, this brute-force approach may perform considerable redundant work.
|
305
|
+
Use a specialized filter (e.g. `minimum_filter` instead of this function with
|
306
|
+
`numpy.min` as the callable; `uniform_filter` instead of this function with
|
307
|
+
`numpy.mean` as the callable) when possible, as it may use a more efficient
|
308
|
+
algorithm.
|
309
|
+
|
310
|
+
When a specialized filter is not available, this function is ideal when `function`
|
311
|
+
is a vectorized, pure-Python callable. Even better performance may be possible
|
312
|
+
by passing a `scipy.LowLevelCallable` to `generic_filter`. `generic_filter` may
|
313
|
+
also be preferred for expensive callables with large filter footprints and
|
314
|
+
callables that are not vectorized (i.e. those without ``axis`` support).
|
315
|
+
|
316
|
+
This function does not provide the ``extra_arguments`` or ``extra_keywords``
|
317
|
+
arguments provided by some `ndimage` functions. There are two reasons:
|
318
|
+
|
319
|
+
- The passthrough functionality can be achieved by the user: simply wrap the
|
320
|
+
original callable in another function that provides the required arguments;
|
321
|
+
e.g., ``function=lambda input, axis: function(input, *extra_arguments, axis=axis, **extra_keywords)``.
|
322
|
+
- There are use cases for `function` to be passed additional *sliding-window data*
|
323
|
+
to `function` besides `input`. This is not yet implemented, but we reserve
|
324
|
+
these argument names for such a feature, which would add capability rather than
|
325
|
+
providing a duplicate interface to existing capability.
|
326
|
+
|
327
|
+
Examples
|
328
|
+
--------
|
329
|
+
Suppose we wish to perform a median filter with even window size on a ``float16``
|
330
|
+
image. Furthermore, the image has NaNs that we wish to be ignored (and effectively
|
331
|
+
removed by the filter). `median_filter` does not support ``float16`` data, its
|
332
|
+
behavior when NaNs are present is not defined, and for even window sizes, it does
|
333
|
+
not return the usual sample median - the average of the two middle elements. This
|
334
|
+
would be an excellent use case for `vectorized_filter` with
|
335
|
+
``function=np.nanmedian``, which supports the required interface: it accepts a
|
336
|
+
data array of any shape as the first positional argument, and tuple of axes as
|
337
|
+
keyword argument ``axis``.
|
338
|
+
|
339
|
+
>>> import numpy as np
|
340
|
+
>>> from scipy import datasets, ndimage
|
341
|
+
>>> from scipy.ndimage import vectorized_filter
|
342
|
+
>>> import matplotlib.pyplot as plt
|
343
|
+
>>> ascent = ndimage.zoom(datasets.ascent(), 0.5).astype(np.float16)
|
344
|
+
>>> ascent[::16, ::16] = np.nan
|
345
|
+
>>> result = vectorized_filter(ascent, function=np.nanmedian, size=4)
|
346
|
+
|
347
|
+
Plot the original and filtered images.
|
348
|
+
|
349
|
+
>>> fig = plt.figure()
|
350
|
+
>>> plt.gray() # show the filtered result in grayscale
|
351
|
+
>>> ax1 = fig.add_subplot(121) # left side
|
352
|
+
>>> ax2 = fig.add_subplot(122) # right side
|
353
|
+
>>> ax1.imshow(ascent)
|
354
|
+
>>> ax2.imshow(result)
|
355
|
+
>>> fig.tight_layout()
|
356
|
+
>>> plt.show()
|
357
|
+
|
358
|
+
Another need satisfied by `vectorized_filter` is to perform multi-output
|
359
|
+
filters. For instance, suppose we wish to filter an image according to the 25th
|
360
|
+
and 75th percentiles in addition to the median. We could perform the three
|
361
|
+
filters separately.
|
362
|
+
|
363
|
+
>>> ascent = ndimage.zoom(datasets.ascent(), 0.5)
|
364
|
+
>>> def get_quantile_fun(p):
|
365
|
+
... return lambda x, axis: np.quantile(x, p, axis=axis)
|
366
|
+
>>> ref1 = vectorized_filter(ascent, get_quantile_fun(0.25), size=4)
|
367
|
+
>>> ref2 = vectorized_filter(ascent, get_quantile_fun(0.50), size=4)
|
368
|
+
>>> ref3 = vectorized_filter(ascent, get_quantile_fun(0.75), size=4)
|
369
|
+
>>> ref = np.stack([ref1, ref2, ref3])
|
370
|
+
|
371
|
+
However, `vectorized_filter` also supports filters that return multiple outputs
|
372
|
+
as long as `output` is unspecified and `batch_memory` is sufficiently high to
|
373
|
+
perform the calculation in a single chunk.
|
374
|
+
|
375
|
+
>>> def quartiles(x, axis):
|
376
|
+
... return np.quantile(x, [0.25, 0.50, 0.75], axis=axis)
|
377
|
+
>>> res = vectorized_filter(ascent, quartiles, size=4, batch_memory=np.inf)
|
378
|
+
>>> np.all(np.isclose(res, ref))
|
379
|
+
np.True_
|
380
|
+
|
381
|
+
The placement of the additional dimension(s) corresponding with multiple outputs
|
382
|
+
is at the discretion of `function`. `quartiles` happens to prepend one dimension
|
383
|
+
corresponding with the three outputs simply because that is the behavior of
|
384
|
+
`np.quantile`:
|
385
|
+
|
386
|
+
>>> res.shape == (3,) + ascent.shape
|
387
|
+
True
|
388
|
+
|
389
|
+
If we wished for this dimension to be appended:
|
390
|
+
|
391
|
+
>>> def quartiles(x, axis):
|
392
|
+
... return np.moveaxis(np.quantile(x, [0.25, 0.50, 0.75], axis=axis), 0, -1)
|
393
|
+
>>> res = vectorized_filter(ascent, quartiles, size=4, batch_memory=np.inf)
|
394
|
+
>>> res.shape == ascent.shape + (3,)
|
395
|
+
True
|
396
|
+
|
397
|
+
Suppose we wish to implment a "mode" filter - a filter that selects the most
|
398
|
+
frequently occuring value within the window. A simple (but rather slow)
|
399
|
+
approach is to use `generic_filter` with `scipy.stats.mode`.
|
400
|
+
|
401
|
+
>>> from scipy import stats
|
402
|
+
>>> rng = np.random.default_rng(3195824598724609246)
|
403
|
+
>>> input = rng.integers(255, size=(50, 50)).astype(np.uint8)
|
404
|
+
>>> def simple_mode(input):
|
405
|
+
... return stats.mode(input, axis=None).mode
|
406
|
+
>>> ref = ndimage.generic_filter(input, simple_mode, size=5)
|
407
|
+
|
408
|
+
If speed is important, `vectorized_filter` can take advantage of the performance
|
409
|
+
benefit of a vectorized callable.
|
410
|
+
|
411
|
+
>>> def vectorized_mode(x, axis=(-1,)):
|
412
|
+
... n_axes = 1 if np.isscalar(axis) else len(axis)
|
413
|
+
... x = np.moveaxis(x, axis, tuple(range(-n_axes, 0)))
|
414
|
+
... x = np.reshape(x, x.shape[:-n_axes] + (-1,))
|
415
|
+
... y = np.sort(x, axis=-1)
|
416
|
+
... i = np.concatenate([np.ones(y.shape[:-1] + (1,), dtype=bool),
|
417
|
+
... y[..., :-1] != y[..., 1:]], axis=-1)
|
418
|
+
... indices = np.arange(y.size)[i.ravel()]
|
419
|
+
... counts = np.diff(indices, append=y.size)
|
420
|
+
... counts = np.reshape(np.repeat(counts, counts), y.shape)
|
421
|
+
... k = np.argmax(counts, axis=-1, keepdims=True)
|
422
|
+
... return np.take_along_axis(y, k, axis=-1)[..., 0]
|
423
|
+
>>> res = vectorized_filter(input, vectorized_mode, size=5)
|
424
|
+
>>> np.all(res == ref)
|
425
|
+
np.True_
|
426
|
+
|
427
|
+
Depending on the machine, the `vectorized_filter` version may be as much as
|
428
|
+
100x faster.
|
429
|
+
|
430
|
+
""" # noqa: E501
|
431
|
+
|
432
|
+
(input, function, size, mode, cval, origin, working_axes, axes, n_axes, n_batch, xp
|
433
|
+
) = _vectorized_filter_iv(input, function, size, footprint, output, mode, cval,
|
434
|
+
origin, axes, batch_memory)
|
435
|
+
|
436
|
+
# `np.pad`/`cp.pad` raises with these sorts of cases, but the best result is
|
437
|
+
# probably to return the original array. It could be argued that we should call
|
438
|
+
# the function on the empty array with `axis=None` just to determine the output
|
439
|
+
# dtype, but I can also see rationale against that.
|
440
|
+
if xp_size(input) == 0:
|
441
|
+
return xp.asarray(input)
|
442
|
+
|
443
|
+
# This seems to be defined.
|
444
|
+
if input.ndim == 0 and size == ():
|
445
|
+
return xp.asarray(function(input) if footprint is None
|
446
|
+
else function(input[footprint]))
|
447
|
+
|
448
|
+
if is_cupy(xp):
|
449
|
+
# CuPy is the only GPU backend that has `pad` (with all modes)
|
450
|
+
# and `sliding_window_view`. An enhancement would be to use
|
451
|
+
# no-copy conversion to CuPy whenever the data is on the GPU.
|
452
|
+
cp = xp # let there be no ambiguity!
|
453
|
+
swv = cp.lib.stride_tricks.sliding_window_view
|
454
|
+
pad = cp.pad
|
455
|
+
else:
|
456
|
+
# Try to perform no-copy conversion to NumPy for padding and
|
457
|
+
# `sliding_window_view`. (If that fails, fine - for now, the only
|
458
|
+
# GPU backend we support is CuPy.)
|
459
|
+
swv = np.lib.stride_tricks.sliding_window_view
|
460
|
+
pad = np.pad
|
461
|
+
input = np.asarray(input)
|
462
|
+
cval = np.asarray(cval)[()] if mode == 'constant' else None
|
463
|
+
|
464
|
+
# Border the image according to `mode` and `offset`.
|
465
|
+
if mode != 'valid':
|
466
|
+
kwargs = {'constant_values': cval} if mode == 'constant' else {}
|
467
|
+
borders = tuple((i//2 + j, (i-1)//2 - j) for i, j in zip(size, origin))
|
468
|
+
bordered_input = pad(input, ((0, 0),)*n_batch + borders, mode=mode, **kwargs)
|
469
|
+
else:
|
470
|
+
bordered_input = input
|
471
|
+
|
472
|
+
# Evaluate function with sliding window view. Function is already wrapped to
|
473
|
+
# manage memory, deal with `footprint`, populate `output`, etc.
|
474
|
+
view = swv(bordered_input, size, working_axes)
|
475
|
+
res = function(view)
|
476
|
+
|
477
|
+
# move working_axes back to original positions
|
478
|
+
return xp.moveaxis(res, working_axes, axes)
|
51
479
|
|
52
480
|
|
53
481
|
def _invalid_origin(origin, lenw):
|
@@ -738,7 +1166,7 @@ def generic_gradient_magnitude(input, derivative, output=None,
|
|
738
1166
|
|
739
1167
|
Returns
|
740
1168
|
-------
|
741
|
-
|
1169
|
+
generic_gradient_magnitude : ndarray
|
742
1170
|
Filtered array. Has the same shape as `input`.
|
743
1171
|
|
744
1172
|
"""
|
@@ -1152,6 +1580,8 @@ def uniform_filter(input, size=3, output=None, mode="reflect",
|
|
1152
1580
|
with a limited precision, the results may be imprecise because
|
1153
1581
|
intermediate results may be stored with insufficient precision.
|
1154
1582
|
|
1583
|
+
%(nan)s
|
1584
|
+
|
1155
1585
|
Examples
|
1156
1586
|
--------
|
1157
1587
|
>>> from scipy import ndimage, datasets
|
@@ -1469,6 +1899,8 @@ def maximum_filter(input, size=None, footprint=None, output=None,
|
|
1469
1899
|
A sequence of modes (one per axis) is only supported when the footprint is
|
1470
1900
|
separable. Otherwise, a single mode string must be provided.
|
1471
1901
|
|
1902
|
+
%(nan)s
|
1903
|
+
|
1472
1904
|
Examples
|
1473
1905
|
--------
|
1474
1906
|
>>> from scipy import ndimage, datasets
|
@@ -1667,6 +2099,15 @@ def median_filter(input, size=None, footprint=None, output=None,
|
|
1667
2099
|
the specialised function `scipy.signal.medfilt2d` may be faster. It is
|
1668
2100
|
however limited to constant mode with ``cval=0``.
|
1669
2101
|
|
2102
|
+
The filter always returns the argument that would appear at index ``n // 2`` in
|
2103
|
+
a sorted array, where ``n`` is the number of elements in the footprint of the
|
2104
|
+
filter. Note that this differs from the conventional definition of the median
|
2105
|
+
when ``n`` is even. Also, this function does not support the ``float16`` dtype,
|
2106
|
+
behavior in the presence of NaNs is undefined, and memory consumption scales with
|
2107
|
+
``n**4``. For ``float16`` support, greater control over the definition of the
|
2108
|
+
filter, and to limit memory usage, consider using `vectorized_filter` with
|
2109
|
+
NumPy functions `np.median` or `np.nanmedian`.
|
2110
|
+
|
1670
2111
|
Examples
|
1671
2112
|
--------
|
1672
2113
|
>>> from scipy import ndimage, datasets
|
@@ -1851,13 +2292,20 @@ def generic_filter(input, function, size=None, footprint=None,
|
|
1851
2292
|
|
1852
2293
|
Returns
|
1853
2294
|
-------
|
1854
|
-
|
2295
|
+
output : ndarray
|
1855
2296
|
Filtered array. Has the same shape as `input`.
|
1856
2297
|
|
2298
|
+
See Also
|
2299
|
+
--------
|
2300
|
+
vectorized_filter : similar functionality, but optimized for vectorized callables
|
2301
|
+
|
1857
2302
|
Notes
|
1858
2303
|
-----
|
1859
|
-
This function
|
1860
|
-
|
2304
|
+
This function is ideal for use with instances of `scipy.LowLevelCallable`;
|
2305
|
+
for vectorized, pure-Python callables, consider `vectorized_filter` for improved
|
2306
|
+
performance.
|
2307
|
+
|
2308
|
+
Low-level callback functions must have one of the following signatures:
|
1861
2309
|
|
1862
2310
|
.. code:: c
|
1863
2311
|
|
scipy/ndimage/_interpolation.py
CHANGED
@@ -33,6 +33,7 @@ import warnings
|
|
33
33
|
|
34
34
|
import numpy as np
|
35
35
|
from scipy._lib._util import normalize_axis_index
|
36
|
+
from scipy._lib import array_api_extra as xpx
|
36
37
|
|
37
38
|
from scipy import special
|
38
39
|
from . import _ni_support
|
@@ -533,6 +534,35 @@ def affine_transform(input, matrix, offset=0.0, output_shape=None,
|
|
533
534
|
affine_transform : ndarray
|
534
535
|
The transformed input.
|
535
536
|
|
537
|
+
Examples
|
538
|
+
--------
|
539
|
+
Use `affine_transform` to stretch an image::
|
540
|
+
|
541
|
+
>>> from scipy.ndimage import affine_transform
|
542
|
+
>>> from scipy.datasets import face
|
543
|
+
>>> from matplotlib import pyplot as plt
|
544
|
+
>>> import numpy as np
|
545
|
+
>>> im = face(gray=True)
|
546
|
+
>>> matrix = (0.5, 2)
|
547
|
+
>>> im2 = affine_transform(im, matrix)
|
548
|
+
>>> plt.imshow(im2)
|
549
|
+
>>> plt.show()
|
550
|
+
|
551
|
+
Rotate an image by 90 degrees and project it onto an expanded canvas::
|
552
|
+
|
553
|
+
>>> matrix = ((0, 1), (1, 0))
|
554
|
+
>>> im3 = affine_transform(im, matrix, output_shape=(1024, 1024))
|
555
|
+
>>> plt.imshow(im3)
|
556
|
+
>>> plt.show()
|
557
|
+
|
558
|
+
Offset the rotation so that the image is centred::
|
559
|
+
|
560
|
+
>>> output_shape = (1200, 1200)
|
561
|
+
>>> offset = (np.array(im.shape) - output_shape) / 2
|
562
|
+
>>> im4 = affine_transform(im, matrix, offset=offset, output_shape=output_shape)
|
563
|
+
>>> plt.imshow(im4)
|
564
|
+
>>> plt.show()
|
565
|
+
|
536
566
|
Notes
|
537
567
|
-----
|
538
568
|
The given matrix and offset are used to find for each point in the
|
@@ -616,12 +646,6 @@ def affine_transform(input, matrix, offset=0.0, output_shape=None,
|
|
616
646
|
if not offset.flags.contiguous:
|
617
647
|
offset = offset.copy()
|
618
648
|
if matrix.ndim == 1:
|
619
|
-
warnings.warn(
|
620
|
-
"The behavior of affine_transform with a 1-D "
|
621
|
-
"array supplied for the matrix parameter has changed in "
|
622
|
-
"SciPy 0.18.0.",
|
623
|
-
stacklevel=2
|
624
|
-
)
|
625
649
|
_nd_image.zoom_shift(filtered, matrix, offset/matrix, output, order,
|
626
650
|
mode, cval, npad, False)
|
627
651
|
else:
|
@@ -818,6 +842,12 @@ def zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0,
|
|
818
842
|
complex_output = np.iscomplexobj(input)
|
819
843
|
output = _ni_support._get_output(output, input, shape=output_shape,
|
820
844
|
complex_output=complex_output)
|
845
|
+
if all(z == 1 for z in zoom) and prefilter: # early exit for gh-20999
|
846
|
+
# zoom 1 means "return original image". If `prefilter=False`,
|
847
|
+
# `input` is *not* the original image; processing is still needed
|
848
|
+
# to undo the filter. So we only early exit if `prefilter`.
|
849
|
+
output = xpx.at(output)[...].set(input)
|
850
|
+
return output
|
821
851
|
if complex_output:
|
822
852
|
# import under different name to avoid confusion with zoom parameter
|
823
853
|
from scipy.ndimage._interpolation import zoom as _zoom
|
scipy/ndimage/_measurements.py
CHANGED
@@ -630,6 +630,7 @@ def _stats(input, labels=None, index=None, centered=False):
|
|
630
630
|
if labels is None:
|
631
631
|
return single_group(input)
|
632
632
|
|
633
|
+
labels = np.asarray(labels)
|
633
634
|
# ensure input and labels match sizes
|
634
635
|
input, labels = np.broadcast_arrays(input, labels)
|
635
636
|
|
@@ -944,6 +945,7 @@ def _select(input, labels=None, index=None, find_min=False, find_max=False,
|
|
944
945
|
if labels is None:
|
945
946
|
return single_group(input, positions)
|
946
947
|
|
948
|
+
labels = np.asarray(labels)
|
947
949
|
# ensure input and labels match sizes
|
948
950
|
input, labels = np.broadcast_arrays(input, labels)
|
949
951
|
|
@@ -1053,7 +1055,7 @@ def minimum(input, labels=None, index=None):
|
|
1053
1055
|
|
1054
1056
|
Returns
|
1055
1057
|
-------
|
1056
|
-
|
1058
|
+
output : a scalar or list of integers or floats based on input type.
|
1057
1059
|
List of minima of `input` over the regions determined by `labels` and
|
1058
1060
|
whose index is in `index`. If `index` or `labels` are not specified, a
|
1059
1061
|
float is returned: the minimal value of `input` if `labels` is None,
|
@@ -1116,7 +1118,7 @@ def maximum(input, labels=None, index=None):
|
|
1116
1118
|
|
1117
1119
|
Returns
|
1118
1120
|
-------
|
1119
|
-
output :
|
1121
|
+
output : a scalar or list of integers or floats based on input type.
|
1120
1122
|
List of maxima of `input` over the regions determined by `labels` and
|
1121
1123
|
whose index is in `index`. If `index` or `labels` are not specified, a
|
1122
1124
|
float is returned: the maximal value of `input` if `labels` is None,
|
scipy/ndimage/_morphology.py
CHANGED
@@ -221,6 +221,10 @@ def _binary_erosion(input, structure, iterations, mask, output,
|
|
221
221
|
raise TypeError('iterations parameter should be an integer') from e
|
222
222
|
|
223
223
|
input = np.asarray(input)
|
224
|
+
# The Cython code can't cope with broadcasted inputs
|
225
|
+
if not input.flags.c_contiguous and not input.flags.f_contiguous:
|
226
|
+
input = np.ascontiguousarray(input)
|
227
|
+
|
224
228
|
ndim = input.ndim
|
225
229
|
if np.iscomplexobj(input):
|
226
230
|
raise TypeError('Complex type not supported')
|
@@ -1791,6 +1795,7 @@ def morphological_laplace(input, size=None, footprint=None, structure=None,
|
|
1791
1795
|
Output
|
1792
1796
|
|
1793
1797
|
"""
|
1798
|
+
input = np.asarray(input)
|
1794
1799
|
tmp1 = grey_dilation(input, size, footprint, structure, None, mode,
|
1795
1800
|
cval, origin, axes=axes)
|
1796
1801
|
if isinstance(output, np.ndarray):
|
Binary file
|
Binary file
|
scipy/ndimage/_ni_docstrings.py
CHANGED
@@ -17,6 +17,9 @@ _output_doc = (
|
|
17
17
|
The array in which to place the output, or the dtype of the
|
18
18
|
returned array. By default an array of the same dtype as input
|
19
19
|
will be created.""")
|
20
|
+
_nan_doc = (
|
21
|
+
"""The behavior of this function with NaN elements is undefined. To control
|
22
|
+
behavior in the presence of NaNs, consider using `vectorized_filter`.""")
|
20
23
|
_size_foot_doc = (
|
21
24
|
"""size : scalar or tuple, optional
|
22
25
|
See footprint, below. Ignored if footprint is given.
|
@@ -204,7 +207,8 @@ docdict = {
|
|
204
207
|
'origin_multiple': _origin_multiple_doc,
|
205
208
|
'extra_arguments': _extra_arguments_doc,
|
206
209
|
'extra_keywords': _extra_keywords_doc,
|
207
|
-
'prefilter': _prefilter_doc
|
210
|
+
'prefilter': _prefilter_doc,
|
211
|
+
'nan': _nan_doc,
|
208
212
|
}
|
209
213
|
|
210
214
|
docfiller: Final = doccer.filldoc(docdict)
|
Binary file
|
Binary file
|
scipy/ndimage/_ni_support.py
CHANGED
@@ -84,7 +84,7 @@ def _get_output(output, input, shape=None, complex_output=False):
|
|
84
84
|
else:
|
85
85
|
complex_type = np.promote_types(input.dtype, np.complex64)
|
86
86
|
output = np.zeros(shape, dtype=complex_type)
|
87
|
-
elif isinstance(output,
|
87
|
+
elif isinstance(output, type | np.dtype):
|
88
88
|
# Classes (like `np.float32`) and dtypes are interpreted as dtype
|
89
89
|
if complex_output and np.dtype(output).kind != 'c':
|
90
90
|
warnings.warn("promoting specified output dtype to complex", stacklevel=3)
|
@@ -137,7 +137,3 @@ def _skip_if_dtype(arg):
|
|
137
137
|
return None if issubclass(arg, np.generic) else arg
|
138
138
|
else:
|
139
139
|
return None if isinstance(arg, np.dtype) else arg
|
140
|
-
|
141
|
-
|
142
|
-
def _skip_if_int(arg):
|
143
|
-
return None if (arg is None or isinstance(arg, int)) else arg
|
Binary file
|