scipy 1.15.3__cp313-cp313t-macosx_14_0_arm64.whl → 1.16.0rc2__cp313-cp313t-macosx_14_0_arm64.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 +3 -3
- scipy/__init__.py +3 -6
- scipy/_cyutility.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/_lib/_docscrape.py +1 -1
- scipy/_lib/_elementwise_iterative_method.py +15 -26
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_deprecation_call.cpython-313t-darwin.so +0 -0
- scipy/_lib/_testutils.py +6 -2
- 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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/cluster/_optimal_leaf_ordering.cpython-313t-darwin.so +0 -0
- scipy/cluster/_vq.cpython-313t-darwin.so +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/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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/integrate/_lsoda.cpython-313t-darwin.so +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cpython-313t-darwin.so +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cpython-313t-darwin.so +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_odeint_banded.cpython-313t-darwin.so +0 -0
- scipy/integrate/_vode.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_dierckx.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_fitpack.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cpython-313t-darwin.so +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/_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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/io/matlab/_mio_utils.cpython-313t-darwin.so +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cpython-313t-darwin.so +0 -0
- scipy/linalg/_flapack.cpython-313t-darwin.so +0 -0
- scipy/linalg/_linalg_pythran.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cpython-313t-darwin.so +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cpython-313t-darwin.so +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cpython-313t-darwin.so +0 -0
- scipy/linalg/cython_lapack.cpython-313t-darwin.so +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/_cytest.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cpython-313t-darwin.so +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cpython-313t-darwin.so +0 -0
- scipy/optimize/_lbfgsb.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/signal/_peak_finding_utils.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/signal/_sosfilt.cpython-313t-darwin.so +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_matching.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_reordering.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_shortest_path.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_tools.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_traversal.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cpython-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_spropack.cpython-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/spatial/_distance_pybind.cpython-313t-darwin.so +0 -0
- scipy/spatial/_distance_wrap.cpython-313t-darwin.so +0 -0
- scipy/spatial/_hausdorff.cpython-313t-darwin.so +0 -0
- scipy/spatial/_qhull.cpython-313t-darwin.so +0 -0
- scipy/spatial/_voronoi.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/spatial/transform/_rotation.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/special/_ellip_harm_2.cpython-313t-darwin.so +0 -0
- scipy/special/_gufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cpython-313t-darwin.so +0 -0
- scipy/special/_special_ufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cpython-313t-darwin.so +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cpython-313t-darwin.so +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.cpython-313t-darwin.so +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.cpython-313t-darwin.so +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cpython-313t-darwin.so +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cpython-313t-darwin.so +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cpython-313t-darwin.so +0 -0
- scipy/stats/_stats.cpython-313t-darwin.so +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cpython-313t-darwin.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.cpython-313t-darwin.so +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.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 +559 -566
- scipy-1.16.0rc2.dist-info/WHEEL +6 -0
- scipy/_lib/array_api_extra/_funcs.py +0 -484
- scipy/_lib/array_api_extra/_typing.py +0 -8
- scipy/interpolate/_bspl.cpython-313t-darwin.so +0 -0
- scipy/optimize/_cobyla.cpython-313t-darwin.so +0 -0
- scipy/optimize/_cython_nnls.cpython-313t-darwin.so +0 -0
- scipy/optimize/_slsqp.cpython-313t-darwin.so +0 -0
- scipy/spatial/qhull_src/COPYING.txt +0 -38
- scipy/special/libsf_error_state.dylib +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.cpython-313t-darwin.so +0 -0
- scipy-1.15.3.dist-info/WHEEL +0 -4
@@ -1,18 +1,23 @@
|
|
1
|
+
import math
|
1
2
|
import numpy as np
|
3
|
+
|
2
4
|
from numpy.testing import assert_warns
|
3
|
-
from scipy._lib._array_api import (
|
4
|
-
xp_assert_close, xp_assert_equal,
|
5
|
-
assert_almost_equal, assert_array_almost_equal,
|
6
|
-
)
|
7
5
|
from pytest import raises as assert_raises
|
8
6
|
import pytest
|
9
7
|
|
10
|
-
|
11
|
-
from scipy.
|
8
|
+
import scipy._lib.array_api_extra as xpx
|
9
|
+
from scipy._lib._array_api import (
|
10
|
+
xp_assert_close, xp_assert_equal, assert_almost_equal, assert_array_almost_equal,
|
11
|
+
array_namespace, xp_default_dtype
|
12
|
+
)
|
13
|
+
from scipy.fft import fft, fft2
|
12
14
|
from scipy.signal import (kaiser_beta, kaiser_atten, kaiserord,
|
13
|
-
firwin, firwin2, freqz, remez, firls, minimum_phase
|
15
|
+
firwin, firwin2, freqz, remez, firls, minimum_phase, convolve2d, firwin_2d
|
14
16
|
)
|
15
17
|
|
18
|
+
skip_xp_backends = pytest.mark.skip_xp_backends
|
19
|
+
xfail_xp_backends = pytest.mark.xfail_xp_backends
|
20
|
+
|
16
21
|
|
17
22
|
def test_kaiser_beta():
|
18
23
|
b = kaiser_beta(58.7)
|
@@ -41,17 +46,19 @@ def test_kaiserord():
|
|
41
46
|
class TestFirwin:
|
42
47
|
|
43
48
|
def check_response(self, h, expected_response, tol=.05):
|
44
|
-
|
49
|
+
xp = array_namespace(h)
|
50
|
+
N = h.shape[0]
|
45
51
|
alpha = 0.5 * (N-1)
|
46
|
-
m =
|
52
|
+
m = xp.arange(0, N) - alpha # time indices of taps
|
47
53
|
for freq, expected in expected_response:
|
48
|
-
actual = abs(
|
49
|
-
mse = abs(actual-expected)**2
|
54
|
+
actual = abs(xp.sum(h * xp.exp(-1j * xp.pi * m * freq)))
|
55
|
+
mse = abs(actual - expected)**2
|
50
56
|
assert mse < tol, f'response not as expected, mse={mse:g} > {tol:g}'
|
51
57
|
|
52
|
-
def test_response(self):
|
58
|
+
def test_response(self, xp):
|
53
59
|
N = 51
|
54
60
|
f = .5
|
61
|
+
|
55
62
|
# increase length just to try even/odd
|
56
63
|
h = firwin(N, f) # low-pass from 0 to f
|
57
64
|
self.check_response(h, [(.25,1), (.75,0)])
|
@@ -97,7 +104,7 @@ class TestFirwin:
|
|
97
104
|
mse = np.mean(abs(abs(H)-Hideal)**2)
|
98
105
|
return mse
|
99
106
|
|
100
|
-
def test_scaling(self):
|
107
|
+
def test_scaling(self, xp):
|
101
108
|
"""
|
102
109
|
For one lowpass, bandpass, and highpass example filter, this test
|
103
110
|
checks two things:
|
@@ -133,110 +140,130 @@ class TestFirwin:
|
|
133
140
|
class TestFirWinMore:
|
134
141
|
"""Different author, different style, different tests..."""
|
135
142
|
|
136
|
-
def test_lowpass(self):
|
143
|
+
def test_lowpass(self, xp):
|
137
144
|
width = 0.04
|
138
145
|
ntaps, beta = kaiserord(120, width)
|
139
|
-
|
146
|
+
cutoff = xp.asarray(0.5)
|
147
|
+
kwargs = dict(cutoff=cutoff, window=('kaiser', beta), scale=False)
|
140
148
|
taps = firwin(ntaps, **kwargs)
|
141
149
|
|
142
150
|
# Check the symmetry of taps.
|
143
|
-
assert_array_almost_equal(taps[:ntaps//2], taps[
|
151
|
+
assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2])
|
144
152
|
|
145
153
|
# Check the gain at a few samples where
|
146
154
|
# we know it should be approximately 0 or 1.
|
147
|
-
freq_samples =
|
148
|
-
freqs, response = freqz(taps, worN=
|
149
|
-
|
150
|
-
|
155
|
+
freq_samples = xp.asarray([0.0, 0.25, 0.5-width/2, 0.5+width/2, 0.75, 1.0])
|
156
|
+
freqs, response = freqz(taps, worN=xp.pi*freq_samples)
|
157
|
+
|
158
|
+
assert_array_almost_equal(
|
159
|
+
xp.abs(response),
|
160
|
+
xp.asarray([1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5
|
161
|
+
)
|
151
162
|
|
152
163
|
taps_str = firwin(ntaps, pass_zero='lowpass', **kwargs)
|
153
164
|
xp_assert_close(taps, taps_str)
|
154
165
|
|
155
|
-
def test_highpass(self):
|
166
|
+
def test_highpass(self, xp):
|
156
167
|
width = 0.04
|
157
168
|
ntaps, beta = kaiserord(120, width)
|
158
169
|
|
159
170
|
# Ensure that ntaps is odd.
|
160
171
|
ntaps |= 1
|
161
172
|
|
162
|
-
|
173
|
+
cutoff = xp.asarray(0.5)
|
174
|
+
kwargs = dict(cutoff=cutoff, window=('kaiser', beta), scale=False)
|
163
175
|
taps = firwin(ntaps, pass_zero=False, **kwargs)
|
164
176
|
|
165
177
|
# Check the symmetry of taps.
|
166
|
-
assert_array_almost_equal(taps[:ntaps//2], taps[
|
178
|
+
assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2])
|
167
179
|
|
168
180
|
# Check the gain at a few samples where
|
169
181
|
# we know it should be approximately 0 or 1.
|
170
|
-
freq_samples =
|
182
|
+
freq_samples = xp.asarray([0.0, 0.25, 0.5 - width/2, 0.5 + width/2, 0.75, 1.0])
|
171
183
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
172
|
-
|
173
|
-
|
184
|
+
|
185
|
+
assert_array_almost_equal(xp.abs(response),
|
186
|
+
xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5)
|
174
187
|
|
175
188
|
taps_str = firwin(ntaps, pass_zero='highpass', **kwargs)
|
176
189
|
xp_assert_close(taps, taps_str)
|
177
190
|
|
178
|
-
def test_bandpass(self):
|
191
|
+
def test_bandpass(self, xp):
|
179
192
|
width = 0.04
|
180
193
|
ntaps, beta = kaiserord(120, width)
|
181
|
-
kwargs = dict(
|
194
|
+
kwargs = dict(
|
195
|
+
cutoff=xp.asarray([0.3, 0.7]), window=('kaiser', beta), scale=False
|
196
|
+
)
|
182
197
|
taps = firwin(ntaps, pass_zero=False, **kwargs)
|
183
198
|
|
184
199
|
# Check the symmetry of taps.
|
185
|
-
assert_array_almost_equal(taps[:ntaps//2], taps[
|
200
|
+
assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2])
|
186
201
|
|
187
202
|
# Check the gain at a few samples where
|
188
203
|
# we know it should be approximately 0 or 1.
|
189
|
-
freq_samples =
|
190
|
-
|
204
|
+
freq_samples = xp.asarray([0.0, 0.2, 0.3 - width/2, 0.3 + width/2, 0.5,
|
205
|
+
0.7 - width/2, 0.7 + width/2, 0.8, 1.0])
|
191
206
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
192
|
-
|
193
|
-
|
207
|
+
|
208
|
+
assert_array_almost_equal(xp.abs(response),
|
209
|
+
xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5)
|
194
210
|
|
195
211
|
taps_str = firwin(ntaps, pass_zero='bandpass', **kwargs)
|
196
212
|
xp_assert_close(taps, taps_str)
|
197
213
|
|
198
|
-
def test_bandstop_multi(self):
|
214
|
+
def test_bandstop_multi(self, xp):
|
199
215
|
width = 0.04
|
200
216
|
ntaps, beta = kaiserord(120, width)
|
201
|
-
kwargs = dict(cutoff=[0.2, 0.5, 0.8], window=('kaiser', beta),
|
217
|
+
kwargs = dict(cutoff=xp.asarray([0.2, 0.5, 0.8]), window=('kaiser', beta),
|
202
218
|
scale=False)
|
203
219
|
taps = firwin(ntaps, **kwargs)
|
204
220
|
|
205
221
|
# Check the symmetry of taps.
|
206
|
-
assert_array_almost_equal(taps[:ntaps//2], taps[
|
222
|
+
assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2])
|
207
223
|
|
208
224
|
# Check the gain at a few samples where
|
209
225
|
# we know it should be approximately 0 or 1.
|
210
|
-
freq_samples =
|
211
|
-
|
212
|
-
|
226
|
+
freq_samples = xp.asarray([0.0, 0.1, 0.2 - width/2, 0.2 + width/2, 0.35,
|
227
|
+
0.5 - width/2, 0.5 + width/2, 0.65,
|
228
|
+
0.8 - width/2, 0.8 + width/2, 0.9, 1.0])
|
213
229
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
214
|
-
|
215
|
-
|
216
|
-
|
230
|
+
|
231
|
+
assert_array_almost_equal(
|
232
|
+
xp.abs(response),
|
233
|
+
xp.asarray([1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]),
|
234
|
+
decimal=5
|
235
|
+
)
|
217
236
|
|
218
237
|
taps_str = firwin(ntaps, pass_zero='bandstop', **kwargs)
|
219
238
|
xp_assert_close(taps, taps_str)
|
220
239
|
|
221
|
-
def test_fs_nyq(self):
|
240
|
+
def test_fs_nyq(self, xp):
|
222
241
|
"""Test the fs and nyq keywords."""
|
223
242
|
nyquist = 1000
|
224
243
|
width = 40.0
|
225
244
|
relative_width = width/nyquist
|
226
245
|
ntaps, beta = kaiserord(120, relative_width)
|
227
|
-
taps = firwin(ntaps, cutoff=[300, 700], window=('kaiser', beta),
|
246
|
+
taps = firwin(ntaps, cutoff=xp.asarray([300, 700]), window=('kaiser', beta),
|
228
247
|
pass_zero=False, scale=False, fs=2*nyquist)
|
229
248
|
|
230
249
|
# Check the symmetry of taps.
|
231
|
-
assert_array_almost_equal(taps[:ntaps//2], taps[
|
250
|
+
assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2])
|
232
251
|
|
233
252
|
# Check the gain at a few samples where
|
234
253
|
# we know it should be approximately 0 or 1.
|
235
|
-
freq_samples =
|
236
|
-
|
254
|
+
freq_samples = xp.asarray([0.0, 200, 300 - width/2, 300 + width/2, 500,
|
255
|
+
700 - width/2, 700 + width/2, 800, 1000])
|
237
256
|
freqs, response = freqz(taps, worN=np.pi*freq_samples/nyquist)
|
238
|
-
|
239
|
-
|
257
|
+
|
258
|
+
assert_array_almost_equal(xp.abs(response),
|
259
|
+
xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5)
|
260
|
+
|
261
|
+
def test_array_cutoff(self, xp):
|
262
|
+
taps = firwin(3, xp.asarray([.1, .2]))
|
263
|
+
# smoke test against the value computed by scipy==1.5.2
|
264
|
+
xp_assert_close(
|
265
|
+
taps, xp.asarray([-0.00801395, 1.0160279, -0.00801395]), atol=1e-8
|
266
|
+
)
|
240
267
|
|
241
268
|
def test_bad_cutoff(self):
|
242
269
|
"""Test that invalid cutoff argument raises ValueError."""
|
@@ -265,9 +292,9 @@ class TestFirWinMore:
|
|
265
292
|
|
266
293
|
def test_bad_pass_zero(self):
|
267
294
|
"""Test degenerate pass_zero cases."""
|
268
|
-
with assert_raises(ValueError, match='
|
295
|
+
with assert_raises(ValueError, match="^Parameter pass_zero='foo' not in "):
|
269
296
|
firwin(41, 0.5, pass_zero='foo')
|
270
|
-
with assert_raises(
|
297
|
+
with assert_raises(ValueError, match="^Parameter pass_zero=1.0 not in "):
|
271
298
|
firwin(41, 0.5, pass_zero=1.)
|
272
299
|
for pass_zero in ('lowpass', 'highpass'):
|
273
300
|
with assert_raises(ValueError, match='cutoff must have one'):
|
@@ -281,6 +308,7 @@ class TestFirWinMore:
|
|
281
308
|
firwin2(51, .5, 1, fs=np.array([10, 20]))
|
282
309
|
|
283
310
|
|
311
|
+
@skip_xp_backends(cpu_only=True, reason="firwin2 uses np.interp")
|
284
312
|
class TestFirwin2:
|
285
313
|
|
286
314
|
def test_invalid_args(self):
|
@@ -330,90 +358,117 @@ class TestFirwin2:
|
|
330
358
|
with assert_raises(ValueError, match='Type IV filter'):
|
331
359
|
firwin2(16, [0.0, 0.5, 1.0], [1.0, 1.0, 0.0], antisymmetric=True)
|
332
360
|
|
333
|
-
def test01(self):
|
361
|
+
def test01(self, xp):
|
334
362
|
width = 0.04
|
335
363
|
beta = 12.0
|
336
364
|
ntaps = 400
|
337
365
|
# Filter is 1 from w=0 to w=0.5, then decreases linearly from 1 to 0 as w
|
338
366
|
# increases from w=0.5 to w=1 (w=1 is the Nyquist frequency).
|
339
|
-
freq = [0.0, 0.5, 1.0]
|
340
|
-
gain = [1.0, 1.0, 0.0]
|
367
|
+
freq = xp.asarray([0.0, 0.5, 1.0])
|
368
|
+
gain = xp.asarray([1.0, 1.0, 0.0])
|
341
369
|
taps = firwin2(ntaps, freq, gain, window=('kaiser', beta))
|
342
|
-
freq_samples =
|
343
|
-
0.75, 1.0-width/2])
|
370
|
+
freq_samples = xp.asarray([0.0, 0.25, 0.5 - width/2, 0.5 + width/2,
|
371
|
+
0.75, 1.0 - width/2])
|
344
372
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
373
|
+
freqs, response = xp.asarray(freqs), xp.asarray(response)
|
374
|
+
assert_array_almost_equal(
|
375
|
+
xp.abs(response),
|
376
|
+
xp.asarray([1.0, 1.0, 1.0, 1.0 - width, 0.5, width]), decimal=5
|
377
|
+
)
|
378
|
+
|
379
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
380
|
+
def test02(self, xp):
|
349
381
|
width = 0.04
|
350
382
|
beta = 12.0
|
351
383
|
# ntaps must be odd for positive gain at Nyquist.
|
352
384
|
ntaps = 401
|
353
385
|
# An ideal highpass filter.
|
354
|
-
freq = [0.0, 0.5, 0.5, 1.0]
|
355
|
-
gain = [0.0, 0.0, 1.0, 1.0]
|
386
|
+
freq = xp.asarray([0.0, 0.5, 0.5, 1.0])
|
387
|
+
gain = xp.asarray([0.0, 0.0, 1.0, 1.0])
|
356
388
|
taps = firwin2(ntaps, freq, gain, window=('kaiser', beta))
|
357
|
-
freq_samples = np.array([0.0, 0.25, 0.5-width, 0.5+width, 0.75, 1.0])
|
389
|
+
freq_samples = np.array([0.0, 0.25, 0.5 - width, 0.5 + width, 0.75, 1.0])
|
358
390
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
391
|
+
freqs, response = xp.asarray(freqs), xp.asarray(response)
|
392
|
+
assert_array_almost_equal(
|
393
|
+
xp.abs(response),
|
394
|
+
xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5
|
395
|
+
)
|
396
|
+
|
397
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
398
|
+
def test03(self, xp):
|
363
399
|
width = 0.02
|
364
400
|
ntaps, beta = kaiserord(120, width)
|
365
401
|
# ntaps must be odd for positive gain at Nyquist.
|
366
402
|
ntaps = int(ntaps) | 1
|
367
|
-
freq = [0.0, 0.4, 0.4, 0.5, 0.5, 1.0]
|
368
|
-
gain = [1.0, 1.0, 0.0, 0.0, 1.0, 1.0]
|
403
|
+
freq = xp.asarray([0.0, 0.4, 0.4, 0.5, 0.5, 1.0])
|
404
|
+
gain = xp.asarray([1.0, 1.0, 0.0, 0.0, 1.0, 1.0])
|
369
405
|
taps = firwin2(ntaps, freq, gain, window=('kaiser', beta))
|
370
|
-
freq_samples = np.array([0.0, 0.4-width, 0.4+width, 0.45,
|
371
|
-
0.5-width, 0.5+width, 0.75, 1.0])
|
406
|
+
freq_samples = np.array([0.0, 0.4 - width, 0.4 + width, 0.45,
|
407
|
+
0.5 - width, 0.5 + width, 0.75, 1.0])
|
372
408
|
freqs, response = freqz(taps, worN=np.pi*freq_samples)
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
409
|
+
freqs, response = xp.asarray(freqs), xp.asarray(response)
|
410
|
+
assert_array_almost_equal(
|
411
|
+
xp.abs(response),
|
412
|
+
xp.asarray([1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5
|
413
|
+
)
|
414
|
+
|
415
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
416
|
+
def test04(self, xp):
|
377
417
|
"""Test firwin2 when window=None."""
|
378
418
|
ntaps = 5
|
379
419
|
# Ideal lowpass: gain is 1 on [0,0.5], and 0 on [0.5, 1.0]
|
380
|
-
freq = [0.0, 0.5, 0.5, 1.0]
|
381
|
-
gain = [1.0, 1.0, 0.0, 0.0]
|
420
|
+
freq = xp.asarray([0.0, 0.5, 0.5, 1.0])
|
421
|
+
gain = xp.asarray([1.0, 1.0, 0.0, 0.0])
|
422
|
+
|
382
423
|
taps = firwin2(ntaps, freq, gain, window=None, nfreqs=8193)
|
383
424
|
alpha = 0.5 * (ntaps - 1)
|
384
|
-
m =
|
385
|
-
h = 0.5 * sinc(0.5 * m)
|
425
|
+
m = xp.arange(0, ntaps, dtype=freq.dtype) - alpha
|
426
|
+
h = 0.5 * xpx.sinc(0.5 * m)
|
386
427
|
assert_array_almost_equal(h, taps)
|
387
428
|
|
388
|
-
def test05(self):
|
429
|
+
def test05(self, xp):
|
389
430
|
"""Test firwin2 for calculating Type IV filters"""
|
390
431
|
ntaps = 1500
|
391
432
|
|
392
|
-
freq = [0.0, 1.0]
|
393
|
-
gain = [0.0, 1.0]
|
433
|
+
freq = xp.asarray([0.0, 1.0])
|
434
|
+
gain = xp.asarray([0.0, 1.0])
|
394
435
|
taps = firwin2(ntaps, freq, gain, window=None, antisymmetric=True)
|
395
|
-
assert_array_almost_equal(taps[: ntaps // 2], -taps[ntaps // 2:][::-1])
|
396
436
|
|
397
|
-
|
398
|
-
|
437
|
+
flip = array_namespace(freq).flip
|
438
|
+
dec = {'decimal': 4.5} if xp_default_dtype(xp) == xp.float32 else {}
|
439
|
+
assert_array_almost_equal(taps[: ntaps // 2], flip(-taps[ntaps // 2:]), **dec)
|
399
440
|
|
400
|
-
|
441
|
+
freqs, response = freqz(np.asarray(taps), worN=2048) # XXX convert freqz
|
442
|
+
assert_array_almost_equal(abs(xp.asarray(response)),
|
443
|
+
xp.asarray(freqs / np.pi), decimal=4)
|
444
|
+
|
445
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
446
|
+
def test06(self, xp):
|
401
447
|
"""Test firwin2 for calculating Type III filters"""
|
402
448
|
ntaps = 1501
|
403
449
|
|
404
|
-
freq = [0.0, 0.5, 0.55, 1.0]
|
405
|
-
gain = [0.0, 0.5, 0.0, 0.0]
|
450
|
+
freq = xp.asarray([0.0, 0.5, 0.55, 1.0])
|
451
|
+
gain = xp.asarray([0.0, 0.5, 0.0, 0.0])
|
406
452
|
taps = firwin2(ntaps, freq, gain, window=None, antisymmetric=True)
|
407
453
|
assert taps[ntaps // 2] == 0.0
|
408
|
-
assert_array_almost_equal(taps[: ntaps // 2], -taps[ntaps // 2 + 1:][::-1])
|
409
454
|
|
410
|
-
|
411
|
-
|
455
|
+
flip = array_namespace(freq).flip
|
456
|
+
dec = {'decimal': 4.5} if xp_default_dtype(xp) == xp.float32 else {}
|
457
|
+
assert_array_almost_equal(taps[: ntaps // 2],
|
458
|
+
flip(-taps[ntaps // 2 + 1:]), **dec
|
459
|
+
)
|
460
|
+
|
461
|
+
freqs, response1 = freqz(np.asarray(taps), worN=2048) # XXX convert freqz
|
462
|
+
response1 = xp.asarray(response1)
|
463
|
+
response2 = xp.asarray(
|
464
|
+
np.interp(np.asarray(freqs) / np.pi, np.asarray(freq), np.asarray(gain))
|
465
|
+
)
|
412
466
|
assert_array_almost_equal(abs(response1), response2, decimal=3)
|
413
467
|
|
414
|
-
def test_fs_nyq(self):
|
415
|
-
taps1 = firwin2(80, [0.0, 0.5, 1.0], [1.0, 1.0, 0.0])
|
416
|
-
taps2 = firwin2(80, [0.0, 30.0, 60.0], [1.0, 1.0, 0.0],
|
468
|
+
def test_fs_nyq(self, xp):
|
469
|
+
taps1 = firwin2(80, xp.asarray([0.0, 0.5, 1.0]), xp.asarray([1.0, 1.0, 0.0]))
|
470
|
+
taps2 = firwin2(80, xp.asarray([0.0, 30.0, 60.0]), xp.asarray([1.0, 1.0, 0.0]),
|
471
|
+
fs=120.0)
|
417
472
|
assert_array_almost_equal(taps1, taps2)
|
418
473
|
|
419
474
|
def test_tuple(self):
|
@@ -421,13 +476,15 @@ class TestFirwin2:
|
|
421
476
|
taps2 = firwin2(150, [0.0, 0.5, 0.5, 1.0], [1.0, 1.0, 0.0, 0.0])
|
422
477
|
assert_array_almost_equal(taps1, taps2)
|
423
478
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
479
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
480
|
+
def test_input_modyfication(self, xp):
|
481
|
+
freq1 = xp.asarray([0.0, 0.5, 0.5, 1.0])
|
482
|
+
freq2 = xp.asarray(freq1)
|
483
|
+
firwin2(80, freq1, xp.asarray([1.0, 1.0, 0.0, 0.0]))
|
428
484
|
xp_assert_equal(freq1, freq2)
|
429
485
|
|
430
486
|
|
487
|
+
@skip_xp_backends(cpu_only=True)
|
431
488
|
class TestRemez:
|
432
489
|
|
433
490
|
def test_bad_args(self):
|
@@ -462,14 +519,15 @@ class TestRemez:
|
|
462
519
|
idx = np.logical_and(f > a, f < 0.5-a)
|
463
520
|
assert (abs(Hmag[idx] - 1) < 0.015).all(), "Pass Band Close To Unity"
|
464
521
|
|
465
|
-
def test_compare(self):
|
522
|
+
def test_compare(self, xp):
|
466
523
|
# test comparison to MATLAB
|
467
524
|
k = [0.024590270518440, -0.041314581814658, -0.075943803756711,
|
468
525
|
-0.003530911231040, 0.193140296954975, 0.373400753484939,
|
469
526
|
0.373400753484939, 0.193140296954975, -0.003530911231040,
|
470
527
|
-0.075943803756711, -0.041314581814658, 0.024590270518440]
|
471
|
-
h = remez(12, [0, 0.3, 0.5, 1], [1, 0], fs=2.)
|
472
|
-
|
528
|
+
h = remez(12, xp.asarray([0, 0.3, 0.5, 1]), xp.asarray([1, 0]), fs=2.)
|
529
|
+
atol_arg = {'atol': 1e-8} if xp_default_dtype(xp) == xp.float32 else {}
|
530
|
+
xp_assert_close(h, xp.asarray(k, dtype=xp.float64), **atol_arg)
|
473
531
|
|
474
532
|
h = [-0.038976016082299, 0.018704846485491, -0.014644062687875,
|
475
533
|
0.002879152556419, 0.016849978528150, -0.043276706138248,
|
@@ -478,12 +536,19 @@ class TestRemez:
|
|
478
536
|
0.129770906801075, -0.103908158578635, 0.073641298245579,
|
479
537
|
-0.043276706138248, 0.016849978528150, 0.002879152556419,
|
480
538
|
-0.014644062687875, 0.018704846485491, -0.038976016082299]
|
481
|
-
|
539
|
+
atol_arg = {'atol': 3e-8} if xp_default_dtype(xp) == xp.float32 else {}
|
540
|
+
xp_assert_close(
|
541
|
+
remez(21, xp.asarray([0, 0.8, 0.9, 1]), xp.asarray([0, 1]), fs=2.),
|
542
|
+
xp.asarray(h, dtype=xp.float64), **atol_arg
|
543
|
+
)
|
482
544
|
|
483
545
|
def test_fs_validation(self):
|
484
546
|
with pytest.raises(ValueError, match="Sampling.*single scalar"):
|
485
547
|
remez(11, .1, 1, fs=np.array([10, 20]))
|
486
548
|
|
549
|
+
|
550
|
+
|
551
|
+
@skip_xp_backends(cpu_only=True, reason="lstsq")
|
487
552
|
class TestFirls:
|
488
553
|
|
489
554
|
def test_bad_args(self):
|
@@ -505,105 +570,121 @@ class TestFirls:
|
|
505
570
|
# negative weight
|
506
571
|
assert_raises(ValueError, firls, 11, [0.1, 0.2], [0, 0], weight=[-1])
|
507
572
|
|
508
|
-
|
573
|
+
@skip_xp_backends("dask.array", reason="dask fancy indexing shape=(nan,)")
|
574
|
+
def test_firls(self, xp):
|
509
575
|
N = 11 # number of taps in the filter
|
510
576
|
a = 0.1 # width of the transition band
|
511
577
|
|
512
578
|
# design a halfband symmetric low-pass filter
|
513
|
-
h = firls(11, [0, a, 0.5-a, 0.5], [1, 1, 0, 0],
|
579
|
+
h = firls(11, xp.asarray([0, a, 0.5 - a, 0.5]), xp.asarray([1, 1, 0, 0]),
|
580
|
+
fs=1.0)
|
514
581
|
|
515
582
|
# make sure the filter has correct # of taps
|
516
583
|
assert h.shape[0] == N
|
517
584
|
|
518
585
|
# make sure it is symmetric
|
519
586
|
midx = (N-1) // 2
|
520
|
-
|
587
|
+
flip = array_namespace(h).flip
|
588
|
+
assert_array_almost_equal(h[:midx], flip(h[midx+1:])) # h[:-midx-1:-1])
|
521
589
|
|
522
590
|
# make sure the center tap is 0.5
|
523
|
-
|
591
|
+
assert math.isclose(h[midx], 0.5, abs_tol=1e-8)
|
524
592
|
|
525
593
|
# For halfband symmetric, odd coefficients (except the center)
|
526
594
|
# should be zero (really small)
|
527
|
-
hodd =
|
528
|
-
assert_array_almost_equal(hodd,
|
595
|
+
hodd = xp.stack((h[1:midx:2], h[-midx+1::2]))
|
596
|
+
assert_array_almost_equal(hodd, xp.zeros_like(hodd))
|
529
597
|
|
530
598
|
# now check the frequency response
|
531
|
-
w, H = freqz(h, 1)
|
532
|
-
|
533
|
-
|
599
|
+
w, H = freqz(np.asarray(h), 1)
|
600
|
+
w, H = xp.asarray(w), xp.asarray(H)
|
601
|
+
f = w/2/xp.pi
|
602
|
+
Hmag = xp.abs(H)
|
534
603
|
|
535
604
|
# check that the pass band is close to unity
|
536
|
-
idx =
|
537
|
-
assert_array_almost_equal(Hmag[idx],
|
605
|
+
idx = xp.logical_and(f > 0, f < a)
|
606
|
+
assert_array_almost_equal(Hmag[idx], xp.ones_like(Hmag[idx]), decimal=3)
|
538
607
|
|
539
608
|
# check that the stop band is close to zero
|
540
|
-
idx =
|
541
|
-
assert_array_almost_equal(Hmag[idx],
|
609
|
+
idx = xp.logical_and(f > 0.5 - a, f < 0.5)
|
610
|
+
assert_array_almost_equal(Hmag[idx], xp.zeros_like(Hmag[idx]), decimal=3)
|
542
611
|
|
543
|
-
def test_compare(self):
|
612
|
+
def test_compare(self, xp):
|
544
613
|
# compare to OCTAVE output
|
545
|
-
taps = firls(9, [0, 0.5, 0.55, 1],
|
614
|
+
taps = firls(9, xp.asarray([0, 0.5, 0.55, 1]),
|
615
|
+
xp.asarray([1, 1, 0, 0]), weight=xp.asarray([1, 2]))
|
546
616
|
# >> taps = firls(8, [0 0.5 0.55 1], [1 1 0 0], [1, 2]);
|
547
617
|
known_taps = [-6.26930101730182e-04, -1.03354450635036e-01,
|
548
618
|
-9.81576747564301e-03, 3.17271686090449e-01,
|
549
619
|
5.11409425599933e-01, 3.17271686090449e-01,
|
550
620
|
-9.81576747564301e-03, -1.03354450635036e-01,
|
551
621
|
-6.26930101730182e-04]
|
552
|
-
|
622
|
+
atol_arg = {'atol': 5e-8} if xp_default_dtype(xp) == xp.float32 else {}
|
623
|
+
known_taps = xp.asarray(known_taps, dtype=xp.float64)
|
624
|
+
xp_assert_close(taps, known_taps, **atol_arg)
|
553
625
|
|
554
626
|
# compare to MATLAB output
|
555
|
-
taps = firls(11, [0, 0.5, 0.5, 1],
|
627
|
+
taps = firls(11, xp.asarray([0, 0.5, 0.5, 1]),
|
628
|
+
xp.asarray([1, 1, 0, 0]), weight=xp.asarray([1, 2]))
|
556
629
|
# >> taps = firls(10, [0 0.5 0.5 1], [1 1 0 0], [1, 2]);
|
557
630
|
known_taps = [
|
558
631
|
0.058545300496815, -0.014233383714318, -0.104688258464392,
|
559
632
|
0.012403323025279, 0.317930861136062, 0.488047220029700,
|
560
633
|
0.317930861136062, 0.012403323025279, -0.104688258464392,
|
561
634
|
-0.014233383714318, 0.058545300496815]
|
562
|
-
|
635
|
+
known_taps = xp.asarray(known_taps, dtype=xp.float64)
|
636
|
+
atol_arg = {'atol': 3e-8} if xp_default_dtype(xp) == xp.float32 else {}
|
637
|
+
xp_assert_close(taps, known_taps, **atol_arg)
|
563
638
|
|
564
639
|
# With linear changes:
|
565
|
-
taps = firls(7, (0, 1, 2, 3, 4, 5),
|
640
|
+
taps = firls(7, xp.asarray((0, 1, 2, 3, 4, 5)),
|
641
|
+
xp.asarray([1, 0, 0, 1, 1, 0]), fs=20)
|
566
642
|
# >> taps = firls(6, [0, 0.1, 0.2, 0.3, 0.4, 0.5], [1, 0, 0, 1, 1, 0])
|
567
643
|
known_taps = [
|
568
644
|
1.156090832768218, -4.1385894727395849, 7.5288619164321826,
|
569
645
|
-8.5530572592947856, 7.5288619164321826, -4.1385894727395849,
|
570
646
|
1.156090832768218]
|
647
|
+
known_taps = xp.asarray(known_taps, dtype=xp.float64)
|
571
648
|
xp_assert_close(taps, known_taps)
|
572
649
|
|
573
|
-
def test_rank_deficient(self):
|
650
|
+
def test_rank_deficient(self, xp):
|
574
651
|
# solve() runs but warns (only sometimes, so here we don't use match)
|
575
|
-
x = firls(21, [0, 0.1, 0.9, 1], [1, 1, 0, 0])
|
576
|
-
w, h = freqz(x, fs=2.)
|
577
|
-
|
578
|
-
|
579
|
-
absh2
|
580
|
-
|
652
|
+
x = firls(21, xp.asarray([0, 0.1, 0.9, 1]), xp.asarray([1, 1, 0, 0]))
|
653
|
+
w, h = freqz(np.asarray(x), fs=2.)
|
654
|
+
w, h = map(xp.asarray, (w, h)) # XXX convert freqz
|
655
|
+
absh2 = xp.abs(h[:2])
|
656
|
+
xp_assert_close(absh2, xp.ones_like(absh2), atol=1e-5)
|
657
|
+
absh2 = xp.abs(h[-2:])
|
658
|
+
xp_assert_close(absh2, xp.zeros_like(absh2), atol=1e-6, rtol=1e-7)
|
581
659
|
# switch to pinvh (tolerances could be higher with longer
|
582
660
|
# filters, but using shorter ones is faster computationally and
|
583
661
|
# the idea is the same)
|
584
|
-
x = firls(101, [0, 0.01, 0.99, 1], [1, 1, 0, 0])
|
585
|
-
w, h = freqz(x, fs=2.)
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
662
|
+
x = firls(101, xp.asarray([0, 0.01, 0.99, 1]), xp.asarray([1, 1, 0, 0]))
|
663
|
+
w, h = freqz(np.asarray(x), fs=2.)
|
664
|
+
w, h = map(xp.asarray, (w, h)) # XXX convert freqz
|
665
|
+
mask = xp.asarray(w < 0.01)
|
666
|
+
h = xp.asarray(h)
|
667
|
+
assert xp.sum(xp.astype(mask, xp.int64)) > 3
|
668
|
+
habs = xp.abs(h[mask])
|
669
|
+
xp_assert_close(habs, xp.ones_like(habs), atol=1e-4)
|
670
|
+
mask = xp.asarray(w > 0.99)
|
671
|
+
assert xp.sum(xp.astype(mask, xp.int64)) > 3
|
672
|
+
habs = xp.abs(h[mask])
|
673
|
+
xp_assert_close(habs, xp.zeros_like(habs), atol=1e-4)
|
594
674
|
|
595
675
|
def test_fs_validation(self):
|
596
676
|
with pytest.raises(ValueError, match="Sampling.*single scalar"):
|
597
677
|
firls(11, .1, 1, fs=np.array([10, 20]))
|
598
678
|
|
599
679
|
class TestMinimumPhase:
|
680
|
+
|
600
681
|
@pytest.mark.thread_unsafe
|
601
682
|
def test_bad_args(self):
|
602
683
|
# not enough taps
|
603
684
|
assert_raises(ValueError, minimum_phase, [1.])
|
604
685
|
assert_raises(ValueError, minimum_phase, [1., 1.])
|
605
686
|
assert_raises(ValueError, minimum_phase, np.full(10, 1j))
|
606
|
-
assert_raises(ValueError, minimum_phase, 'foo')
|
687
|
+
assert_raises((ValueError, TypeError), minimum_phase, 'foo')
|
607
688
|
assert_raises(ValueError, minimum_phase, np.ones(10), n_fft=8)
|
608
689
|
assert_raises(ValueError, minimum_phase, np.ones(10), method='foo')
|
609
690
|
assert_warns(RuntimeWarning, minimum_phase, np.arange(3))
|
@@ -630,7 +711,9 @@ class TestMinimumPhase:
|
|
630
711
|
assert len(h_linear) == len(h_new)
|
631
712
|
xp_assert_close(np.abs(fft(h_new)), np.abs(fft(h_linear)), rtol=1e-4)
|
632
713
|
|
633
|
-
|
714
|
+
@skip_xp_backends("dask.array", reason="too slow")
|
715
|
+
@skip_xp_backends("jax.numpy", reason="immutable arrays")
|
716
|
+
def test_hilbert(self, xp):
|
634
717
|
# compare to MATLAB output of reference implementation
|
635
718
|
|
636
719
|
# f=[0 0.3 0.5 1];
|
@@ -639,6 +722,8 @@ class TestMinimumPhase:
|
|
639
722
|
h = remez(12, [0, 0.3, 0.5, 1], [1, 0], fs=2.)
|
640
723
|
k = [0.349585548646686, 0.373552164395447, 0.326082685363438,
|
641
724
|
0.077152207480935, -0.129943946349364, -0.059355880509749]
|
725
|
+
h = xp.asarray(h)
|
726
|
+
k = xp.asarray(k, dtype=xp.float64)
|
642
727
|
m = minimum_phase(h, 'hilbert')
|
643
728
|
xp_assert_close(m, k, rtol=5e-3)
|
644
729
|
|
@@ -650,5 +735,112 @@ class TestMinimumPhase:
|
|
650
735
|
-0.157957283165866, 0.151739294892963, -0.129293146705090,
|
651
736
|
0.100787844523204, -0.065832656741252, 0.035361328741024,
|
652
737
|
-0.014977068692269, -0.158416139047557]
|
738
|
+
h = xp.asarray(h)
|
739
|
+
k = xp.asarray(k, dtype=xp.float64)
|
653
740
|
m = minimum_phase(h, 'hilbert', n_fft=2**19)
|
654
741
|
xp_assert_close(m, k, rtol=2e-3)
|
742
|
+
|
743
|
+
|
744
|
+
class Testfirwin_2d:
|
745
|
+
def test_invalid_args(self):
|
746
|
+
with pytest.raises(ValueError,
|
747
|
+
match="hsize must be a 2-element tuple or list"):
|
748
|
+
firwin_2d((50,), window=(("kaiser", 5.0), "boxcar"), fc=0.4)
|
749
|
+
|
750
|
+
with pytest.raises(ValueError,
|
751
|
+
match="window must be a 2-element tuple or list"):
|
752
|
+
firwin_2d((51, 51), window=("hamming",), fc=0.5)
|
753
|
+
|
754
|
+
with pytest.raises(ValueError,
|
755
|
+
match="window must be a 2-element tuple or list"):
|
756
|
+
firwin_2d((51, 51), window="invalid_window", fc=0.5)
|
757
|
+
|
758
|
+
def test_filter_design(self):
|
759
|
+
hsize = (51, 51)
|
760
|
+
window = (("kaiser", 8.0), ("kaiser", 8.0))
|
761
|
+
fc = 0.4
|
762
|
+
taps_kaiser = firwin_2d(hsize, window, fc=fc)
|
763
|
+
assert taps_kaiser.shape == (51, 51)
|
764
|
+
|
765
|
+
window = ("hamming", "hamming")
|
766
|
+
taps_hamming = firwin_2d(hsize, window, fc=fc)
|
767
|
+
assert taps_hamming.shape == (51, 51)
|
768
|
+
|
769
|
+
def test_impulse_response(self):
|
770
|
+
hsize = (31, 31)
|
771
|
+
window = ("hamming", "hamming")
|
772
|
+
fc = 0.4
|
773
|
+
taps = firwin_2d(hsize, window, fc=fc)
|
774
|
+
|
775
|
+
impulse = np.zeros((63, 63))
|
776
|
+
impulse[31, 31] = 1
|
777
|
+
|
778
|
+
response = convolve2d(impulse, taps, mode='same')
|
779
|
+
|
780
|
+
expected_response = taps
|
781
|
+
xp_assert_close(response[16:47, 16:47], expected_response, rtol=1e-5)
|
782
|
+
|
783
|
+
def test_frequency_response(self):
|
784
|
+
"""Compare 1d and 2d frequency response. """
|
785
|
+
hsize = (31, 31)
|
786
|
+
windows = ("hamming", "hamming")
|
787
|
+
fc = 0.4
|
788
|
+
taps_1d = firwin(numtaps=hsize[0], cutoff=fc, window=windows[0])
|
789
|
+
taps_2d = firwin_2d(hsize, windows, fc=fc)
|
790
|
+
|
791
|
+
f_resp_1d = fft(taps_1d)
|
792
|
+
f_resp_2d = fft2(taps_2d)
|
793
|
+
|
794
|
+
xp_assert_close(f_resp_2d[0, :], f_resp_1d,
|
795
|
+
err_msg='DC Gain at (0, f1) is not unity!')
|
796
|
+
xp_assert_close(f_resp_2d[:, 0], f_resp_1d,
|
797
|
+
err_msg='DC Gain at (f0, 0) is not unity!')
|
798
|
+
xp_assert_close(f_resp_2d, np.outer(f_resp_1d, f_resp_1d),
|
799
|
+
atol=np.finfo(f_resp_2d.dtype).resolution,
|
800
|
+
err_msg='2d frequency response is not product of 1d responses')
|
801
|
+
|
802
|
+
def test_symmetry(self):
|
803
|
+
hsize = (51, 51)
|
804
|
+
window = ("hamming", "hamming")
|
805
|
+
fc = 0.4
|
806
|
+
taps = firwin_2d(hsize, window, fc=fc)
|
807
|
+
xp_assert_close(taps, np.flip(taps), rtol=1e-5)
|
808
|
+
|
809
|
+
def test_circular_symmetry(self):
|
810
|
+
hsize = (51, 51)
|
811
|
+
window = "hamming"
|
812
|
+
taps = firwin_2d(hsize, window, circular=True, fc=0.5)
|
813
|
+
center = hsize[0] // 2
|
814
|
+
for i in range(hsize[0]):
|
815
|
+
for j in range(hsize[1]):
|
816
|
+
xp_assert_close(taps[i, j],
|
817
|
+
taps[center - (i - center), center - (j - center)],
|
818
|
+
rtol=1e-5)
|
819
|
+
|
820
|
+
def test_edge_case_circular(self):
|
821
|
+
hsize = (3, 3)
|
822
|
+
window = "hamming"
|
823
|
+
taps_small = firwin_2d(hsize, window, circular=True, fc=0.5)
|
824
|
+
assert taps_small.shape == (3, 3)
|
825
|
+
|
826
|
+
hsize = (101, 101)
|
827
|
+
taps_large = firwin_2d(hsize, window, circular=True, fc=0.5)
|
828
|
+
assert taps_large.shape == (101, 101)
|
829
|
+
|
830
|
+
def test_known_result(self):
|
831
|
+
hsize = (5, 5)
|
832
|
+
window = ('kaiser', 8.0)
|
833
|
+
fc = 0.1
|
834
|
+
fs = 2
|
835
|
+
|
836
|
+
row_filter = firwin(hsize[0], cutoff=fc, window=window, fs=fs)
|
837
|
+
col_filter = firwin(hsize[1], cutoff=fc, window=window, fs=fs)
|
838
|
+
known_result = np.outer(row_filter, col_filter)
|
839
|
+
|
840
|
+
taps = firwin_2d(hsize, (window, window), fc=fc)
|
841
|
+
assert taps.shape == known_result.shape, (
|
842
|
+
f"Shape mismatch: {taps.shape} vs {known_result.shape}"
|
843
|
+
)
|
844
|
+
assert np.allclose(taps, known_result, rtol=1e-1), (
|
845
|
+
f"Filter shape mismatch: {taps} vs {known_result}"
|
846
|
+
)
|