scipy 1.16.1__cp314-cp314-macosx_10_14_x86_64.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.
Files changed (1416) hide show
  1. scipy/.dylibs/libgcc_s.1.1.dylib +0 -0
  2. scipy/.dylibs/libgfortran.5.dylib +0 -0
  3. scipy/.dylibs/libquadmath.0.dylib +0 -0
  4. scipy/.dylibs/libscipy_openblas.dylib +0 -0
  5. scipy/__config__.py +161 -0
  6. scipy/__init__.py +138 -0
  7. scipy/_cyutility.cpython-314-darwin.so +0 -0
  8. scipy/_distributor_init.py +18 -0
  9. scipy/_lib/__init__.py +14 -0
  10. scipy/_lib/_array_api.py +931 -0
  11. scipy/_lib/_array_api_compat_vendor.py +9 -0
  12. scipy/_lib/_array_api_no_0d.py +103 -0
  13. scipy/_lib/_bunch.py +229 -0
  14. scipy/_lib/_ccallback.py +251 -0
  15. scipy/_lib/_ccallback_c.cpython-314-darwin.so +0 -0
  16. scipy/_lib/_disjoint_set.py +254 -0
  17. scipy/_lib/_docscrape.py +761 -0
  18. scipy/_lib/_elementwise_iterative_method.py +346 -0
  19. scipy/_lib/_fpumode.cpython-314-darwin.so +0 -0
  20. scipy/_lib/_gcutils.py +105 -0
  21. scipy/_lib/_pep440.py +487 -0
  22. scipy/_lib/_sparse.py +41 -0
  23. scipy/_lib/_test_ccallback.cpython-314-darwin.so +0 -0
  24. scipy/_lib/_test_deprecation_call.cpython-314-darwin.so +0 -0
  25. scipy/_lib/_test_deprecation_def.cpython-314-darwin.so +0 -0
  26. scipy/_lib/_testutils.py +373 -0
  27. scipy/_lib/_threadsafety.py +58 -0
  28. scipy/_lib/_tmpdirs.py +86 -0
  29. scipy/_lib/_uarray/LICENSE +29 -0
  30. scipy/_lib/_uarray/__init__.py +116 -0
  31. scipy/_lib/_uarray/_backend.py +707 -0
  32. scipy/_lib/_uarray/_uarray.cpython-314-darwin.so +0 -0
  33. scipy/_lib/_util.py +1283 -0
  34. scipy/_lib/array_api_compat/__init__.py +22 -0
  35. scipy/_lib/array_api_compat/_internal.py +59 -0
  36. scipy/_lib/array_api_compat/common/__init__.py +1 -0
  37. scipy/_lib/array_api_compat/common/_aliases.py +727 -0
  38. scipy/_lib/array_api_compat/common/_fft.py +213 -0
  39. scipy/_lib/array_api_compat/common/_helpers.py +1058 -0
  40. scipy/_lib/array_api_compat/common/_linalg.py +232 -0
  41. scipy/_lib/array_api_compat/common/_typing.py +192 -0
  42. scipy/_lib/array_api_compat/cupy/__init__.py +13 -0
  43. scipy/_lib/array_api_compat/cupy/_aliases.py +156 -0
  44. scipy/_lib/array_api_compat/cupy/_info.py +336 -0
  45. scipy/_lib/array_api_compat/cupy/_typing.py +31 -0
  46. scipy/_lib/array_api_compat/cupy/fft.py +36 -0
  47. scipy/_lib/array_api_compat/cupy/linalg.py +49 -0
  48. scipy/_lib/array_api_compat/dask/__init__.py +0 -0
  49. scipy/_lib/array_api_compat/dask/array/__init__.py +12 -0
  50. scipy/_lib/array_api_compat/dask/array/_aliases.py +376 -0
  51. scipy/_lib/array_api_compat/dask/array/_info.py +416 -0
  52. scipy/_lib/array_api_compat/dask/array/fft.py +21 -0
  53. scipy/_lib/array_api_compat/dask/array/linalg.py +72 -0
  54. scipy/_lib/array_api_compat/numpy/__init__.py +28 -0
  55. scipy/_lib/array_api_compat/numpy/_aliases.py +190 -0
  56. scipy/_lib/array_api_compat/numpy/_info.py +366 -0
  57. scipy/_lib/array_api_compat/numpy/_typing.py +30 -0
  58. scipy/_lib/array_api_compat/numpy/fft.py +35 -0
  59. scipy/_lib/array_api_compat/numpy/linalg.py +143 -0
  60. scipy/_lib/array_api_compat/torch/__init__.py +22 -0
  61. scipy/_lib/array_api_compat/torch/_aliases.py +855 -0
  62. scipy/_lib/array_api_compat/torch/_info.py +369 -0
  63. scipy/_lib/array_api_compat/torch/_typing.py +3 -0
  64. scipy/_lib/array_api_compat/torch/fft.py +85 -0
  65. scipy/_lib/array_api_compat/torch/linalg.py +121 -0
  66. scipy/_lib/array_api_extra/__init__.py +38 -0
  67. scipy/_lib/array_api_extra/_delegation.py +171 -0
  68. scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
  69. scipy/_lib/array_api_extra/_lib/_at.py +463 -0
  70. scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
  71. scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
  72. scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
  73. scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
  74. scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
  75. scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
  76. scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
  77. scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
  78. scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
  79. scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
  80. scipy/_lib/array_api_extra/testing.py +359 -0
  81. scipy/_lib/cobyqa/__init__.py +20 -0
  82. scipy/_lib/cobyqa/framework.py +1240 -0
  83. scipy/_lib/cobyqa/main.py +1506 -0
  84. scipy/_lib/cobyqa/models.py +1529 -0
  85. scipy/_lib/cobyqa/problem.py +1296 -0
  86. scipy/_lib/cobyqa/settings.py +132 -0
  87. scipy/_lib/cobyqa/subsolvers/__init__.py +14 -0
  88. scipy/_lib/cobyqa/subsolvers/geometry.py +387 -0
  89. scipy/_lib/cobyqa/subsolvers/optim.py +1203 -0
  90. scipy/_lib/cobyqa/utils/__init__.py +18 -0
  91. scipy/_lib/cobyqa/utils/exceptions.py +22 -0
  92. scipy/_lib/cobyqa/utils/math.py +77 -0
  93. scipy/_lib/cobyqa/utils/versions.py +67 -0
  94. scipy/_lib/decorator.py +399 -0
  95. scipy/_lib/deprecation.py +274 -0
  96. scipy/_lib/doccer.py +366 -0
  97. scipy/_lib/messagestream.cpython-314-darwin.so +0 -0
  98. scipy/_lib/pyprima/__init__.py +212 -0
  99. scipy/_lib/pyprima/cobyla/__init__.py +0 -0
  100. scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
  101. scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
  102. scipy/_lib/pyprima/cobyla/geometry.py +226 -0
  103. scipy/_lib/pyprima/cobyla/initialize.py +215 -0
  104. scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
  105. scipy/_lib/pyprima/cobyla/update.py +289 -0
  106. scipy/_lib/pyprima/common/__init__.py +0 -0
  107. scipy/_lib/pyprima/common/_bounds.py +34 -0
  108. scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
  109. scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
  110. scipy/_lib/pyprima/common/_project.py +173 -0
  111. scipy/_lib/pyprima/common/checkbreak.py +93 -0
  112. scipy/_lib/pyprima/common/consts.py +47 -0
  113. scipy/_lib/pyprima/common/evaluate.py +99 -0
  114. scipy/_lib/pyprima/common/history.py +38 -0
  115. scipy/_lib/pyprima/common/infos.py +30 -0
  116. scipy/_lib/pyprima/common/linalg.py +435 -0
  117. scipy/_lib/pyprima/common/message.py +290 -0
  118. scipy/_lib/pyprima/common/powalg.py +131 -0
  119. scipy/_lib/pyprima/common/preproc.py +277 -0
  120. scipy/_lib/pyprima/common/present.py +5 -0
  121. scipy/_lib/pyprima/common/ratio.py +54 -0
  122. scipy/_lib/pyprima/common/redrho.py +47 -0
  123. scipy/_lib/pyprima/common/selectx.py +296 -0
  124. scipy/_lib/tests/__init__.py +0 -0
  125. scipy/_lib/tests/test__gcutils.py +110 -0
  126. scipy/_lib/tests/test__pep440.py +67 -0
  127. scipy/_lib/tests/test__testutils.py +32 -0
  128. scipy/_lib/tests/test__threadsafety.py +51 -0
  129. scipy/_lib/tests/test__util.py +641 -0
  130. scipy/_lib/tests/test_array_api.py +322 -0
  131. scipy/_lib/tests/test_bunch.py +169 -0
  132. scipy/_lib/tests/test_ccallback.py +196 -0
  133. scipy/_lib/tests/test_config.py +45 -0
  134. scipy/_lib/tests/test_deprecation.py +10 -0
  135. scipy/_lib/tests/test_doccer.py +143 -0
  136. scipy/_lib/tests/test_import_cycles.py +18 -0
  137. scipy/_lib/tests/test_public_api.py +482 -0
  138. scipy/_lib/tests/test_scipy_version.py +28 -0
  139. scipy/_lib/tests/test_tmpdirs.py +48 -0
  140. scipy/_lib/tests/test_warnings.py +137 -0
  141. scipy/_lib/uarray.py +31 -0
  142. scipy/cluster/__init__.py +31 -0
  143. scipy/cluster/_hierarchy.cpython-314-darwin.so +0 -0
  144. scipy/cluster/_optimal_leaf_ordering.cpython-314-darwin.so +0 -0
  145. scipy/cluster/_vq.cpython-314-darwin.so +0 -0
  146. scipy/cluster/hierarchy.py +4348 -0
  147. scipy/cluster/tests/__init__.py +0 -0
  148. scipy/cluster/tests/hierarchy_test_data.py +145 -0
  149. scipy/cluster/tests/test_disjoint_set.py +202 -0
  150. scipy/cluster/tests/test_hierarchy.py +1238 -0
  151. scipy/cluster/tests/test_vq.py +434 -0
  152. scipy/cluster/vq.py +832 -0
  153. scipy/conftest.py +683 -0
  154. scipy/constants/__init__.py +358 -0
  155. scipy/constants/_codata.py +2266 -0
  156. scipy/constants/_constants.py +369 -0
  157. scipy/constants/codata.py +21 -0
  158. scipy/constants/constants.py +53 -0
  159. scipy/constants/tests/__init__.py +0 -0
  160. scipy/constants/tests/test_codata.py +78 -0
  161. scipy/constants/tests/test_constants.py +83 -0
  162. scipy/datasets/__init__.py +90 -0
  163. scipy/datasets/_download_all.py +71 -0
  164. scipy/datasets/_fetchers.py +225 -0
  165. scipy/datasets/_registry.py +26 -0
  166. scipy/datasets/_utils.py +81 -0
  167. scipy/datasets/tests/__init__.py +0 -0
  168. scipy/datasets/tests/test_data.py +128 -0
  169. scipy/differentiate/__init__.py +27 -0
  170. scipy/differentiate/_differentiate.py +1129 -0
  171. scipy/differentiate/tests/__init__.py +0 -0
  172. scipy/differentiate/tests/test_differentiate.py +694 -0
  173. scipy/fft/__init__.py +114 -0
  174. scipy/fft/_backend.py +196 -0
  175. scipy/fft/_basic.py +1650 -0
  176. scipy/fft/_basic_backend.py +197 -0
  177. scipy/fft/_debug_backends.py +22 -0
  178. scipy/fft/_fftlog.py +223 -0
  179. scipy/fft/_fftlog_backend.py +200 -0
  180. scipy/fft/_helper.py +348 -0
  181. scipy/fft/_pocketfft/LICENSE.md +25 -0
  182. scipy/fft/_pocketfft/__init__.py +9 -0
  183. scipy/fft/_pocketfft/basic.py +251 -0
  184. scipy/fft/_pocketfft/helper.py +249 -0
  185. scipy/fft/_pocketfft/pypocketfft.cpython-314-darwin.so +0 -0
  186. scipy/fft/_pocketfft/realtransforms.py +109 -0
  187. scipy/fft/_pocketfft/tests/__init__.py +0 -0
  188. scipy/fft/_pocketfft/tests/test_basic.py +1011 -0
  189. scipy/fft/_pocketfft/tests/test_real_transforms.py +505 -0
  190. scipy/fft/_realtransforms.py +706 -0
  191. scipy/fft/_realtransforms_backend.py +63 -0
  192. scipy/fft/tests/__init__.py +0 -0
  193. scipy/fft/tests/mock_backend.py +96 -0
  194. scipy/fft/tests/test_backend.py +98 -0
  195. scipy/fft/tests/test_basic.py +504 -0
  196. scipy/fft/tests/test_fftlog.py +215 -0
  197. scipy/fft/tests/test_helper.py +558 -0
  198. scipy/fft/tests/test_multithreading.py +84 -0
  199. scipy/fft/tests/test_real_transforms.py +247 -0
  200. scipy/fftpack/__init__.py +103 -0
  201. scipy/fftpack/_basic.py +428 -0
  202. scipy/fftpack/_helper.py +115 -0
  203. scipy/fftpack/_pseudo_diffs.py +554 -0
  204. scipy/fftpack/_realtransforms.py +598 -0
  205. scipy/fftpack/basic.py +20 -0
  206. scipy/fftpack/convolve.cpython-314-darwin.so +0 -0
  207. scipy/fftpack/helper.py +19 -0
  208. scipy/fftpack/pseudo_diffs.py +22 -0
  209. scipy/fftpack/realtransforms.py +19 -0
  210. scipy/fftpack/tests/__init__.py +0 -0
  211. scipy/fftpack/tests/fftw_double_ref.npz +0 -0
  212. scipy/fftpack/tests/fftw_longdouble_ref.npz +0 -0
  213. scipy/fftpack/tests/fftw_single_ref.npz +0 -0
  214. scipy/fftpack/tests/test.npz +0 -0
  215. scipy/fftpack/tests/test_basic.py +877 -0
  216. scipy/fftpack/tests/test_helper.py +54 -0
  217. scipy/fftpack/tests/test_import.py +33 -0
  218. scipy/fftpack/tests/test_pseudo_diffs.py +388 -0
  219. scipy/fftpack/tests/test_real_transforms.py +836 -0
  220. scipy/integrate/__init__.py +122 -0
  221. scipy/integrate/_bvp.py +1160 -0
  222. scipy/integrate/_cubature.py +729 -0
  223. scipy/integrate/_dop.cpython-314-darwin.so +0 -0
  224. scipy/integrate/_ivp/__init__.py +8 -0
  225. scipy/integrate/_ivp/base.py +290 -0
  226. scipy/integrate/_ivp/bdf.py +478 -0
  227. scipy/integrate/_ivp/common.py +451 -0
  228. scipy/integrate/_ivp/dop853_coefficients.py +193 -0
  229. scipy/integrate/_ivp/ivp.py +755 -0
  230. scipy/integrate/_ivp/lsoda.py +224 -0
  231. scipy/integrate/_ivp/radau.py +572 -0
  232. scipy/integrate/_ivp/rk.py +601 -0
  233. scipy/integrate/_ivp/tests/__init__.py +0 -0
  234. scipy/integrate/_ivp/tests/test_ivp.py +1287 -0
  235. scipy/integrate/_ivp/tests/test_rk.py +37 -0
  236. scipy/integrate/_lebedev.py +5450 -0
  237. scipy/integrate/_lsoda.cpython-314-darwin.so +0 -0
  238. scipy/integrate/_ode.py +1395 -0
  239. scipy/integrate/_odepack.cpython-314-darwin.so +0 -0
  240. scipy/integrate/_odepack_py.py +273 -0
  241. scipy/integrate/_quad_vec.py +674 -0
  242. scipy/integrate/_quadpack.cpython-314-darwin.so +0 -0
  243. scipy/integrate/_quadpack_py.py +1283 -0
  244. scipy/integrate/_quadrature.py +1336 -0
  245. scipy/integrate/_rules/__init__.py +12 -0
  246. scipy/integrate/_rules/_base.py +518 -0
  247. scipy/integrate/_rules/_gauss_kronrod.py +202 -0
  248. scipy/integrate/_rules/_gauss_legendre.py +62 -0
  249. scipy/integrate/_rules/_genz_malik.py +210 -0
  250. scipy/integrate/_tanhsinh.py +1385 -0
  251. scipy/integrate/_test_multivariate.cpython-314-darwin.so +0 -0
  252. scipy/integrate/_test_odeint_banded.cpython-314-darwin.so +0 -0
  253. scipy/integrate/_vode.cpython-314-darwin.so +0 -0
  254. scipy/integrate/dop.py +15 -0
  255. scipy/integrate/lsoda.py +15 -0
  256. scipy/integrate/odepack.py +17 -0
  257. scipy/integrate/quadpack.py +23 -0
  258. scipy/integrate/tests/__init__.py +0 -0
  259. scipy/integrate/tests/test__quad_vec.py +211 -0
  260. scipy/integrate/tests/test_banded_ode_solvers.py +305 -0
  261. scipy/integrate/tests/test_bvp.py +714 -0
  262. scipy/integrate/tests/test_cubature.py +1375 -0
  263. scipy/integrate/tests/test_integrate.py +840 -0
  264. scipy/integrate/tests/test_odeint_jac.py +74 -0
  265. scipy/integrate/tests/test_quadpack.py +680 -0
  266. scipy/integrate/tests/test_quadrature.py +730 -0
  267. scipy/integrate/tests/test_tanhsinh.py +1171 -0
  268. scipy/integrate/vode.py +15 -0
  269. scipy/interpolate/__init__.py +228 -0
  270. scipy/interpolate/_bary_rational.py +715 -0
  271. scipy/interpolate/_bsplines.py +2469 -0
  272. scipy/interpolate/_cubic.py +973 -0
  273. scipy/interpolate/_dfitpack.cpython-314-darwin.so +0 -0
  274. scipy/interpolate/_dierckx.cpython-314-darwin.so +0 -0
  275. scipy/interpolate/_fitpack.cpython-314-darwin.so +0 -0
  276. scipy/interpolate/_fitpack2.py +2397 -0
  277. scipy/interpolate/_fitpack_impl.py +811 -0
  278. scipy/interpolate/_fitpack_py.py +898 -0
  279. scipy/interpolate/_fitpack_repro.py +996 -0
  280. scipy/interpolate/_interpnd.cpython-314-darwin.so +0 -0
  281. scipy/interpolate/_interpolate.py +2266 -0
  282. scipy/interpolate/_ndbspline.py +415 -0
  283. scipy/interpolate/_ndgriddata.py +329 -0
  284. scipy/interpolate/_pade.py +67 -0
  285. scipy/interpolate/_polyint.py +1025 -0
  286. scipy/interpolate/_ppoly.cpython-314-darwin.so +0 -0
  287. scipy/interpolate/_rbf.py +290 -0
  288. scipy/interpolate/_rbfinterp.py +550 -0
  289. scipy/interpolate/_rbfinterp_pythran.cpython-314-darwin.so +0 -0
  290. scipy/interpolate/_rgi.py +764 -0
  291. scipy/interpolate/_rgi_cython.cpython-314-darwin.so +0 -0
  292. scipy/interpolate/dfitpack.py +24 -0
  293. scipy/interpolate/fitpack.py +31 -0
  294. scipy/interpolate/fitpack2.py +29 -0
  295. scipy/interpolate/interpnd.py +24 -0
  296. scipy/interpolate/interpolate.py +30 -0
  297. scipy/interpolate/ndgriddata.py +23 -0
  298. scipy/interpolate/polyint.py +24 -0
  299. scipy/interpolate/rbf.py +18 -0
  300. scipy/interpolate/tests/__init__.py +0 -0
  301. scipy/interpolate/tests/data/bug-1310.npz +0 -0
  302. scipy/interpolate/tests/data/estimate_gradients_hang.npy +0 -0
  303. scipy/interpolate/tests/data/gcvspl.npz +0 -0
  304. scipy/interpolate/tests/test_bary_rational.py +368 -0
  305. scipy/interpolate/tests/test_bsplines.py +3754 -0
  306. scipy/interpolate/tests/test_fitpack.py +519 -0
  307. scipy/interpolate/tests/test_fitpack2.py +1431 -0
  308. scipy/interpolate/tests/test_gil.py +64 -0
  309. scipy/interpolate/tests/test_interpnd.py +452 -0
  310. scipy/interpolate/tests/test_interpolate.py +2630 -0
  311. scipy/interpolate/tests/test_ndgriddata.py +308 -0
  312. scipy/interpolate/tests/test_pade.py +107 -0
  313. scipy/interpolate/tests/test_polyint.py +972 -0
  314. scipy/interpolate/tests/test_rbf.py +246 -0
  315. scipy/interpolate/tests/test_rbfinterp.py +534 -0
  316. scipy/interpolate/tests/test_rgi.py +1151 -0
  317. scipy/io/__init__.py +116 -0
  318. scipy/io/_fast_matrix_market/__init__.py +600 -0
  319. scipy/io/_fast_matrix_market/_fmm_core.cpython-314-darwin.so +0 -0
  320. scipy/io/_fortran.py +354 -0
  321. scipy/io/_harwell_boeing/__init__.py +7 -0
  322. scipy/io/_harwell_boeing/_fortran_format_parser.py +316 -0
  323. scipy/io/_harwell_boeing/hb.py +571 -0
  324. scipy/io/_harwell_boeing/tests/__init__.py +0 -0
  325. scipy/io/_harwell_boeing/tests/test_fortran_format.py +74 -0
  326. scipy/io/_harwell_boeing/tests/test_hb.py +70 -0
  327. scipy/io/_idl.py +917 -0
  328. scipy/io/_mmio.py +968 -0
  329. scipy/io/_netcdf.py +1104 -0
  330. scipy/io/_test_fortran.cpython-314-darwin.so +0 -0
  331. scipy/io/arff/__init__.py +28 -0
  332. scipy/io/arff/_arffread.py +873 -0
  333. scipy/io/arff/arffread.py +19 -0
  334. scipy/io/arff/tests/__init__.py +0 -0
  335. scipy/io/arff/tests/data/iris.arff +225 -0
  336. scipy/io/arff/tests/data/missing.arff +8 -0
  337. scipy/io/arff/tests/data/nodata.arff +11 -0
  338. scipy/io/arff/tests/data/quoted_nominal.arff +13 -0
  339. scipy/io/arff/tests/data/quoted_nominal_spaces.arff +13 -0
  340. scipy/io/arff/tests/data/test1.arff +10 -0
  341. scipy/io/arff/tests/data/test10.arff +8 -0
  342. scipy/io/arff/tests/data/test11.arff +11 -0
  343. scipy/io/arff/tests/data/test2.arff +15 -0
  344. scipy/io/arff/tests/data/test3.arff +6 -0
  345. scipy/io/arff/tests/data/test4.arff +11 -0
  346. scipy/io/arff/tests/data/test5.arff +26 -0
  347. scipy/io/arff/tests/data/test6.arff +12 -0
  348. scipy/io/arff/tests/data/test7.arff +15 -0
  349. scipy/io/arff/tests/data/test8.arff +12 -0
  350. scipy/io/arff/tests/data/test9.arff +14 -0
  351. scipy/io/arff/tests/test_arffread.py +421 -0
  352. scipy/io/harwell_boeing.py +17 -0
  353. scipy/io/idl.py +17 -0
  354. scipy/io/matlab/__init__.py +66 -0
  355. scipy/io/matlab/_byteordercodes.py +75 -0
  356. scipy/io/matlab/_mio.py +375 -0
  357. scipy/io/matlab/_mio4.py +632 -0
  358. scipy/io/matlab/_mio5.py +901 -0
  359. scipy/io/matlab/_mio5_params.py +281 -0
  360. scipy/io/matlab/_mio5_utils.cpython-314-darwin.so +0 -0
  361. scipy/io/matlab/_mio_utils.cpython-314-darwin.so +0 -0
  362. scipy/io/matlab/_miobase.py +435 -0
  363. scipy/io/matlab/_streams.cpython-314-darwin.so +0 -0
  364. scipy/io/matlab/byteordercodes.py +17 -0
  365. scipy/io/matlab/mio.py +16 -0
  366. scipy/io/matlab/mio4.py +17 -0
  367. scipy/io/matlab/mio5.py +19 -0
  368. scipy/io/matlab/mio5_params.py +18 -0
  369. scipy/io/matlab/mio5_utils.py +17 -0
  370. scipy/io/matlab/mio_utils.py +17 -0
  371. scipy/io/matlab/miobase.py +16 -0
  372. scipy/io/matlab/streams.py +16 -0
  373. scipy/io/matlab/tests/__init__.py +0 -0
  374. scipy/io/matlab/tests/data/bad_miuint32.mat +0 -0
  375. scipy/io/matlab/tests/data/bad_miutf8_array_name.mat +0 -0
  376. scipy/io/matlab/tests/data/big_endian.mat +0 -0
  377. scipy/io/matlab/tests/data/broken_utf8.mat +0 -0
  378. scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat +0 -0
  379. scipy/io/matlab/tests/data/corrupted_zlib_data.mat +0 -0
  380. scipy/io/matlab/tests/data/debigged_m4.mat +0 -0
  381. scipy/io/matlab/tests/data/japanese_utf8.txt +5 -0
  382. scipy/io/matlab/tests/data/little_endian.mat +0 -0
  383. scipy/io/matlab/tests/data/logical_sparse.mat +0 -0
  384. scipy/io/matlab/tests/data/malformed1.mat +0 -0
  385. scipy/io/matlab/tests/data/miuint32_for_miint32.mat +0 -0
  386. scipy/io/matlab/tests/data/miutf8_array_name.mat +0 -0
  387. scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat +0 -0
  388. scipy/io/matlab/tests/data/one_by_zero_char.mat +0 -0
  389. scipy/io/matlab/tests/data/parabola.mat +0 -0
  390. scipy/io/matlab/tests/data/single_empty_string.mat +0 -0
  391. scipy/io/matlab/tests/data/some_functions.mat +0 -0
  392. scipy/io/matlab/tests/data/sqr.mat +0 -0
  393. scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat +0 -0
  394. scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat +0 -0
  395. scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat +0 -0
  396. scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat +0 -0
  397. scipy/io/matlab/tests/data/test_empty_struct.mat +0 -0
  398. scipy/io/matlab/tests/data/test_mat4_le_floats.mat +0 -0
  399. scipy/io/matlab/tests/data/test_skip_variable.mat +0 -0
  400. scipy/io/matlab/tests/data/testbool_8_WIN64.mat +0 -0
  401. scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat +0 -0
  402. scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat +0 -0
  403. scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat +0 -0
  404. scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat +0 -0
  405. scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat +0 -0
  406. scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat +0 -0
  407. scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat +0 -0
  408. scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat +0 -0
  409. scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat +0 -0
  410. scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat +0 -0
  411. scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat +0 -0
  412. scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat +0 -0
  413. scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat +0 -0
  414. scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat +0 -0
  415. scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat +0 -0
  416. scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat +0 -0
  417. scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat +0 -0
  418. scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat +0 -0
  419. scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat +0 -0
  420. scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat +0 -0
  421. scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat +0 -0
  422. scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat +0 -0
  423. scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat +0 -0
  424. scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat +0 -0
  425. scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat +0 -0
  426. scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat +0 -0
  427. scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat +0 -0
  428. scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat +0 -0
  429. scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat +0 -0
  430. scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat +0 -0
  431. scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat +0 -0
  432. scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat +0 -0
  433. scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat +0 -0
  434. scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat +0 -0
  435. scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat +0 -0
  436. scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat +0 -0
  437. scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat +0 -0
  438. scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat +0 -0
  439. scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat +0 -0
  440. scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat +0 -0
  441. scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat +0 -0
  442. scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat +0 -0
  443. scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat +0 -0
  444. scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat +0 -0
  445. scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat +0 -0
  446. scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat +0 -0
  447. scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat +0 -0
  448. scipy/io/matlab/tests/data/testsimplecell.mat +0 -0
  449. scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat +0 -0
  450. scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat +0 -0
  451. scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat +0 -0
  452. scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat +0 -0
  453. scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat +0 -0
  454. scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat +0 -0
  455. scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat +0 -0
  456. scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat +0 -0
  457. scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat +0 -0
  458. scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat +0 -0
  459. scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat +0 -0
  460. scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat +0 -0
  461. scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat +0 -0
  462. scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat +0 -0
  463. scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat +0 -0
  464. scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat +0 -0
  465. scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat +0 -0
  466. scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat +0 -0
  467. scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat +0 -0
  468. scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat +0 -0
  469. scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat +0 -0
  470. scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat +0 -0
  471. scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat +0 -0
  472. scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat +0 -0
  473. scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat +0 -0
  474. scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat +0 -0
  475. scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat +0 -0
  476. scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat +0 -0
  477. scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat +0 -0
  478. scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat +0 -0
  479. scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat +0 -0
  480. scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat +0 -0
  481. scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat +0 -0
  482. scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat +0 -0
  483. scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat +0 -0
  484. scipy/io/matlab/tests/data/testvec_4_GLNX86.mat +0 -0
  485. scipy/io/matlab/tests/test_byteordercodes.py +29 -0
  486. scipy/io/matlab/tests/test_mio.py +1399 -0
  487. scipy/io/matlab/tests/test_mio5_utils.py +179 -0
  488. scipy/io/matlab/tests/test_mio_funcs.py +51 -0
  489. scipy/io/matlab/tests/test_mio_utils.py +45 -0
  490. scipy/io/matlab/tests/test_miobase.py +32 -0
  491. scipy/io/matlab/tests/test_pathological.py +33 -0
  492. scipy/io/matlab/tests/test_streams.py +241 -0
  493. scipy/io/mmio.py +17 -0
  494. scipy/io/netcdf.py +17 -0
  495. scipy/io/tests/__init__.py +0 -0
  496. scipy/io/tests/data/Transparent Busy.ani +0 -0
  497. scipy/io/tests/data/array_float32_1d.sav +0 -0
  498. scipy/io/tests/data/array_float32_2d.sav +0 -0
  499. scipy/io/tests/data/array_float32_3d.sav +0 -0
  500. scipy/io/tests/data/array_float32_4d.sav +0 -0
  501. scipy/io/tests/data/array_float32_5d.sav +0 -0
  502. scipy/io/tests/data/array_float32_6d.sav +0 -0
  503. scipy/io/tests/data/array_float32_7d.sav +0 -0
  504. scipy/io/tests/data/array_float32_8d.sav +0 -0
  505. scipy/io/tests/data/array_float32_pointer_1d.sav +0 -0
  506. scipy/io/tests/data/array_float32_pointer_2d.sav +0 -0
  507. scipy/io/tests/data/array_float32_pointer_3d.sav +0 -0
  508. scipy/io/tests/data/array_float32_pointer_4d.sav +0 -0
  509. scipy/io/tests/data/array_float32_pointer_5d.sav +0 -0
  510. scipy/io/tests/data/array_float32_pointer_6d.sav +0 -0
  511. scipy/io/tests/data/array_float32_pointer_7d.sav +0 -0
  512. scipy/io/tests/data/array_float32_pointer_8d.sav +0 -0
  513. scipy/io/tests/data/example_1.nc +0 -0
  514. scipy/io/tests/data/example_2.nc +0 -0
  515. scipy/io/tests/data/example_3_maskedvals.nc +0 -0
  516. scipy/io/tests/data/fortran-3x3d-2i.dat +0 -0
  517. scipy/io/tests/data/fortran-mixed.dat +0 -0
  518. scipy/io/tests/data/fortran-sf8-11x1x10.dat +0 -0
  519. scipy/io/tests/data/fortran-sf8-15x10x22.dat +0 -0
  520. scipy/io/tests/data/fortran-sf8-1x1x1.dat +0 -0
  521. scipy/io/tests/data/fortran-sf8-1x1x5.dat +0 -0
  522. scipy/io/tests/data/fortran-sf8-1x1x7.dat +0 -0
  523. scipy/io/tests/data/fortran-sf8-1x3x5.dat +0 -0
  524. scipy/io/tests/data/fortran-si4-11x1x10.dat +0 -0
  525. scipy/io/tests/data/fortran-si4-15x10x22.dat +0 -0
  526. scipy/io/tests/data/fortran-si4-1x1x1.dat +0 -0
  527. scipy/io/tests/data/fortran-si4-1x1x5.dat +0 -0
  528. scipy/io/tests/data/fortran-si4-1x1x7.dat +0 -0
  529. scipy/io/tests/data/fortran-si4-1x3x5.dat +0 -0
  530. scipy/io/tests/data/invalid_pointer.sav +0 -0
  531. scipy/io/tests/data/null_pointer.sav +0 -0
  532. scipy/io/tests/data/scalar_byte.sav +0 -0
  533. scipy/io/tests/data/scalar_byte_descr.sav +0 -0
  534. scipy/io/tests/data/scalar_complex32.sav +0 -0
  535. scipy/io/tests/data/scalar_complex64.sav +0 -0
  536. scipy/io/tests/data/scalar_float32.sav +0 -0
  537. scipy/io/tests/data/scalar_float64.sav +0 -0
  538. scipy/io/tests/data/scalar_heap_pointer.sav +0 -0
  539. scipy/io/tests/data/scalar_int16.sav +0 -0
  540. scipy/io/tests/data/scalar_int32.sav +0 -0
  541. scipy/io/tests/data/scalar_int64.sav +0 -0
  542. scipy/io/tests/data/scalar_string.sav +0 -0
  543. scipy/io/tests/data/scalar_uint16.sav +0 -0
  544. scipy/io/tests/data/scalar_uint32.sav +0 -0
  545. scipy/io/tests/data/scalar_uint64.sav +0 -0
  546. scipy/io/tests/data/struct_arrays.sav +0 -0
  547. scipy/io/tests/data/struct_arrays_byte_idl80.sav +0 -0
  548. scipy/io/tests/data/struct_arrays_replicated.sav +0 -0
  549. scipy/io/tests/data/struct_arrays_replicated_3d.sav +0 -0
  550. scipy/io/tests/data/struct_inherit.sav +0 -0
  551. scipy/io/tests/data/struct_pointer_arrays.sav +0 -0
  552. scipy/io/tests/data/struct_pointer_arrays_replicated.sav +0 -0
  553. scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav +0 -0
  554. scipy/io/tests/data/struct_pointers.sav +0 -0
  555. scipy/io/tests/data/struct_pointers_replicated.sav +0 -0
  556. scipy/io/tests/data/struct_pointers_replicated_3d.sav +0 -0
  557. scipy/io/tests/data/struct_scalars.sav +0 -0
  558. scipy/io/tests/data/struct_scalars_replicated.sav +0 -0
  559. scipy/io/tests/data/struct_scalars_replicated_3d.sav +0 -0
  560. scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav +0 -0
  561. scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav +0 -0
  562. scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav +0 -0
  563. scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav +0 -0
  564. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav +0 -0
  565. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav +0 -0
  566. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav +0 -0
  567. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav +0 -0
  568. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav +0 -0
  569. scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav +0 -0
  570. scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav +0 -0
  571. scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav +0 -0
  572. scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav +0 -0
  573. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav +0 -0
  574. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav +0 -0
  575. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav +0 -0
  576. scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav +0 -0
  577. scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav +0 -0
  578. scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav +0 -0
  579. scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav +0 -0
  580. scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav +0 -0
  581. scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav +0 -0
  582. scipy/io/tests/data/various_compressed.sav +0 -0
  583. scipy/io/tests/test_fortran.py +264 -0
  584. scipy/io/tests/test_idl.py +483 -0
  585. scipy/io/tests/test_mmio.py +831 -0
  586. scipy/io/tests/test_netcdf.py +550 -0
  587. scipy/io/tests/test_paths.py +93 -0
  588. scipy/io/tests/test_wavfile.py +501 -0
  589. scipy/io/wavfile.py +938 -0
  590. scipy/linalg/__init__.pxd +1 -0
  591. scipy/linalg/__init__.py +236 -0
  592. scipy/linalg/_basic.py +2146 -0
  593. scipy/linalg/_blas_subroutines.h +164 -0
  594. scipy/linalg/_cythonized_array_utils.cpython-314-darwin.so +0 -0
  595. scipy/linalg/_cythonized_array_utils.pxd +40 -0
  596. scipy/linalg/_cythonized_array_utils.pyi +16 -0
  597. scipy/linalg/_decomp.py +1645 -0
  598. scipy/linalg/_decomp_cholesky.py +413 -0
  599. scipy/linalg/_decomp_cossin.py +236 -0
  600. scipy/linalg/_decomp_interpolative.cpython-314-darwin.so +0 -0
  601. scipy/linalg/_decomp_ldl.py +356 -0
  602. scipy/linalg/_decomp_lu.py +401 -0
  603. scipy/linalg/_decomp_lu_cython.cpython-314-darwin.so +0 -0
  604. scipy/linalg/_decomp_lu_cython.pyi +6 -0
  605. scipy/linalg/_decomp_polar.py +113 -0
  606. scipy/linalg/_decomp_qr.py +494 -0
  607. scipy/linalg/_decomp_qz.py +452 -0
  608. scipy/linalg/_decomp_schur.py +336 -0
  609. scipy/linalg/_decomp_svd.py +545 -0
  610. scipy/linalg/_decomp_update.cpython-314-darwin.so +0 -0
  611. scipy/linalg/_expm_frechet.py +417 -0
  612. scipy/linalg/_fblas.cpython-314-darwin.so +0 -0
  613. scipy/linalg/_flapack.cpython-314-darwin.so +0 -0
  614. scipy/linalg/_lapack_subroutines.h +1521 -0
  615. scipy/linalg/_linalg_pythran.cpython-314-darwin.so +0 -0
  616. scipy/linalg/_matfuncs.py +1050 -0
  617. scipy/linalg/_matfuncs_expm.cpython-314-darwin.so +0 -0
  618. scipy/linalg/_matfuncs_expm.pyi +6 -0
  619. scipy/linalg/_matfuncs_inv_ssq.py +886 -0
  620. scipy/linalg/_matfuncs_schur_sqrtm.cpython-314-darwin.so +0 -0
  621. scipy/linalg/_matfuncs_sqrtm.py +107 -0
  622. scipy/linalg/_matfuncs_sqrtm_triu.cpython-314-darwin.so +0 -0
  623. scipy/linalg/_misc.py +191 -0
  624. scipy/linalg/_procrustes.py +113 -0
  625. scipy/linalg/_sketches.py +189 -0
  626. scipy/linalg/_solve_toeplitz.cpython-314-darwin.so +0 -0
  627. scipy/linalg/_solvers.py +862 -0
  628. scipy/linalg/_special_matrices.py +1322 -0
  629. scipy/linalg/_testutils.py +65 -0
  630. scipy/linalg/basic.py +23 -0
  631. scipy/linalg/blas.py +495 -0
  632. scipy/linalg/cython_blas.cpython-314-darwin.so +0 -0
  633. scipy/linalg/cython_blas.pxd +169 -0
  634. scipy/linalg/cython_blas.pyx +1432 -0
  635. scipy/linalg/cython_lapack.cpython-314-darwin.so +0 -0
  636. scipy/linalg/cython_lapack.pxd +1528 -0
  637. scipy/linalg/cython_lapack.pyx +12045 -0
  638. scipy/linalg/decomp.py +23 -0
  639. scipy/linalg/decomp_cholesky.py +21 -0
  640. scipy/linalg/decomp_lu.py +21 -0
  641. scipy/linalg/decomp_qr.py +20 -0
  642. scipy/linalg/decomp_schur.py +21 -0
  643. scipy/linalg/decomp_svd.py +21 -0
  644. scipy/linalg/interpolative.py +989 -0
  645. scipy/linalg/lapack.py +1081 -0
  646. scipy/linalg/matfuncs.py +23 -0
  647. scipy/linalg/misc.py +21 -0
  648. scipy/linalg/special_matrices.py +22 -0
  649. scipy/linalg/tests/__init__.py +0 -0
  650. scipy/linalg/tests/_cython_examples/extending.pyx +23 -0
  651. scipy/linalg/tests/_cython_examples/meson.build +34 -0
  652. scipy/linalg/tests/data/carex_15_data.npz +0 -0
  653. scipy/linalg/tests/data/carex_18_data.npz +0 -0
  654. scipy/linalg/tests/data/carex_19_data.npz +0 -0
  655. scipy/linalg/tests/data/carex_20_data.npz +0 -0
  656. scipy/linalg/tests/data/carex_6_data.npz +0 -0
  657. scipy/linalg/tests/data/gendare_20170120_data.npz +0 -0
  658. scipy/linalg/tests/test_basic.py +2074 -0
  659. scipy/linalg/tests/test_batch.py +588 -0
  660. scipy/linalg/tests/test_blas.py +1127 -0
  661. scipy/linalg/tests/test_cython_blas.py +118 -0
  662. scipy/linalg/tests/test_cython_lapack.py +22 -0
  663. scipy/linalg/tests/test_cythonized_array_utils.py +130 -0
  664. scipy/linalg/tests/test_decomp.py +3189 -0
  665. scipy/linalg/tests/test_decomp_cholesky.py +268 -0
  666. scipy/linalg/tests/test_decomp_cossin.py +314 -0
  667. scipy/linalg/tests/test_decomp_ldl.py +137 -0
  668. scipy/linalg/tests/test_decomp_lu.py +308 -0
  669. scipy/linalg/tests/test_decomp_polar.py +110 -0
  670. scipy/linalg/tests/test_decomp_update.py +1701 -0
  671. scipy/linalg/tests/test_extending.py +46 -0
  672. scipy/linalg/tests/test_fblas.py +607 -0
  673. scipy/linalg/tests/test_interpolative.py +232 -0
  674. scipy/linalg/tests/test_lapack.py +3616 -0
  675. scipy/linalg/tests/test_matfuncs.py +1125 -0
  676. scipy/linalg/tests/test_matmul_toeplitz.py +136 -0
  677. scipy/linalg/tests/test_procrustes.py +214 -0
  678. scipy/linalg/tests/test_sketches.py +118 -0
  679. scipy/linalg/tests/test_solve_toeplitz.py +150 -0
  680. scipy/linalg/tests/test_solvers.py +844 -0
  681. scipy/linalg/tests/test_special_matrices.py +636 -0
  682. scipy/misc/__init__.py +6 -0
  683. scipy/misc/common.py +6 -0
  684. scipy/misc/doccer.py +6 -0
  685. scipy/ndimage/__init__.py +174 -0
  686. scipy/ndimage/_ctest.cpython-314-darwin.so +0 -0
  687. scipy/ndimage/_cytest.cpython-314-darwin.so +0 -0
  688. scipy/ndimage/_delegators.py +303 -0
  689. scipy/ndimage/_filters.py +2422 -0
  690. scipy/ndimage/_fourier.py +306 -0
  691. scipy/ndimage/_interpolation.py +1033 -0
  692. scipy/ndimage/_measurements.py +1689 -0
  693. scipy/ndimage/_morphology.py +2634 -0
  694. scipy/ndimage/_nd_image.cpython-314-darwin.so +0 -0
  695. scipy/ndimage/_ndimage_api.py +16 -0
  696. scipy/ndimage/_ni_docstrings.py +214 -0
  697. scipy/ndimage/_ni_label.cpython-314-darwin.so +0 -0
  698. scipy/ndimage/_ni_support.py +139 -0
  699. scipy/ndimage/_rank_filter_1d.cpython-314-darwin.so +0 -0
  700. scipy/ndimage/_support_alternative_backends.py +84 -0
  701. scipy/ndimage/filters.py +27 -0
  702. scipy/ndimage/fourier.py +21 -0
  703. scipy/ndimage/interpolation.py +22 -0
  704. scipy/ndimage/measurements.py +24 -0
  705. scipy/ndimage/morphology.py +27 -0
  706. scipy/ndimage/tests/__init__.py +12 -0
  707. scipy/ndimage/tests/data/label_inputs.txt +21 -0
  708. scipy/ndimage/tests/data/label_results.txt +294 -0
  709. scipy/ndimage/tests/data/label_strels.txt +42 -0
  710. scipy/ndimage/tests/dots.png +0 -0
  711. scipy/ndimage/tests/test_c_api.py +102 -0
  712. scipy/ndimage/tests/test_datatypes.py +67 -0
  713. scipy/ndimage/tests/test_filters.py +3083 -0
  714. scipy/ndimage/tests/test_fourier.py +187 -0
  715. scipy/ndimage/tests/test_interpolation.py +1491 -0
  716. scipy/ndimage/tests/test_measurements.py +1592 -0
  717. scipy/ndimage/tests/test_morphology.py +2950 -0
  718. scipy/ndimage/tests/test_ni_support.py +78 -0
  719. scipy/ndimage/tests/test_splines.py +70 -0
  720. scipy/odr/__init__.py +131 -0
  721. scipy/odr/__odrpack.cpython-314-darwin.so +0 -0
  722. scipy/odr/_add_newdocs.py +34 -0
  723. scipy/odr/_models.py +315 -0
  724. scipy/odr/_odrpack.py +1154 -0
  725. scipy/odr/models.py +20 -0
  726. scipy/odr/odrpack.py +21 -0
  727. scipy/odr/tests/__init__.py +0 -0
  728. scipy/odr/tests/test_odr.py +607 -0
  729. scipy/optimize/__init__.pxd +1 -0
  730. scipy/optimize/__init__.py +460 -0
  731. scipy/optimize/_basinhopping.py +741 -0
  732. scipy/optimize/_bglu_dense.cpython-314-darwin.so +0 -0
  733. scipy/optimize/_bracket.py +706 -0
  734. scipy/optimize/_chandrupatla.py +551 -0
  735. scipy/optimize/_cobyla_py.py +297 -0
  736. scipy/optimize/_cobyqa_py.py +72 -0
  737. scipy/optimize/_constraints.py +598 -0
  738. scipy/optimize/_dcsrch.py +728 -0
  739. scipy/optimize/_differentiable_functions.py +835 -0
  740. scipy/optimize/_differentialevolution.py +1970 -0
  741. scipy/optimize/_direct.cpython-314-darwin.so +0 -0
  742. scipy/optimize/_direct_py.py +280 -0
  743. scipy/optimize/_dual_annealing.py +732 -0
  744. scipy/optimize/_elementwise.py +798 -0
  745. scipy/optimize/_group_columns.cpython-314-darwin.so +0 -0
  746. scipy/optimize/_hessian_update_strategy.py +479 -0
  747. scipy/optimize/_highspy/__init__.py +0 -0
  748. scipy/optimize/_highspy/_core.cpython-314-darwin.so +0 -0
  749. scipy/optimize/_highspy/_highs_options.cpython-314-darwin.so +0 -0
  750. scipy/optimize/_highspy/_highs_wrapper.py +338 -0
  751. scipy/optimize/_isotonic.py +157 -0
  752. scipy/optimize/_lbfgsb.cpython-314-darwin.so +0 -0
  753. scipy/optimize/_lbfgsb_py.py +634 -0
  754. scipy/optimize/_linesearch.py +896 -0
  755. scipy/optimize/_linprog.py +733 -0
  756. scipy/optimize/_linprog_doc.py +1434 -0
  757. scipy/optimize/_linprog_highs.py +422 -0
  758. scipy/optimize/_linprog_ip.py +1141 -0
  759. scipy/optimize/_linprog_rs.py +572 -0
  760. scipy/optimize/_linprog_simplex.py +663 -0
  761. scipy/optimize/_linprog_util.py +1521 -0
  762. scipy/optimize/_lsap.cpython-314-darwin.so +0 -0
  763. scipy/optimize/_lsq/__init__.py +5 -0
  764. scipy/optimize/_lsq/bvls.py +183 -0
  765. scipy/optimize/_lsq/common.py +731 -0
  766. scipy/optimize/_lsq/dogbox.py +345 -0
  767. scipy/optimize/_lsq/givens_elimination.cpython-314-darwin.so +0 -0
  768. scipy/optimize/_lsq/least_squares.py +1044 -0
  769. scipy/optimize/_lsq/lsq_linear.py +361 -0
  770. scipy/optimize/_lsq/trf.py +587 -0
  771. scipy/optimize/_lsq/trf_linear.py +249 -0
  772. scipy/optimize/_milp.py +394 -0
  773. scipy/optimize/_minimize.py +1199 -0
  774. scipy/optimize/_minpack.cpython-314-darwin.so +0 -0
  775. scipy/optimize/_minpack_py.py +1178 -0
  776. scipy/optimize/_moduleTNC.cpython-314-darwin.so +0 -0
  777. scipy/optimize/_nnls.py +96 -0
  778. scipy/optimize/_nonlin.py +1634 -0
  779. scipy/optimize/_numdiff.py +963 -0
  780. scipy/optimize/_optimize.py +4169 -0
  781. scipy/optimize/_pava_pybind.cpython-314-darwin.so +0 -0
  782. scipy/optimize/_qap.py +760 -0
  783. scipy/optimize/_remove_redundancy.py +522 -0
  784. scipy/optimize/_root.py +732 -0
  785. scipy/optimize/_root_scalar.py +538 -0
  786. scipy/optimize/_shgo.py +1606 -0
  787. scipy/optimize/_shgo_lib/__init__.py +0 -0
  788. scipy/optimize/_shgo_lib/_complex.py +1225 -0
  789. scipy/optimize/_shgo_lib/_vertex.py +460 -0
  790. scipy/optimize/_slsqp_py.py +603 -0
  791. scipy/optimize/_slsqplib.cpython-314-darwin.so +0 -0
  792. scipy/optimize/_spectral.py +260 -0
  793. scipy/optimize/_tnc.py +438 -0
  794. scipy/optimize/_trlib/__init__.py +12 -0
  795. scipy/optimize/_trlib/_trlib.cpython-314-darwin.so +0 -0
  796. scipy/optimize/_trustregion.py +318 -0
  797. scipy/optimize/_trustregion_constr/__init__.py +6 -0
  798. scipy/optimize/_trustregion_constr/canonical_constraint.py +390 -0
  799. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +231 -0
  800. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +584 -0
  801. scipy/optimize/_trustregion_constr/projections.py +411 -0
  802. scipy/optimize/_trustregion_constr/qp_subproblem.py +637 -0
  803. scipy/optimize/_trustregion_constr/report.py +49 -0
  804. scipy/optimize/_trustregion_constr/tests/__init__.py +0 -0
  805. scipy/optimize/_trustregion_constr/tests/test_canonical_constraint.py +296 -0
  806. scipy/optimize/_trustregion_constr/tests/test_nested_minimize.py +39 -0
  807. scipy/optimize/_trustregion_constr/tests/test_projections.py +214 -0
  808. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +645 -0
  809. scipy/optimize/_trustregion_constr/tests/test_report.py +34 -0
  810. scipy/optimize/_trustregion_constr/tr_interior_point.py +361 -0
  811. scipy/optimize/_trustregion_dogleg.py +122 -0
  812. scipy/optimize/_trustregion_exact.py +437 -0
  813. scipy/optimize/_trustregion_krylov.py +65 -0
  814. scipy/optimize/_trustregion_ncg.py +126 -0
  815. scipy/optimize/_tstutils.py +972 -0
  816. scipy/optimize/_zeros.cpython-314-darwin.so +0 -0
  817. scipy/optimize/_zeros_py.py +1475 -0
  818. scipy/optimize/cobyla.py +19 -0
  819. scipy/optimize/cython_optimize/__init__.py +133 -0
  820. scipy/optimize/cython_optimize/_zeros.cpython-314-darwin.so +0 -0
  821. scipy/optimize/cython_optimize/_zeros.pxd +33 -0
  822. scipy/optimize/cython_optimize/c_zeros.pxd +26 -0
  823. scipy/optimize/cython_optimize.pxd +11 -0
  824. scipy/optimize/elementwise.py +38 -0
  825. scipy/optimize/lbfgsb.py +23 -0
  826. scipy/optimize/linesearch.py +18 -0
  827. scipy/optimize/minpack.py +27 -0
  828. scipy/optimize/minpack2.py +17 -0
  829. scipy/optimize/moduleTNC.py +19 -0
  830. scipy/optimize/nonlin.py +29 -0
  831. scipy/optimize/optimize.py +40 -0
  832. scipy/optimize/slsqp.py +22 -0
  833. scipy/optimize/tests/__init__.py +0 -0
  834. scipy/optimize/tests/_cython_examples/extending.pyx +43 -0
  835. scipy/optimize/tests/_cython_examples/meson.build +32 -0
  836. scipy/optimize/tests/test__basinhopping.py +535 -0
  837. scipy/optimize/tests/test__differential_evolution.py +1703 -0
  838. scipy/optimize/tests/test__dual_annealing.py +416 -0
  839. scipy/optimize/tests/test__linprog_clean_inputs.py +312 -0
  840. scipy/optimize/tests/test__numdiff.py +885 -0
  841. scipy/optimize/tests/test__remove_redundancy.py +228 -0
  842. scipy/optimize/tests/test__root.py +124 -0
  843. scipy/optimize/tests/test__shgo.py +1164 -0
  844. scipy/optimize/tests/test__spectral.py +226 -0
  845. scipy/optimize/tests/test_bracket.py +896 -0
  846. scipy/optimize/tests/test_chandrupatla.py +982 -0
  847. scipy/optimize/tests/test_cobyla.py +195 -0
  848. scipy/optimize/tests/test_cobyqa.py +252 -0
  849. scipy/optimize/tests/test_constraint_conversion.py +286 -0
  850. scipy/optimize/tests/test_constraints.py +255 -0
  851. scipy/optimize/tests/test_cython_optimize.py +92 -0
  852. scipy/optimize/tests/test_differentiable_functions.py +1025 -0
  853. scipy/optimize/tests/test_direct.py +321 -0
  854. scipy/optimize/tests/test_extending.py +28 -0
  855. scipy/optimize/tests/test_hessian_update_strategy.py +300 -0
  856. scipy/optimize/tests/test_isotonic_regression.py +167 -0
  857. scipy/optimize/tests/test_lbfgsb_hessinv.py +65 -0
  858. scipy/optimize/tests/test_lbfgsb_setulb.py +122 -0
  859. scipy/optimize/tests/test_least_squares.py +986 -0
  860. scipy/optimize/tests/test_linear_assignment.py +116 -0
  861. scipy/optimize/tests/test_linesearch.py +328 -0
  862. scipy/optimize/tests/test_linprog.py +2577 -0
  863. scipy/optimize/tests/test_lsq_common.py +297 -0
  864. scipy/optimize/tests/test_lsq_linear.py +287 -0
  865. scipy/optimize/tests/test_milp.py +459 -0
  866. scipy/optimize/tests/test_minimize_constrained.py +845 -0
  867. scipy/optimize/tests/test_minpack.py +1194 -0
  868. scipy/optimize/tests/test_nnls.py +469 -0
  869. scipy/optimize/tests/test_nonlin.py +572 -0
  870. scipy/optimize/tests/test_optimize.py +3335 -0
  871. scipy/optimize/tests/test_quadratic_assignment.py +455 -0
  872. scipy/optimize/tests/test_regression.py +40 -0
  873. scipy/optimize/tests/test_slsqp.py +645 -0
  874. scipy/optimize/tests/test_tnc.py +345 -0
  875. scipy/optimize/tests/test_trustregion.py +110 -0
  876. scipy/optimize/tests/test_trustregion_exact.py +351 -0
  877. scipy/optimize/tests/test_trustregion_krylov.py +170 -0
  878. scipy/optimize/tests/test_zeros.py +998 -0
  879. scipy/optimize/tnc.py +22 -0
  880. scipy/optimize/zeros.py +26 -0
  881. scipy/signal/__init__.py +316 -0
  882. scipy/signal/_arraytools.py +264 -0
  883. scipy/signal/_czt.py +575 -0
  884. scipy/signal/_delegators.py +568 -0
  885. scipy/signal/_filter_design.py +5893 -0
  886. scipy/signal/_fir_filter_design.py +1458 -0
  887. scipy/signal/_lti_conversion.py +534 -0
  888. scipy/signal/_ltisys.py +3546 -0
  889. scipy/signal/_max_len_seq.py +139 -0
  890. scipy/signal/_max_len_seq_inner.cpython-314-darwin.so +0 -0
  891. scipy/signal/_peak_finding.py +1310 -0
  892. scipy/signal/_peak_finding_utils.cpython-314-darwin.so +0 -0
  893. scipy/signal/_polyutils.py +172 -0
  894. scipy/signal/_savitzky_golay.py +357 -0
  895. scipy/signal/_short_time_fft.py +2187 -0
  896. scipy/signal/_signal_api.py +30 -0
  897. scipy/signal/_signaltools.py +5309 -0
  898. scipy/signal/_sigtools.cpython-314-darwin.so +0 -0
  899. scipy/signal/_sosfilt.cpython-314-darwin.so +0 -0
  900. scipy/signal/_spectral_py.py +2471 -0
  901. scipy/signal/_spline.cpython-314-darwin.so +0 -0
  902. scipy/signal/_spline.pyi +34 -0
  903. scipy/signal/_spline_filters.py +848 -0
  904. scipy/signal/_support_alternative_backends.py +73 -0
  905. scipy/signal/_upfirdn.py +219 -0
  906. scipy/signal/_upfirdn_apply.cpython-314-darwin.so +0 -0
  907. scipy/signal/_waveforms.py +687 -0
  908. scipy/signal/_wavelets.py +29 -0
  909. scipy/signal/bsplines.py +21 -0
  910. scipy/signal/filter_design.py +28 -0
  911. scipy/signal/fir_filter_design.py +21 -0
  912. scipy/signal/lti_conversion.py +20 -0
  913. scipy/signal/ltisys.py +25 -0
  914. scipy/signal/signaltools.py +27 -0
  915. scipy/signal/spectral.py +21 -0
  916. scipy/signal/spline.py +18 -0
  917. scipy/signal/tests/__init__.py +0 -0
  918. scipy/signal/tests/_scipy_spectral_test_shim.py +311 -0
  919. scipy/signal/tests/mpsig.py +122 -0
  920. scipy/signal/tests/test_array_tools.py +111 -0
  921. scipy/signal/tests/test_bsplines.py +365 -0
  922. scipy/signal/tests/test_cont2discrete.py +424 -0
  923. scipy/signal/tests/test_czt.py +221 -0
  924. scipy/signal/tests/test_dltisys.py +599 -0
  925. scipy/signal/tests/test_filter_design.py +4744 -0
  926. scipy/signal/tests/test_fir_filter_design.py +851 -0
  927. scipy/signal/tests/test_ltisys.py +1225 -0
  928. scipy/signal/tests/test_max_len_seq.py +71 -0
  929. scipy/signal/tests/test_peak_finding.py +915 -0
  930. scipy/signal/tests/test_result_type.py +51 -0
  931. scipy/signal/tests/test_savitzky_golay.py +363 -0
  932. scipy/signal/tests/test_short_time_fft.py +1098 -0
  933. scipy/signal/tests/test_signaltools.py +4729 -0
  934. scipy/signal/tests/test_spectral.py +2103 -0
  935. scipy/signal/tests/test_splines.py +427 -0
  936. scipy/signal/tests/test_upfirdn.py +322 -0
  937. scipy/signal/tests/test_waveforms.py +400 -0
  938. scipy/signal/tests/test_wavelets.py +59 -0
  939. scipy/signal/tests/test_windows.py +987 -0
  940. scipy/signal/waveforms.py +20 -0
  941. scipy/signal/wavelets.py +17 -0
  942. scipy/signal/windows/__init__.py +52 -0
  943. scipy/signal/windows/_windows.py +2513 -0
  944. scipy/signal/windows/windows.py +23 -0
  945. scipy/sparse/__init__.py +350 -0
  946. scipy/sparse/_base.py +1613 -0
  947. scipy/sparse/_bsr.py +880 -0
  948. scipy/sparse/_compressed.py +1328 -0
  949. scipy/sparse/_construct.py +1454 -0
  950. scipy/sparse/_coo.py +1581 -0
  951. scipy/sparse/_csc.py +367 -0
  952. scipy/sparse/_csparsetools.cpython-314-darwin.so +0 -0
  953. scipy/sparse/_csr.py +558 -0
  954. scipy/sparse/_data.py +569 -0
  955. scipy/sparse/_dia.py +677 -0
  956. scipy/sparse/_dok.py +669 -0
  957. scipy/sparse/_extract.py +178 -0
  958. scipy/sparse/_index.py +444 -0
  959. scipy/sparse/_lil.py +632 -0
  960. scipy/sparse/_matrix.py +169 -0
  961. scipy/sparse/_matrix_io.py +167 -0
  962. scipy/sparse/_sparsetools.cpython-314-darwin.so +0 -0
  963. scipy/sparse/_spfuncs.py +76 -0
  964. scipy/sparse/_sputils.py +632 -0
  965. scipy/sparse/base.py +24 -0
  966. scipy/sparse/bsr.py +22 -0
  967. scipy/sparse/compressed.py +20 -0
  968. scipy/sparse/construct.py +38 -0
  969. scipy/sparse/coo.py +23 -0
  970. scipy/sparse/csc.py +22 -0
  971. scipy/sparse/csgraph/__init__.py +210 -0
  972. scipy/sparse/csgraph/_flow.cpython-314-darwin.so +0 -0
  973. scipy/sparse/csgraph/_laplacian.py +563 -0
  974. scipy/sparse/csgraph/_matching.cpython-314-darwin.so +0 -0
  975. scipy/sparse/csgraph/_min_spanning_tree.cpython-314-darwin.so +0 -0
  976. scipy/sparse/csgraph/_reordering.cpython-314-darwin.so +0 -0
  977. scipy/sparse/csgraph/_shortest_path.cpython-314-darwin.so +0 -0
  978. scipy/sparse/csgraph/_tools.cpython-314-darwin.so +0 -0
  979. scipy/sparse/csgraph/_traversal.cpython-314-darwin.so +0 -0
  980. scipy/sparse/csgraph/_validation.py +66 -0
  981. scipy/sparse/csgraph/tests/__init__.py +0 -0
  982. scipy/sparse/csgraph/tests/test_connected_components.py +119 -0
  983. scipy/sparse/csgraph/tests/test_conversions.py +61 -0
  984. scipy/sparse/csgraph/tests/test_flow.py +209 -0
  985. scipy/sparse/csgraph/tests/test_graph_laplacian.py +368 -0
  986. scipy/sparse/csgraph/tests/test_matching.py +307 -0
  987. scipy/sparse/csgraph/tests/test_pydata_sparse.py +197 -0
  988. scipy/sparse/csgraph/tests/test_reordering.py +70 -0
  989. scipy/sparse/csgraph/tests/test_shortest_path.py +540 -0
  990. scipy/sparse/csgraph/tests/test_spanning_tree.py +66 -0
  991. scipy/sparse/csgraph/tests/test_traversal.py +148 -0
  992. scipy/sparse/csr.py +22 -0
  993. scipy/sparse/data.py +18 -0
  994. scipy/sparse/dia.py +22 -0
  995. scipy/sparse/dok.py +22 -0
  996. scipy/sparse/extract.py +23 -0
  997. scipy/sparse/lil.py +22 -0
  998. scipy/sparse/linalg/__init__.py +148 -0
  999. scipy/sparse/linalg/_dsolve/__init__.py +71 -0
  1000. scipy/sparse/linalg/_dsolve/_add_newdocs.py +147 -0
  1001. scipy/sparse/linalg/_dsolve/_superlu.cpython-314-darwin.so +0 -0
  1002. scipy/sparse/linalg/_dsolve/linsolve.py +882 -0
  1003. scipy/sparse/linalg/_dsolve/tests/__init__.py +0 -0
  1004. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +928 -0
  1005. scipy/sparse/linalg/_eigen/__init__.py +22 -0
  1006. scipy/sparse/linalg/_eigen/_svds.py +540 -0
  1007. scipy/sparse/linalg/_eigen/_svds_doc.py +382 -0
  1008. scipy/sparse/linalg/_eigen/arpack/COPYING +45 -0
  1009. scipy/sparse/linalg/_eigen/arpack/__init__.py +20 -0
  1010. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-314-darwin.so +0 -0
  1011. scipy/sparse/linalg/_eigen/arpack/arpack.py +1706 -0
  1012. scipy/sparse/linalg/_eigen/arpack/tests/__init__.py +0 -0
  1013. scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py +717 -0
  1014. scipy/sparse/linalg/_eigen/lobpcg/__init__.py +16 -0
  1015. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +1110 -0
  1016. scipy/sparse/linalg/_eigen/lobpcg/tests/__init__.py +0 -0
  1017. scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py +725 -0
  1018. scipy/sparse/linalg/_eigen/tests/__init__.py +0 -0
  1019. scipy/sparse/linalg/_eigen/tests/test_svds.py +886 -0
  1020. scipy/sparse/linalg/_expm_multiply.py +816 -0
  1021. scipy/sparse/linalg/_interface.py +920 -0
  1022. scipy/sparse/linalg/_isolve/__init__.py +20 -0
  1023. scipy/sparse/linalg/_isolve/_gcrotmk.py +503 -0
  1024. scipy/sparse/linalg/_isolve/iterative.py +1051 -0
  1025. scipy/sparse/linalg/_isolve/lgmres.py +230 -0
  1026. scipy/sparse/linalg/_isolve/lsmr.py +486 -0
  1027. scipy/sparse/linalg/_isolve/lsqr.py +589 -0
  1028. scipy/sparse/linalg/_isolve/minres.py +372 -0
  1029. scipy/sparse/linalg/_isolve/tests/__init__.py +0 -0
  1030. scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py +183 -0
  1031. scipy/sparse/linalg/_isolve/tests/test_iterative.py +809 -0
  1032. scipy/sparse/linalg/_isolve/tests/test_lgmres.py +225 -0
  1033. scipy/sparse/linalg/_isolve/tests/test_lsmr.py +185 -0
  1034. scipy/sparse/linalg/_isolve/tests/test_lsqr.py +120 -0
  1035. scipy/sparse/linalg/_isolve/tests/test_minres.py +97 -0
  1036. scipy/sparse/linalg/_isolve/tests/test_utils.py +9 -0
  1037. scipy/sparse/linalg/_isolve/tfqmr.py +179 -0
  1038. scipy/sparse/linalg/_isolve/utils.py +121 -0
  1039. scipy/sparse/linalg/_matfuncs.py +940 -0
  1040. scipy/sparse/linalg/_norm.py +195 -0
  1041. scipy/sparse/linalg/_onenormest.py +467 -0
  1042. scipy/sparse/linalg/_propack/_cpropack.cpython-314-darwin.so +0 -0
  1043. scipy/sparse/linalg/_propack/_dpropack.cpython-314-darwin.so +0 -0
  1044. scipy/sparse/linalg/_propack/_spropack.cpython-314-darwin.so +0 -0
  1045. scipy/sparse/linalg/_propack/_zpropack.cpython-314-darwin.so +0 -0
  1046. scipy/sparse/linalg/_special_sparse_arrays.py +949 -0
  1047. scipy/sparse/linalg/_svdp.py +309 -0
  1048. scipy/sparse/linalg/dsolve.py +22 -0
  1049. scipy/sparse/linalg/eigen.py +21 -0
  1050. scipy/sparse/linalg/interface.py +20 -0
  1051. scipy/sparse/linalg/isolve.py +22 -0
  1052. scipy/sparse/linalg/matfuncs.py +18 -0
  1053. scipy/sparse/linalg/tests/__init__.py +0 -0
  1054. scipy/sparse/linalg/tests/propack_test_data.npz +0 -0
  1055. scipy/sparse/linalg/tests/test_expm_multiply.py +367 -0
  1056. scipy/sparse/linalg/tests/test_interface.py +561 -0
  1057. scipy/sparse/linalg/tests/test_matfuncs.py +592 -0
  1058. scipy/sparse/linalg/tests/test_norm.py +154 -0
  1059. scipy/sparse/linalg/tests/test_onenormest.py +252 -0
  1060. scipy/sparse/linalg/tests/test_propack.py +165 -0
  1061. scipy/sparse/linalg/tests/test_pydata_sparse.py +272 -0
  1062. scipy/sparse/linalg/tests/test_special_sparse_arrays.py +337 -0
  1063. scipy/sparse/sparsetools.py +17 -0
  1064. scipy/sparse/spfuncs.py +17 -0
  1065. scipy/sparse/sputils.py +17 -0
  1066. scipy/sparse/tests/__init__.py +0 -0
  1067. scipy/sparse/tests/data/csc_py2.npz +0 -0
  1068. scipy/sparse/tests/data/csc_py3.npz +0 -0
  1069. scipy/sparse/tests/test_arithmetic1d.py +341 -0
  1070. scipy/sparse/tests/test_array_api.py +561 -0
  1071. scipy/sparse/tests/test_base.py +5870 -0
  1072. scipy/sparse/tests/test_common1d.py +447 -0
  1073. scipy/sparse/tests/test_construct.py +872 -0
  1074. scipy/sparse/tests/test_coo.py +1119 -0
  1075. scipy/sparse/tests/test_csc.py +98 -0
  1076. scipy/sparse/tests/test_csr.py +214 -0
  1077. scipy/sparse/tests/test_dok.py +209 -0
  1078. scipy/sparse/tests/test_extract.py +51 -0
  1079. scipy/sparse/tests/test_indexing1d.py +603 -0
  1080. scipy/sparse/tests/test_matrix_io.py +109 -0
  1081. scipy/sparse/tests/test_minmax1d.py +128 -0
  1082. scipy/sparse/tests/test_sparsetools.py +344 -0
  1083. scipy/sparse/tests/test_spfuncs.py +97 -0
  1084. scipy/sparse/tests/test_sputils.py +424 -0
  1085. scipy/spatial/__init__.py +129 -0
  1086. scipy/spatial/_ckdtree.cpython-314-darwin.so +0 -0
  1087. scipy/spatial/_distance_pybind.cpython-314-darwin.so +0 -0
  1088. scipy/spatial/_distance_wrap.cpython-314-darwin.so +0 -0
  1089. scipy/spatial/_geometric_slerp.py +238 -0
  1090. scipy/spatial/_hausdorff.cpython-314-darwin.so +0 -0
  1091. scipy/spatial/_kdtree.py +920 -0
  1092. scipy/spatial/_plotutils.py +274 -0
  1093. scipy/spatial/_procrustes.py +132 -0
  1094. scipy/spatial/_qhull.cpython-314-darwin.so +0 -0
  1095. scipy/spatial/_qhull.pyi +213 -0
  1096. scipy/spatial/_spherical_voronoi.py +341 -0
  1097. scipy/spatial/_voronoi.cpython-314-darwin.so +0 -0
  1098. scipy/spatial/_voronoi.pyi +4 -0
  1099. scipy/spatial/ckdtree.py +18 -0
  1100. scipy/spatial/distance.py +3147 -0
  1101. scipy/spatial/distance.pyi +210 -0
  1102. scipy/spatial/kdtree.py +25 -0
  1103. scipy/spatial/qhull.py +25 -0
  1104. scipy/spatial/tests/__init__.py +0 -0
  1105. scipy/spatial/tests/data/cdist-X1.txt +10 -0
  1106. scipy/spatial/tests/data/cdist-X2.txt +20 -0
  1107. scipy/spatial/tests/data/degenerate_pointset.npz +0 -0
  1108. scipy/spatial/tests/data/iris.txt +150 -0
  1109. scipy/spatial/tests/data/pdist-boolean-inp.txt +20 -0
  1110. scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt +1 -0
  1111. scipy/spatial/tests/data/pdist-chebyshev-ml.txt +1 -0
  1112. scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt +1 -0
  1113. scipy/spatial/tests/data/pdist-cityblock-ml.txt +1 -0
  1114. scipy/spatial/tests/data/pdist-correlation-ml-iris.txt +1 -0
  1115. scipy/spatial/tests/data/pdist-correlation-ml.txt +1 -0
  1116. scipy/spatial/tests/data/pdist-cosine-ml-iris.txt +1 -0
  1117. scipy/spatial/tests/data/pdist-cosine-ml.txt +1 -0
  1118. scipy/spatial/tests/data/pdist-double-inp.txt +20 -0
  1119. scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt +1 -0
  1120. scipy/spatial/tests/data/pdist-euclidean-ml.txt +1 -0
  1121. scipy/spatial/tests/data/pdist-hamming-ml.txt +1 -0
  1122. scipy/spatial/tests/data/pdist-jaccard-ml.txt +1 -0
  1123. scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt +1 -0
  1124. scipy/spatial/tests/data/pdist-jensenshannon-ml.txt +1 -0
  1125. scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt +1 -0
  1126. scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt +1 -0
  1127. scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt +1 -0
  1128. scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt +1 -0
  1129. scipy/spatial/tests/data/pdist-seuclidean-ml.txt +1 -0
  1130. scipy/spatial/tests/data/pdist-spearman-ml.txt +1 -0
  1131. scipy/spatial/tests/data/random-bool-data.txt +100 -0
  1132. scipy/spatial/tests/data/random-double-data.txt +100 -0
  1133. scipy/spatial/tests/data/random-int-data.txt +100 -0
  1134. scipy/spatial/tests/data/random-uint-data.txt +100 -0
  1135. scipy/spatial/tests/data/selfdual-4d-polytope.txt +27 -0
  1136. scipy/spatial/tests/test__plotutils.py +91 -0
  1137. scipy/spatial/tests/test__procrustes.py +116 -0
  1138. scipy/spatial/tests/test_distance.py +2388 -0
  1139. scipy/spatial/tests/test_hausdorff.py +199 -0
  1140. scipy/spatial/tests/test_kdtree.py +1536 -0
  1141. scipy/spatial/tests/test_qhull.py +1313 -0
  1142. scipy/spatial/tests/test_slerp.py +417 -0
  1143. scipy/spatial/tests/test_spherical_voronoi.py +358 -0
  1144. scipy/spatial/transform/__init__.py +31 -0
  1145. scipy/spatial/transform/_rigid_transform.cpython-314-darwin.so +0 -0
  1146. scipy/spatial/transform/_rotation.cpython-314-darwin.so +0 -0
  1147. scipy/spatial/transform/_rotation_groups.py +140 -0
  1148. scipy/spatial/transform/_rotation_spline.py +460 -0
  1149. scipy/spatial/transform/rotation.py +21 -0
  1150. scipy/spatial/transform/tests/__init__.py +0 -0
  1151. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  1152. scipy/spatial/transform/tests/test_rotation.py +2569 -0
  1153. scipy/spatial/transform/tests/test_rotation_groups.py +169 -0
  1154. scipy/spatial/transform/tests/test_rotation_spline.py +183 -0
  1155. scipy/special/__init__.pxd +1 -0
  1156. scipy/special/__init__.py +841 -0
  1157. scipy/special/_add_newdocs.py +9961 -0
  1158. scipy/special/_basic.py +3576 -0
  1159. scipy/special/_comb.cpython-314-darwin.so +0 -0
  1160. scipy/special/_ellip_harm.py +214 -0
  1161. scipy/special/_ellip_harm_2.cpython-314-darwin.so +0 -0
  1162. scipy/special/_gufuncs.cpython-314-darwin.so +0 -0
  1163. scipy/special/_input_validation.py +17 -0
  1164. scipy/special/_lambertw.py +149 -0
  1165. scipy/special/_logsumexp.py +426 -0
  1166. scipy/special/_mptestutils.py +453 -0
  1167. scipy/special/_multiufuncs.py +610 -0
  1168. scipy/special/_orthogonal.py +2592 -0
  1169. scipy/special/_orthogonal.pyi +330 -0
  1170. scipy/special/_precompute/__init__.py +0 -0
  1171. scipy/special/_precompute/cosine_cdf.py +17 -0
  1172. scipy/special/_precompute/expn_asy.py +54 -0
  1173. scipy/special/_precompute/gammainc_asy.py +116 -0
  1174. scipy/special/_precompute/gammainc_data.py +124 -0
  1175. scipy/special/_precompute/hyp2f1_data.py +484 -0
  1176. scipy/special/_precompute/lambertw.py +68 -0
  1177. scipy/special/_precompute/loggamma.py +43 -0
  1178. scipy/special/_precompute/struve_convergence.py +131 -0
  1179. scipy/special/_precompute/utils.py +38 -0
  1180. scipy/special/_precompute/wright_bessel.py +342 -0
  1181. scipy/special/_precompute/wright_bessel_data.py +152 -0
  1182. scipy/special/_precompute/wrightomega.py +41 -0
  1183. scipy/special/_precompute/zetac.py +27 -0
  1184. scipy/special/_sf_error.py +15 -0
  1185. scipy/special/_specfun.cpython-314-darwin.so +0 -0
  1186. scipy/special/_special_ufuncs.cpython-314-darwin.so +0 -0
  1187. scipy/special/_spfun_stats.py +106 -0
  1188. scipy/special/_spherical_bessel.py +397 -0
  1189. scipy/special/_support_alternative_backends.py +295 -0
  1190. scipy/special/_test_internal.cpython-314-darwin.so +0 -0
  1191. scipy/special/_test_internal.pyi +9 -0
  1192. scipy/special/_testutils.py +321 -0
  1193. scipy/special/_ufuncs.cpython-314-darwin.so +0 -0
  1194. scipy/special/_ufuncs.pyi +522 -0
  1195. scipy/special/_ufuncs.pyx +13173 -0
  1196. scipy/special/_ufuncs_cxx.cpython-314-darwin.so +0 -0
  1197. scipy/special/_ufuncs_cxx.pxd +142 -0
  1198. scipy/special/_ufuncs_cxx.pyx +427 -0
  1199. scipy/special/_ufuncs_cxx_defs.h +147 -0
  1200. scipy/special/_ufuncs_defs.h +57 -0
  1201. scipy/special/add_newdocs.py +15 -0
  1202. scipy/special/basic.py +87 -0
  1203. scipy/special/cython_special.cpython-314-darwin.so +0 -0
  1204. scipy/special/cython_special.pxd +259 -0
  1205. scipy/special/cython_special.pyi +3 -0
  1206. scipy/special/orthogonal.py +45 -0
  1207. scipy/special/sf_error.py +20 -0
  1208. scipy/special/specfun.py +24 -0
  1209. scipy/special/spfun_stats.py +17 -0
  1210. scipy/special/tests/__init__.py +0 -0
  1211. scipy/special/tests/_cython_examples/extending.pyx +12 -0
  1212. scipy/special/tests/_cython_examples/meson.build +34 -0
  1213. scipy/special/tests/data/__init__.py +0 -0
  1214. scipy/special/tests/data/boost.npz +0 -0
  1215. scipy/special/tests/data/gsl.npz +0 -0
  1216. scipy/special/tests/data/local.npz +0 -0
  1217. scipy/special/tests/test_basic.py +4815 -0
  1218. scipy/special/tests/test_bdtr.py +112 -0
  1219. scipy/special/tests/test_boost_ufuncs.py +64 -0
  1220. scipy/special/tests/test_boxcox.py +125 -0
  1221. scipy/special/tests/test_cdflib.py +712 -0
  1222. scipy/special/tests/test_cdft_asymptotic.py +49 -0
  1223. scipy/special/tests/test_cephes_intp_cast.py +29 -0
  1224. scipy/special/tests/test_cosine_distr.py +83 -0
  1225. scipy/special/tests/test_cython_special.py +363 -0
  1226. scipy/special/tests/test_data.py +719 -0
  1227. scipy/special/tests/test_dd.py +42 -0
  1228. scipy/special/tests/test_digamma.py +45 -0
  1229. scipy/special/tests/test_ellip_harm.py +278 -0
  1230. scipy/special/tests/test_erfinv.py +89 -0
  1231. scipy/special/tests/test_exponential_integrals.py +118 -0
  1232. scipy/special/tests/test_extending.py +28 -0
  1233. scipy/special/tests/test_faddeeva.py +85 -0
  1234. scipy/special/tests/test_gamma.py +12 -0
  1235. scipy/special/tests/test_gammainc.py +152 -0
  1236. scipy/special/tests/test_hyp2f1.py +2566 -0
  1237. scipy/special/tests/test_hypergeometric.py +234 -0
  1238. scipy/special/tests/test_iv_ratio.py +249 -0
  1239. scipy/special/tests/test_kolmogorov.py +491 -0
  1240. scipy/special/tests/test_lambertw.py +109 -0
  1241. scipy/special/tests/test_legendre.py +1518 -0
  1242. scipy/special/tests/test_log1mexp.py +85 -0
  1243. scipy/special/tests/test_loggamma.py +70 -0
  1244. scipy/special/tests/test_logit.py +162 -0
  1245. scipy/special/tests/test_logsumexp.py +469 -0
  1246. scipy/special/tests/test_mpmath.py +2293 -0
  1247. scipy/special/tests/test_nan_inputs.py +65 -0
  1248. scipy/special/tests/test_ndtr.py +77 -0
  1249. scipy/special/tests/test_ndtri_exp.py +94 -0
  1250. scipy/special/tests/test_orthogonal.py +821 -0
  1251. scipy/special/tests/test_orthogonal_eval.py +275 -0
  1252. scipy/special/tests/test_owens_t.py +53 -0
  1253. scipy/special/tests/test_pcf.py +24 -0
  1254. scipy/special/tests/test_pdtr.py +48 -0
  1255. scipy/special/tests/test_powm1.py +65 -0
  1256. scipy/special/tests/test_precompute_expn_asy.py +24 -0
  1257. scipy/special/tests/test_precompute_gammainc.py +108 -0
  1258. scipy/special/tests/test_precompute_utils.py +36 -0
  1259. scipy/special/tests/test_round.py +18 -0
  1260. scipy/special/tests/test_sf_error.py +146 -0
  1261. scipy/special/tests/test_sici.py +36 -0
  1262. scipy/special/tests/test_specfun.py +48 -0
  1263. scipy/special/tests/test_spence.py +32 -0
  1264. scipy/special/tests/test_spfun_stats.py +61 -0
  1265. scipy/special/tests/test_sph_harm.py +85 -0
  1266. scipy/special/tests/test_spherical_bessel.py +400 -0
  1267. scipy/special/tests/test_support_alternative_backends.py +248 -0
  1268. scipy/special/tests/test_trig.py +72 -0
  1269. scipy/special/tests/test_ufunc_signatures.py +46 -0
  1270. scipy/special/tests/test_wright_bessel.py +205 -0
  1271. scipy/special/tests/test_wrightomega.py +117 -0
  1272. scipy/special/tests/test_zeta.py +301 -0
  1273. scipy/stats/__init__.py +670 -0
  1274. scipy/stats/_ansari_swilk_statistics.cpython-314-darwin.so +0 -0
  1275. scipy/stats/_axis_nan_policy.py +692 -0
  1276. scipy/stats/_biasedurn.cpython-314-darwin.so +0 -0
  1277. scipy/stats/_biasedurn.pxd +27 -0
  1278. scipy/stats/_binned_statistic.py +795 -0
  1279. scipy/stats/_binomtest.py +375 -0
  1280. scipy/stats/_bws_test.py +177 -0
  1281. scipy/stats/_censored_data.py +459 -0
  1282. scipy/stats/_common.py +5 -0
  1283. scipy/stats/_constants.py +42 -0
  1284. scipy/stats/_continued_fraction.py +387 -0
  1285. scipy/stats/_continuous_distns.py +12486 -0
  1286. scipy/stats/_correlation.py +210 -0
  1287. scipy/stats/_covariance.py +636 -0
  1288. scipy/stats/_crosstab.py +204 -0
  1289. scipy/stats/_discrete_distns.py +2098 -0
  1290. scipy/stats/_distn_infrastructure.py +4201 -0
  1291. scipy/stats/_distr_params.py +299 -0
  1292. scipy/stats/_distribution_infrastructure.py +5750 -0
  1293. scipy/stats/_entropy.py +428 -0
  1294. scipy/stats/_finite_differences.py +145 -0
  1295. scipy/stats/_fit.py +1351 -0
  1296. scipy/stats/_hypotests.py +2060 -0
  1297. scipy/stats/_kde.py +732 -0
  1298. scipy/stats/_ksstats.py +600 -0
  1299. scipy/stats/_levy_stable/__init__.py +1231 -0
  1300. scipy/stats/_levy_stable/levyst.cpython-314-darwin.so +0 -0
  1301. scipy/stats/_mannwhitneyu.py +492 -0
  1302. scipy/stats/_mgc.py +550 -0
  1303. scipy/stats/_morestats.py +4626 -0
  1304. scipy/stats/_mstats_basic.py +3658 -0
  1305. scipy/stats/_mstats_extras.py +521 -0
  1306. scipy/stats/_multicomp.py +449 -0
  1307. scipy/stats/_multivariate.py +7281 -0
  1308. scipy/stats/_new_distributions.py +452 -0
  1309. scipy/stats/_odds_ratio.py +466 -0
  1310. scipy/stats/_page_trend_test.py +486 -0
  1311. scipy/stats/_probability_distribution.py +1964 -0
  1312. scipy/stats/_qmc.py +2956 -0
  1313. scipy/stats/_qmc_cy.cpython-314-darwin.so +0 -0
  1314. scipy/stats/_qmc_cy.pyi +54 -0
  1315. scipy/stats/_qmvnt.py +454 -0
  1316. scipy/stats/_qmvnt_cy.cpython-314-darwin.so +0 -0
  1317. scipy/stats/_quantile.py +335 -0
  1318. scipy/stats/_rcont/__init__.py +4 -0
  1319. scipy/stats/_rcont/rcont.cpython-314-darwin.so +0 -0
  1320. scipy/stats/_relative_risk.py +263 -0
  1321. scipy/stats/_resampling.py +2352 -0
  1322. scipy/stats/_result_classes.py +40 -0
  1323. scipy/stats/_sampling.py +1314 -0
  1324. scipy/stats/_sensitivity_analysis.py +713 -0
  1325. scipy/stats/_sobol.cpython-314-darwin.so +0 -0
  1326. scipy/stats/_sobol.pyi +54 -0
  1327. scipy/stats/_sobol_direction_numbers.npz +0 -0
  1328. scipy/stats/_stats.cpython-314-darwin.so +0 -0
  1329. scipy/stats/_stats.pxd +10 -0
  1330. scipy/stats/_stats_mstats_common.py +322 -0
  1331. scipy/stats/_stats_py.py +11089 -0
  1332. scipy/stats/_stats_pythran.cpython-314-darwin.so +0 -0
  1333. scipy/stats/_survival.py +683 -0
  1334. scipy/stats/_tukeylambda_stats.py +199 -0
  1335. scipy/stats/_unuran/__init__.py +0 -0
  1336. scipy/stats/_unuran/unuran_wrapper.cpython-314-darwin.so +0 -0
  1337. scipy/stats/_unuran/unuran_wrapper.pyi +179 -0
  1338. scipy/stats/_variation.py +126 -0
  1339. scipy/stats/_warnings_errors.py +38 -0
  1340. scipy/stats/_wilcoxon.py +265 -0
  1341. scipy/stats/biasedurn.py +16 -0
  1342. scipy/stats/contingency.py +521 -0
  1343. scipy/stats/distributions.py +24 -0
  1344. scipy/stats/kde.py +18 -0
  1345. scipy/stats/morestats.py +27 -0
  1346. scipy/stats/mstats.py +140 -0
  1347. scipy/stats/mstats_basic.py +42 -0
  1348. scipy/stats/mstats_extras.py +25 -0
  1349. scipy/stats/mvn.py +17 -0
  1350. scipy/stats/qmc.py +236 -0
  1351. scipy/stats/sampling.py +73 -0
  1352. scipy/stats/stats.py +41 -0
  1353. scipy/stats/tests/__init__.py +0 -0
  1354. scipy/stats/tests/common_tests.py +356 -0
  1355. scipy/stats/tests/data/_mvt.py +171 -0
  1356. scipy/stats/tests/data/fisher_exact_results_from_r.py +607 -0
  1357. scipy/stats/tests/data/jf_skew_t_gamlss_pdf_data.npy +0 -0
  1358. scipy/stats/tests/data/levy_stable/stable-Z1-cdf-sample-data.npy +0 -0
  1359. scipy/stats/tests/data/levy_stable/stable-Z1-pdf-sample-data.npy +0 -0
  1360. scipy/stats/tests/data/levy_stable/stable-loc-scale-sample-data.npy +0 -0
  1361. scipy/stats/tests/data/nist_anova/AtmWtAg.dat +108 -0
  1362. scipy/stats/tests/data/nist_anova/SiRstv.dat +85 -0
  1363. scipy/stats/tests/data/nist_anova/SmLs01.dat +249 -0
  1364. scipy/stats/tests/data/nist_anova/SmLs02.dat +1869 -0
  1365. scipy/stats/tests/data/nist_anova/SmLs03.dat +18069 -0
  1366. scipy/stats/tests/data/nist_anova/SmLs04.dat +249 -0
  1367. scipy/stats/tests/data/nist_anova/SmLs05.dat +1869 -0
  1368. scipy/stats/tests/data/nist_anova/SmLs06.dat +18069 -0
  1369. scipy/stats/tests/data/nist_anova/SmLs07.dat +249 -0
  1370. scipy/stats/tests/data/nist_anova/SmLs08.dat +1869 -0
  1371. scipy/stats/tests/data/nist_anova/SmLs09.dat +18069 -0
  1372. scipy/stats/tests/data/nist_linregress/Norris.dat +97 -0
  1373. scipy/stats/tests/data/rel_breitwigner_pdf_sample_data_ROOT.npy +0 -0
  1374. scipy/stats/tests/data/studentized_range_mpmath_ref.json +1499 -0
  1375. scipy/stats/tests/test_axis_nan_policy.py +1388 -0
  1376. scipy/stats/tests/test_binned_statistic.py +568 -0
  1377. scipy/stats/tests/test_censored_data.py +152 -0
  1378. scipy/stats/tests/test_contingency.py +294 -0
  1379. scipy/stats/tests/test_continued_fraction.py +173 -0
  1380. scipy/stats/tests/test_continuous.py +2198 -0
  1381. scipy/stats/tests/test_continuous_basic.py +1053 -0
  1382. scipy/stats/tests/test_continuous_fit_censored.py +683 -0
  1383. scipy/stats/tests/test_correlation.py +80 -0
  1384. scipy/stats/tests/test_crosstab.py +115 -0
  1385. scipy/stats/tests/test_discrete_basic.py +580 -0
  1386. scipy/stats/tests/test_discrete_distns.py +700 -0
  1387. scipy/stats/tests/test_distributions.py +10413 -0
  1388. scipy/stats/tests/test_entropy.py +322 -0
  1389. scipy/stats/tests/test_fast_gen_inversion.py +435 -0
  1390. scipy/stats/tests/test_fit.py +1090 -0
  1391. scipy/stats/tests/test_hypotests.py +1991 -0
  1392. scipy/stats/tests/test_kdeoth.py +676 -0
  1393. scipy/stats/tests/test_marray.py +289 -0
  1394. scipy/stats/tests/test_mgc.py +217 -0
  1395. scipy/stats/tests/test_morestats.py +3259 -0
  1396. scipy/stats/tests/test_mstats_basic.py +2071 -0
  1397. scipy/stats/tests/test_mstats_extras.py +172 -0
  1398. scipy/stats/tests/test_multicomp.py +405 -0
  1399. scipy/stats/tests/test_multivariate.py +4381 -0
  1400. scipy/stats/tests/test_odds_ratio.py +148 -0
  1401. scipy/stats/tests/test_qmc.py +1492 -0
  1402. scipy/stats/tests/test_quantile.py +199 -0
  1403. scipy/stats/tests/test_rank.py +345 -0
  1404. scipy/stats/tests/test_relative_risk.py +95 -0
  1405. scipy/stats/tests/test_resampling.py +2000 -0
  1406. scipy/stats/tests/test_sampling.py +1450 -0
  1407. scipy/stats/tests/test_sensitivity_analysis.py +310 -0
  1408. scipy/stats/tests/test_stats.py +9707 -0
  1409. scipy/stats/tests/test_survival.py +466 -0
  1410. scipy/stats/tests/test_tukeylambda_stats.py +85 -0
  1411. scipy/stats/tests/test_variation.py +216 -0
  1412. scipy/version.py +12 -0
  1413. scipy-1.16.1.dist-info/LICENSE.txt +934 -0
  1414. scipy-1.16.1.dist-info/METADATA +1083 -0
  1415. scipy-1.16.1.dist-info/RECORD +1416 -0
  1416. scipy-1.16.1.dist-info/WHEEL +6 -0
@@ -0,0 +1,2187 @@
1
+ """Implementation of an FFT-based Short-time Fourier Transform. """
2
+
3
+ # Implementation Notes for this file (as of 2023-07)
4
+ # --------------------------------------------------
5
+ # * MyPy version 1.1.1 does not seem to support decorated property methods
6
+ # properly. Hence, applying ``@property`` to methods decorated with `@cache``
7
+ # (as tried with the ``lower_border_end`` method) causes a mypy error when
8
+ # accessing it as an index (e.g., ``SFT.lower_border_end[0]``).
9
+ # * Since the method `stft` and `istft` have identical names as the legacy
10
+ # functions in the signal module, referencing them as HTML link in the
11
+ # docstrings has to be done by an explicit `~ShortTimeFFT.stft` instead of an
12
+ # ambiguous `stft` (The ``~`` hides the class / module name).
13
+ # * The HTML documentation currently renders each method/property on a separate
14
+ # page without reference to the parent class. Thus, a link to `ShortTimeFFT`
15
+ # was added to the "See Also" section of each method/property. These links
16
+ # can be removed, when SciPy updates ``pydata-sphinx-theme`` to >= 0.13.3
17
+ # (currently 0.9). Consult Issue 18512 and PR 16660 for further details.
18
+
19
+
20
+ # Provides typing union operator ``|`` in Python 3.9:
21
+ # Linter does not allow to import ``Generator`` from ``typing`` module:
22
+ from collections.abc import Generator, Callable
23
+ from functools import cache, lru_cache, partial
24
+ from typing import get_args, Literal
25
+
26
+ import numpy as np
27
+
28
+ import scipy.fft as fft_lib
29
+ from scipy.signal._signaltools import detrend
30
+ from scipy.signal.windows import get_window
31
+
32
+ __all__ = ['closest_STFT_dual_window', 'ShortTimeFFT']
33
+
34
+
35
+ #: Allowed values for parameter `padding` of method `ShortTimeFFT.stft()`:
36
+ PAD_TYPE = Literal['zeros', 'edge', 'even', 'odd']
37
+
38
+ #: Allowed values for property `ShortTimeFFT.fft_mode`:
39
+ FFT_MODE_TYPE = Literal['twosided', 'centered', 'onesided', 'onesided2X']
40
+
41
+
42
+ def _calc_dual_canonical_window(win: np.ndarray, hop: int) -> np.ndarray:
43
+ """Calculate canonical dual window for 1d window `win` and a time step
44
+ of `hop` samples.
45
+
46
+ A ``ValueError`` is raised if the inversion fails.
47
+
48
+ This is a separate function not a method, since it is also used in the
49
+ class method ``ShortTimeFFT.from_dual()``.
50
+ """
51
+ if hop > len(win):
52
+ raise ValueError(f"{hop=} is larger than window length of {len(win)}" +
53
+ " => STFT not invertible!")
54
+ if issubclass(win.dtype.type, np.integer):
55
+ raise ValueError("Parameter 'win' cannot be of integer type, but " +
56
+ f"{win.dtype=} => STFT not invertible!")
57
+ # The calculation of `relative_resolution` does not work for ints.
58
+ # Furthermore, `win / DD` casts the integers away, thus an implicit
59
+ # cast is avoided, which can always cause confusion when using 32-Bit
60
+ # floats.
61
+
62
+ w2 = win.real**2 + win.imag**2 # win*win.conj() does not ensure w2 is real
63
+ DD = w2.copy()
64
+ for k_ in range(hop, len(win), hop):
65
+ DD[k_:] += w2[:-k_]
66
+ DD[:-k_] += w2[k_:]
67
+
68
+ # check DD > 0:
69
+ relative_resolution = np.finfo(win.dtype).resolution * max(DD)
70
+ if not np.all(DD >= relative_resolution):
71
+ raise ValueError("Short-time Fourier Transform not invertible!")
72
+
73
+ return win / DD
74
+
75
+
76
+ def closest_STFT_dual_window(win: np.ndarray, hop: int,
77
+ desired_dual: np.ndarray | None = None, *,
78
+ scaled: bool = True) \
79
+ -> tuple[np.ndarray, float | complex]:
80
+ r"""Calculate the STFT dual window of a given window closest to a desired dual
81
+ window.
82
+
83
+ For a given short-time Fourier transform window `win` incremented by `hop`
84
+ samples, the dual window is calculated, which minimizes
85
+ ``abs(dual_win - desired_dual)**2`` when `scaled` is ``False``. For `scaled`
86
+ set to ``True``, ``abs(alpha*dual_win - desired_dual)**2`` is minimized with
87
+ `alpha` being the optimal scaling factor.
88
+ A ``ValueError`` is raised if no valid dual window can be determined.
89
+
90
+
91
+ Parameters
92
+ ----------
93
+ win : np.ndarray
94
+ The window must be a real- or complex-valued 1d array.
95
+ hop : int
96
+ The increment in samples by which the window is shifted in each step.
97
+ desired_dual: np.ndarray | None
98
+ The desired dual window must be a 1d array of the same length as `win`.
99
+ If set to ``None`` (default), then `desired_dual` is assumed to be the
100
+ rectangular window, i.e., ``np.ones_like(win)``.
101
+ scaled : bool
102
+ If set (default), the closest scaled version instead of closest dual window
103
+ is calculated.
104
+
105
+ Returns
106
+ -------
107
+ dual_win : np.ndarray
108
+ A dual window of ``alpha*win`` (with hop interval `hop`), which is closest
109
+ to `desired_dual`. Note that the dual window of `win` is `dual_win/alpha`
110
+ and that the dual window of `dual_win` is `alpha*win`.
111
+ `dual_win` has the same shape as `win` and `desired_win`.
112
+ alpha : float | complex
113
+ Scale factor for `win`. It is always one if `scaled` is set to ``False``.
114
+
115
+ Notes
116
+ -----
117
+ For a given window and `hop` interval, all possible dual windows are expressed
118
+ by the `hop` linear conditions of Eq. :math:numref:`eq_STFT_AllDualWinsCond` in
119
+ the :ref:`tutorial_stft` section of the :ref:`user_guide`. Hence, decreasing
120
+ `hop`, increases the number of degrees of freedom of the set of all possible
121
+ dual windows, improving the ability to better approximate a `desired_dual`.
122
+
123
+ This function can also be used to determine windows which fulfill the
124
+ so-called "Constant OverLap Add" (COLA) condition [1]_. It states that summing
125
+ all touching window values at any given sample position results in the same
126
+ constant :math:`\alpha`. Eq. :math:numref:`eq_STFT_AllDualWinsCond` shows that
127
+ this is equal to having a rectangular dual window, i.e., the dual being
128
+ ``alpha*np.ones(m)``.
129
+
130
+ Some examples of windows that satisfy COLA (taken from [2]_):
131
+
132
+ - Rectangular window at overlap of 0, 1/2, 2/3, 3/4, ...
133
+ - Bartlett window at overlap of 1/2, 3/4, 5/6, ...
134
+ - Hann window at 1/2, 2/3, 3/4, ...
135
+ - Any Blackman family window at 2/3 overlap
136
+ - Any window with ``hop=1``
137
+
138
+ References
139
+ ----------
140
+ .. [1] Julius O. Smith III, "Spectral Audio Signal Processing",
141
+ online book, 2011, https://www.dsprelated.com/freebooks/sasp/
142
+ .. [2] G. Heinzel, A. Ruediger and R. Schilling, "Spectrum and spectral density
143
+ estimation by the Discrete Fourier transform (DFT), including a
144
+ comprehensive list of window functions and some new at-top windows",
145
+ 2002, http://hdl.handle.net/11858/00-001M-0000-0013-557A-5
146
+
147
+ Examples
148
+ --------
149
+ Let's show that a Bartlett window with 75% overlap fulfills the COLA condition:
150
+
151
+ >>> import matplotlib.pyplot as plt
152
+ >>> import numpy as np
153
+ >>> from scipy.signal import closest_STFT_dual_window, windows
154
+ ...
155
+ >>> m = 24
156
+ >>> win, w_rect = windows.bartlett(m, sym=False), np.ones(m)
157
+ >>> d_win, alpha = closest_STFT_dual_window(win, m//4, w_rect, scaled=True)
158
+ >>> print(f"COLA: {np.allclose(d_win, w_rect*alpha)}, {alpha = :g}")
159
+ COLA: True, alpha = 0.5
160
+
161
+ We can also determine for which hop intervals the COLA condition is fulfilled:
162
+
163
+ >>> hops, deviations, alphas = np.arange(1, 16, dtype=int), [], []
164
+ >>> for h_ in hops:
165
+ ... w_cola, alpha = closest_STFT_dual_window(w_rect, h_, win, scaled=True)
166
+ ... deviations.append(np.linalg.norm(w_cola - win*alpha))
167
+ ... alphas.append(alpha)
168
+ ...
169
+ >>> fg0, (ax0, ax1) = plt.subplots(2, 1, sharex='all', tight_layout=True)
170
+ >>> ax0.set_title(f"COLA Window closest to a {m}-Sample Bartlett Window")
171
+ >>> ax0.set(ylabel=r"$||w_\text{cola}-\alpha w||$", xlim=(0, hops[-1]-.5))
172
+ >>> ax1.set(xlabel="Hop Interval", ylabel=r"Scaling factor $\alpha$",
173
+ ... ylim=(0, 1.25))
174
+ >>> ax0.plot(hops, deviations, 'C0.-')
175
+ >>> ax1.plot(hops, alphas, 'C1.-')
176
+ >>> for ax_ in (ax0, ax1):
177
+ ... ax_.grid()
178
+ >>> plt.show()
179
+
180
+ The lower plot shows the calculated scaling factor :math:`\alpha` for different
181
+ `hops` whereas the upper displays the :math:`L^2`-norm of the difference
182
+ between the scaled Bartlett window and the calculated window. Since for `hops`
183
+ 1 to 4 as well as for 6 and 12 the :math:`L^2`-norm of the difference is
184
+ practically zero, the COLA condition is fulfilled for those.
185
+
186
+ See Also
187
+ --------
188
+ ShortTimeFFT: Short-time Fourier transform which is able to utilize a dual
189
+ window for calculating the inverse.
190
+ ShortTimeFFT.from_win_equals_dual: Create instance where the window and its
191
+ dual are equal.
192
+
193
+ """
194
+ if desired_dual is None: # default is rectangular window
195
+ desired_dual = np.ones_like(win)
196
+ if not (win.ndim == 1 and win.shape == desired_dual.shape):
197
+ raise ValueError("Parameters `win` and `desired_dual` are not 1d arrays of " +
198
+ f"equal length ({win.shape=}, {desired_dual.shape=})!")
199
+ if not all(np.isfinite(win)):
200
+ raise ValueError("Parameter win must have finite entries!")
201
+ if not all(np.isfinite(desired_dual)):
202
+ raise ValueError("Parameter desired_dual must have finite entries!")
203
+ if not (1 <= hop <= len(win) and isinstance(hop, int | np.integer)):
204
+ raise ValueError(f"Parameter {hop=} is not an integer between 1 and " +
205
+ f"{len(win)=}!")
206
+
207
+ w_d = _calc_dual_canonical_window(win, hop)
208
+ wdd = win.conjugate() * desired_dual
209
+ q_d = wdd.copy()
210
+ for k_ in range(hop, len(win), hop):
211
+ q_d[k_:] += wdd[:-k_]
212
+ q_d[:-k_] += wdd[k_:]
213
+ q_d = w_d * q_d
214
+
215
+ if not scaled:
216
+ return w_d + desired_dual - q_d, 1.
217
+
218
+ numerator = q_d.conjugate().T @ w_d
219
+ denominator = q_d.T.real @ q_d.real + q_d.T.imag @ q_d.imag # always >= 0
220
+ if not (abs(numerator) > 0 and denominator > np.finfo(w_d.dtype).resolution):
221
+ raise ValueError(
222
+ "Unable to calculate scaled closest dual window due to numerically " +
223
+ "unstable scaling factor! Try setting parameter `scaled` to False.")
224
+ alpha = numerator / denominator
225
+ return w_d + alpha * (desired_dual - q_d), alpha
226
+
227
+
228
+ # noinspection PyShadowingNames
229
+ class ShortTimeFFT:
230
+ r"""Provide a parametrized discrete Short-time Fourier transform (stft)
231
+ and its inverse (istft).
232
+
233
+ .. currentmodule:: scipy.signal.ShortTimeFFT
234
+
235
+ The `~ShortTimeFFT.stft` calculates sequential FFTs by sliding a
236
+ window (`win`) over an input signal by `hop` increments. It can be used to
237
+ quantify the change of the spectrum over time.
238
+
239
+ The `~ShortTimeFFT.stft` is represented by a complex-valued matrix S[q,p]
240
+ where the p-th column represents an FFT with the window centered at the
241
+ time t[p] = p * `delta_t` = p * `hop` * `T` where `T` is the sampling
242
+ interval of the input signal. The q-th row represents the values at the
243
+ frequency f[q] = q * `delta_f` with `delta_f` = 1 / (`mfft` * `T`) being
244
+ the bin width of the FFT.
245
+
246
+ The inverse STFT `~ShortTimeFFT.istft` is calculated by reversing the steps
247
+ of the STFT: Take the IFFT of the p-th slice of S[q,p] and multiply the
248
+ result with the so-called dual window (see `dual_win`). Shift the result by
249
+ p * `delta_t` and add the result to previous shifted results to reconstruct
250
+ the signal. If only the dual window is known and the STFT is invertible,
251
+ `from_dual` can be used to instantiate this class.
252
+
253
+ By default, the so-called canonical dual window is used. It is the window with
254
+ minimal energy among all possible dual windows. `from_win_equals_dual` and
255
+ `~scipy.signal.closest_STFT_dual_window` provide means for utilizing alterantive
256
+ dual windows. Note that `win` is also always a dual window of `dual_win`.
257
+
258
+ Due to the convention of time t = 0 being at the first sample of the input
259
+ signal, the STFT values typically have negative time slots. Hence,
260
+ negative indexes like `p_min` or `k_min` do not indicate counting
261
+ backwards from an array's end like in standard Python indexing but being
262
+ left of t = 0.
263
+
264
+ More detailed information can be found in the :ref:`tutorial_stft`
265
+ section of the :ref:`user_guide`.
266
+
267
+ Note that all parameters of the initializer, except `scale_to` (which uses
268
+ `scaling`) have identical named attributes.
269
+
270
+ Parameters
271
+ ----------
272
+ win : np.ndarray
273
+ The window must be a real- or complex-valued 1d array.
274
+ hop : int
275
+ The increment in samples, by which the window is shifted in each step.
276
+ fs : float
277
+ Sampling frequency of input signal and window. Its relation to the
278
+ sampling interval `T` is ``T = 1 / fs``.
279
+ fft_mode : 'twosided', 'centered', 'onesided', 'onesided2X'
280
+ Mode of FFT to be used (default 'onesided').
281
+ See property `fft_mode` for details.
282
+ mfft: int | None
283
+ Length of the FFT used, if a zero padded FFT is desired.
284
+ If ``None`` (default), the length of the window `win` is used.
285
+ dual_win : np.ndarray | None
286
+ The dual window of `win`. If set to ``None``, it is calculated if
287
+ needed.
288
+ scale_to : 'magnitude', 'psd' | None
289
+ If not ``None`` (default) the window function is scaled, so each STFT
290
+ column represents either a 'magnitude' or a power spectral density
291
+ ('psd') spectrum. This parameter sets the property `scaling` to the
292
+ same value. See method `scale_to` for details.
293
+ phase_shift : int | None
294
+ If set, add a linear phase `phase_shift` / `mfft` * `f` to each
295
+ frequency `f`. The default value of 0 ensures that there is no phase shift
296
+ on the zeroth slice (in which t=0 is centered). See property
297
+ `phase_shift` for more details.
298
+
299
+ Notes
300
+ -----
301
+ A typical STFT application is the creation of various types of time-frequency
302
+ plots, often subsumed under the term "spectrogram". Note that this term is also
303
+ used to explecitly refer to the absolute square of a STFT [11]_, as done in
304
+ :meth:`spectrogram`.
305
+
306
+ The STFT can also be used for filtering and filter banks as discussed in [12]_.
307
+
308
+
309
+ References
310
+ ----------
311
+ .. [11] Karlheinz Gröchenig: "Foundations of Time-Frequency Analysis",
312
+ Birkhäuser Boston 2001, `10.1007/978-1-4612-0003-1`
313
+ .. [12] Julius O. Smith III, "Spectral Audio Signal Processing", online book, 2011,
314
+ https://www.dsprelated.com/freebooks/sasp/
315
+
316
+
317
+ Examples
318
+ --------
319
+ The following example shows the magnitude of the STFT of a sine with
320
+ varying frequency :math:`f_i(t)` (marked by a red dashed line in the plot):
321
+
322
+ >>> import numpy as np
323
+ >>> import matplotlib.pyplot as plt
324
+ >>> from scipy.signal import ShortTimeFFT
325
+ >>> from scipy.signal.windows import gaussian
326
+ ...
327
+ >>> T_x, N = 1 / 20, 1000 # 20 Hz sampling rate for 50 s signal
328
+ >>> t_x = np.arange(N) * T_x # time indexes for signal
329
+ >>> f_i = 1 * np.arctan((t_x - t_x[N // 2]) / 2) + 5 # varying frequency
330
+ >>> x = np.sin(2*np.pi*np.cumsum(f_i)*T_x) # the signal
331
+
332
+ The utilized Gaussian window is 50 samples or 2.5 s long. The parameter
333
+ ``mfft=200`` in `ShortTimeFFT` causes the spectrum to be oversampled
334
+ by a factor of 4:
335
+
336
+ >>> g_std = 8 # standard deviation for Gaussian window in samples
337
+ >>> w = gaussian(50, std=g_std, sym=True) # symmetric Gaussian window
338
+ >>> SFT = ShortTimeFFT(w, hop=10, fs=1/T_x, mfft=200, scale_to='magnitude')
339
+ >>> Sx = SFT.stft(x) # perform the STFT
340
+
341
+ In the plot, the time extent of the signal `x` is marked by vertical dashed
342
+ lines. Note that the SFT produces values outside the time range of `x`. The
343
+ shaded areas on the left and the right indicate border effects caused
344
+ by the window slices in that area not fully being inside time range of
345
+ `x`:
346
+
347
+ >>> fig1, ax1 = plt.subplots(figsize=(6., 4.)) # enlarge plot a bit
348
+ >>> t_lo, t_hi = SFT.extent(N)[:2] # time range of plot
349
+ >>> ax1.set_title(rf"STFT ({SFT.m_num*SFT.T:g}$\,s$ Gaussian window, " +
350
+ ... rf"$\sigma_t={g_std*SFT.T}\,$s)")
351
+ >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " +
352
+ ... rf"$\Delta t = {SFT.delta_t:g}\,$s)",
353
+ ... ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " +
354
+ ... rf"$\Delta f = {SFT.delta_f:g}\,$Hz)",
355
+ ... xlim=(t_lo, t_hi))
356
+ ...
357
+ >>> im1 = ax1.imshow(abs(Sx), origin='lower', aspect='auto',
358
+ ... extent=SFT.extent(N), cmap='viridis')
359
+ >>> ax1.plot(t_x, f_i, 'r--', alpha=.5, label='$f_i(t)$')
360
+ >>> fig1.colorbar(im1, label="Magnitude $|S_x(t, f)|$")
361
+ ...
362
+ >>> # Shade areas where window slices stick out to the side:
363
+ >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T),
364
+ ... (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]:
365
+ ... ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.2)
366
+ >>> for t_ in [0, N * SFT.T]: # mark signal borders with vertical line:
367
+ ... ax1.axvline(t_, color='y', linestyle='--', alpha=0.5)
368
+ >>> ax1.legend()
369
+ >>> fig1.tight_layout()
370
+ >>> plt.show()
371
+
372
+ Reconstructing the signal with the `~ShortTimeFFT.istft` is
373
+ straightforward, but note that the length of `x1` should be specified,
374
+ since the STFT length increases in `hop` steps:
375
+
376
+ >>> SFT.invertible # check if invertible
377
+ True
378
+ >>> x1 = SFT.istft(Sx, k1=N)
379
+ >>> np.allclose(x, x1)
380
+ True
381
+
382
+ It is possible to calculate the STFT of signal parts:
383
+
384
+ >>> N2 = SFT.nearest_k_p(N // 2)
385
+ >>> Sx0 = SFT.stft(x[:N2])
386
+ >>> Sx1 = SFT.stft(x[N2:])
387
+
388
+ When assembling sequential STFT parts together, the overlap needs to be
389
+ considered:
390
+
391
+ >>> p0_ub = SFT.upper_border_begin(N2)[1] - SFT.p_min
392
+ >>> p1_le = SFT.lower_border_end[1] - SFT.p_min
393
+ >>> Sx01 = np.hstack((Sx0[:, :p0_ub],
394
+ ... Sx0[:, p0_ub:] + Sx1[:, :p1_le],
395
+ ... Sx1[:, p1_le:]))
396
+ >>> np.allclose(Sx01, Sx) # Compare with SFT of complete signal
397
+ True
398
+
399
+ It is also possible to calculate the `itsft` for signal parts:
400
+
401
+ >>> y_p = SFT.istft(Sx, N//3, N//2)
402
+ >>> np.allclose(y_p, x[N//3:N//2])
403
+ True
404
+
405
+ """
406
+ # immutable attributes (only have getters but no setters):
407
+ _win: np.ndarray # window
408
+ _dual_win: np.ndarray | None = None # canonical dual window
409
+ _hop: int # Step of STFT in number of samples
410
+
411
+ # mutable attributes:
412
+ _fs: float # sampling frequency of input signal and window
413
+ _fft_mode: FFT_MODE_TYPE = 'onesided' # Mode of FFT to use
414
+ _mfft: int # length of FFT used - defaults to len(win)
415
+ _scaling: Literal['magnitude', 'psd', 'unitary'] | None = None # Scaling of _win
416
+ _phase_shift: int | None # amount to shift phase of FFT in samples
417
+
418
+ # attributes for caching calculated values:
419
+ _fac_mag: float | None = None
420
+ _fac_psd: float | None = None
421
+ _lower_border_end: tuple[int, int] | None = None
422
+
423
+ def __init__(self, win: np.ndarray, hop: int, fs: float, *,
424
+ fft_mode: FFT_MODE_TYPE = 'onesided',
425
+ mfft: int | None = None,
426
+ dual_win: np.ndarray | None = None,
427
+ scale_to: Literal['magnitude', 'psd'] | None = None,
428
+ phase_shift: int | None = 0):
429
+ if not (win.ndim == 1 and win.size > 0):
430
+ raise ValueError(f"Parameter win must be 1d, but {win.shape=}!")
431
+ if not all(np.isfinite(win)):
432
+ raise ValueError("Parameter win must have finite entries!")
433
+ if not (hop >= 1 and isinstance(hop, int | np.integer)):
434
+ raise ValueError(f"Parameter {hop=} is not an integer >= 1!")
435
+
436
+ self._win, self._hop, self.fs = win, hop, fs
437
+ self.win.setflags(write=False)
438
+ self.mfft = len(win) if mfft is None else mfft
439
+
440
+ if dual_win is not None:
441
+ if dual_win.shape != win.shape:
442
+ raise ValueError(f"{dual_win.shape=} must equal {win.shape=}!")
443
+ if not all(np.isfinite(dual_win)):
444
+ raise ValueError("Parameter dual_win must be a finite array!")
445
+ dual_win.setflags(write=False)
446
+ self._dual_win = dual_win # needs to be set before scaling
447
+
448
+ if scale_to is not None: # needs to be set before fft_mode
449
+ self.scale_to(scale_to)
450
+
451
+ self.fft_mode, self.phase_shift = fft_mode, phase_shift
452
+
453
+ @classmethod
454
+ def from_dual(cls, dual_win: np.ndarray, hop: int, fs: float, *,
455
+ fft_mode: FFT_MODE_TYPE = 'onesided',
456
+ mfft: int | None = None,
457
+ scale_to: Literal['magnitude', 'psd'] | None = None,
458
+ phase_shift: int | None = 0):
459
+ r"""Instantiate a `ShortTimeFFT` by only providing a dual window.
460
+
461
+ If an STFT is invertible, it is possible to calculate the window `win`
462
+ from a given dual window `dual_win`. All other parameters have the
463
+ same meaning as in the initializer of `ShortTimeFFT`.
464
+
465
+ As explained in the :ref:`tutorial_stft` section of the
466
+ :ref:`user_guide`, an invertible STFT can be interpreted as series
467
+ expansion of time-shifted and frequency modulated dual windows. E.g.,
468
+ the series coefficient S[q,p] belongs to the term, which shifted
469
+ `dual_win` by p * `delta_t` and multiplied it by
470
+ exp( 2 * j * pi * t * q * `delta_f`).
471
+
472
+
473
+ Examples
474
+ --------
475
+ The following example discusses decomposing a signal into time- and
476
+ frequency-shifted Gaussians. A Gaussian with standard deviation of
477
+ one made up of 51 samples will be used:
478
+
479
+ >>> import numpy as np
480
+ >>> import matplotlib.pyplot as plt
481
+ >>> from scipy.signal import ShortTimeFFT
482
+ >>> from scipy.signal.windows import gaussian
483
+ ...
484
+ >>> T, N = 0.1, 51
485
+ >>> d_win = gaussian(N, std=1/T, sym=True) # symmetric Gaussian window
486
+ >>> t = T * (np.arange(N) - N//2)
487
+ ...
488
+ >>> fg1, ax1 = plt.subplots()
489
+ >>> ax1.set_title(r"Dual Window: Gaussian with $\sigma_t=1$")
490
+ >>> ax1.set(xlabel=f"Time $t$ in seconds ({N} samples, $T={T}$ s)",
491
+ ... xlim=(t[0], t[-1]), ylim=(0, 1.1*np.max(d_win)))
492
+ >>> ax1.plot(t, d_win, 'C0-')
493
+
494
+ The following plot with the overlap of 41, 11 and 2 samples show how
495
+ the `hop` interval affects the shape of the window `win`:
496
+
497
+ >>> fig2, axx = plt.subplots(3, 1, sharex='all')
498
+ ...
499
+ >>> axx[0].set_title(r"Windows for hop$\in\{10, 40, 49\}$")
500
+ >>> for c_, h_ in enumerate([10, 40, 49]):
501
+ ... SFT = ShortTimeFFT.from_dual(d_win, h_, 1/T)
502
+ ... axx[c_].plot(t + h_ * T, SFT.win, 'k--', alpha=.3, label=None)
503
+ ... axx[c_].plot(t - h_ * T, SFT.win, 'k:', alpha=.3, label=None)
504
+ ... axx[c_].plot(t, SFT.win, f'C{c_+1}',
505
+ ... label=r"$\Delta t=%0.1f\,$s" % SFT.delta_t)
506
+ ... axx[c_].set_ylim(0, 1.1*max(SFT.win))
507
+ ... axx[c_].legend(loc='center')
508
+ >>> axx[-1].set(xlabel=f"Time $t$ in seconds ({N} samples, $T={T}$ s)",
509
+ ... xlim=(t[0], t[-1]))
510
+ >>> plt.show()
511
+
512
+ Beside the window `win` centered at t = 0 the previous (t = -`delta_t`)
513
+ and following window (t = `delta_t`) are depicted. It can be seen that
514
+ for small `hop` intervals, the window is compact and smooth, having a
515
+ good time-frequency concentration in the STFT. For the large `hop`
516
+ interval of 4.9 s, the window has small values around t = 0, which are
517
+ not covered by the overlap of the adjacent windows, which could lead to
518
+ numeric inaccuracies. Furthermore, the peaky shape at the beginning and
519
+ the end of the window points to a higher bandwidth, resulting in a
520
+ poorer time-frequency resolution of the STFT.
521
+ Hence, the choice of the `hop` interval will be a compromise between
522
+ a time-frequency resolution and memory requirements demanded by small
523
+ `hop` sizes.
524
+
525
+ See Also
526
+ --------
527
+ from_window: Create instance by wrapping `get_window`.
528
+ ShortTimeFFT: Create instance using standard initializer.
529
+ """
530
+ win = _calc_dual_canonical_window(dual_win, hop)
531
+ return cls(win=win, hop=hop, fs=fs, fft_mode=fft_mode, mfft=mfft,
532
+ dual_win=dual_win, scale_to=scale_to,
533
+ phase_shift=phase_shift)
534
+
535
+ @classmethod
536
+ def from_window(cls, win_param: str | tuple | float,
537
+ fs: float, nperseg: int, noverlap: int, *,
538
+ symmetric_win: bool = False,
539
+ fft_mode: FFT_MODE_TYPE = 'onesided',
540
+ mfft: int | None = None,
541
+ scale_to: Literal['magnitude', 'psd'] | None = None,
542
+ phase_shift: int | None = 0):
543
+ """Instantiate `ShortTimeFFT` by using `get_window`.
544
+
545
+ The method `get_window` is used to create a window of length
546
+ `nperseg`. The parameter names `noverlap`, and `nperseg` are used here,
547
+ since they more inline with other classical STFT libraries.
548
+
549
+ Parameters
550
+ ----------
551
+ win_param: Union[str, tuple, float],
552
+ Parameters passed to `get_window`. For windows with no parameters,
553
+ it may be a string (e.g., ``'hann'``), for parametrized windows a
554
+ tuple, (e.g., ``('gaussian', 2.)``) or a single float specifying
555
+ the shape parameter of a kaiser window (i.e. ``4.`` and
556
+ ``('kaiser', 4.)`` are equal. See `get_window` for more details.
557
+ fs : float
558
+ Sampling frequency of input signal. Its relation to the
559
+ sampling interval `T` is ``T = 1 / fs``.
560
+ nperseg: int
561
+ Window length in samples, which corresponds to the `m_num`.
562
+ noverlap: int
563
+ Window overlap in samples. It relates to the `hop` increment by
564
+ ``hop = npsereg - noverlap``.
565
+ symmetric_win: bool
566
+ If ``True`` then a symmetric window is generated, else a periodic
567
+ window is generated (default). Though symmetric windows seem for
568
+ most applications to be more sensible, the default of a periodic
569
+ windows was chosen to correspond to the default of `get_window`.
570
+ fft_mode : 'twosided', 'centered', 'onesided', 'onesided2X'
571
+ Mode of FFT to be used (default 'onesided').
572
+ See property `fft_mode` for details.
573
+ mfft: int | None
574
+ Length of the FFT used, if a zero padded FFT is desired.
575
+ If ``None`` (default), the length of the window `win` is used.
576
+ scale_to : 'magnitude', 'psd' | None
577
+ If not ``None`` (default) the window function is scaled, so each
578
+ STFT column represents either a 'magnitude' or a power spectral
579
+ density ('psd') spectrum. This parameter sets the property
580
+ `scaling` to the same value. See method `scale_to` for details.
581
+ phase_shift : int | None
582
+ If set, add a linear phase `phase_shift` / `mfft` * `f` to each
583
+ frequency `f`. The default value 0 ensures that there is no phase
584
+ shift on the zeroth slice (in which t=0 is centered). See property
585
+ `phase_shift` for more details.
586
+
587
+ Examples
588
+ --------
589
+ The following instances ``SFT0`` and ``SFT1`` are equivalent:
590
+
591
+ >>> from scipy.signal import ShortTimeFFT, get_window
592
+ >>> nperseg = 9 # window length
593
+ >>> w = get_window(('gaussian', 2.), nperseg)
594
+ >>> fs = 128 # sampling frequency
595
+ >>> hop = 3 # increment of STFT time slice
596
+ >>> SFT0 = ShortTimeFFT(w, hop, fs=fs)
597
+ >>> SFT1 = ShortTimeFFT.from_window(('gaussian', 2.), fs, nperseg,
598
+ ... noverlap=nperseg-hop)
599
+
600
+ See Also
601
+ --------
602
+ scipy.signal.get_window: Return a window of a given length and type.
603
+ from_dual: Create instance using dual window.
604
+ ShortTimeFFT: Create instance using standard initializer.
605
+ """
606
+ win = get_window(win_param, nperseg, fftbins=not symmetric_win)
607
+ return cls(win, hop=nperseg-noverlap, fs=fs, fft_mode=fft_mode,
608
+ mfft=mfft, scale_to=scale_to, phase_shift=phase_shift)
609
+
610
+ @classmethod
611
+ def from_win_equals_dual(
612
+ cls, desired_win: np.ndarray, hop: int, fs: float, *,
613
+ fft_mode: FFT_MODE_TYPE = 'onesided', mfft: int | None = None,
614
+ scale_to: Literal['magnitude', 'psd', 'unitary'] | None = None,
615
+ phase_shift: int | None = 0):
616
+ r"""Create instance where the window and its dual are equal up to a
617
+ scaling factor.
618
+
619
+ An instance is created were window and dual window are equal as well as being
620
+ closest to the parameter `desired_win` in the least-squares sense, i.e.,
621
+ minimizing ``abs(win-desired_win)**2``. Hence, `win` has the same length as
622
+ `desired_win`. Then a scaling factor is applied accoring to the `scale_to`
623
+ parameter.
624
+
625
+ All other parameters have the identical meaning as in the initializer.
626
+
627
+ To be able to calculate a valid window, `desired_win` needs to have a valid
628
+ dual STFT window for the given `hop` interval.
629
+ If this is not the case, a ``ValueError`` is raised.
630
+
631
+ Parameters
632
+ ----------
633
+ desired_win : np.ndarray
634
+ A real-valued or complex-valued 1d array containing the sample of the
635
+ desired window.
636
+ hop : int
637
+ The increment in samples, by which the window is shifted in each step.
638
+ fs : float
639
+ Sampling frequency of input signal and window. Its relation to the
640
+ sampling interval `T` is ``T = 1 / fs``.
641
+ fft_mode : 'twosided', 'centered', 'onesided', 'onesided2X'
642
+ Mode of FFT to be used (default 'onesided').
643
+ See property `fft_mode` for details.
644
+ mfft: int | None
645
+ Length of the FFT used, if a zero padded FFT is desired.
646
+ If ``None`` (default), the length of the window `win` is used.
647
+ scale_to : 'magnitude' | 'psd' | 'unitary' | None
648
+ If not ``None`` (default) the window function is scaled, so each STFT
649
+ column represents either a 'magnitude' or a power spectral density ('psd')
650
+ spectrum, Alternatively, the STFT can be scaled to a`unitary` mapping,
651
+ i.e., dividing the window by ``np.sqrt(mfft)`` and multiplying the dual
652
+ window by the same amount.
653
+ phase_shift : int | None
654
+ If set, add a linear phase `phase_shift` / `mfft` * `f` to each
655
+ frequency `f`. The default value of 0 ensures that there is no phase shift
656
+ on the zeroth slice (in which t=0 is centered). See property
657
+ `phase_shift` for more details.
658
+
659
+
660
+ Notes
661
+ -----
662
+ The set of all possible windows with identical dual is defined by the set of
663
+ linear constraints of Eq. :math:numref:`eq_STFT_AllDualWinsCond` in the
664
+ :ref:`tutorial_stft` section of the :ref:`user_guide`. There it is also
665
+ derived that ``ShortTimeFFT.dual_win == ShortTimeFFT.m_pts * ShortTimeFFT.win``
666
+ needs to hold for an STFT to be a unitary mapping.
667
+
668
+ A unitary mapping preserves the value of the scalar product, i.e.,
669
+
670
+ .. math::
671
+
672
+ \langle x, y\rangle = \sum_k x[k]\, \overline{y[k]}
673
+ \stackrel{\stackrel{\text{unitary}}{\downarrow}}{=}
674
+ \sum_{q,p} S_x[q,p]\, \overline{S_y[q,p]}
675
+ = \langle S_x[q,p], S_y[q,p]\rangle\ ,
676
+
677
+ with :math:`S_{x,y}` being the STFT of :math:`x,y`. Hence, the energy
678
+ :math:`E_x=T\sum_k |x[k]|^2` of a signal is also preserved. This is also
679
+ illustrated in the example below.
680
+
681
+ Thie reason of distinguishing between no scaling (i.e., parameter `scale_to` is
682
+ ``None``) and unitary scaling (i.e., ``scale_to = 'unitary'``) is due to the
683
+ utilized FFT function not being unitary (i.e., using the default value
684
+ ``'backward'`` for the `~scipy.fft.fft` parameter `norm`).
685
+
686
+
687
+ See Also
688
+ --------
689
+ closest_STFT_dual_window: Calculate the STFT dual window of a given window
690
+ closest to a desired dual window.
691
+ ShortTimeFFT.spectrogram: Calculate squared STFTs
692
+ ShortTimeFFT: Class this property belongs to.
693
+
694
+ Examples
695
+ --------
696
+ The following example shows that an STFT can be indeed unitary:
697
+
698
+ >>> import matplotlib.pyplot as plt
699
+ >>> import numpy as np
700
+ >>> from scipy.signal import ShortTimeFFT, windows
701
+ ...
702
+ >>> m, hop, std = 36, 8, 5
703
+ >>> desired_win = windows.gaussian(m, std, sym=True)
704
+ >>> SFT = ShortTimeFFT.from_win_equals_dual(desired_win, hop, fs=1/m,
705
+ ... fft_mode='twosided',
706
+ ... scale_to='unitary')
707
+ >>> np.allclose(SFT.dual_win, SFT.win * SFT.m_num) # check if STFT is unitary
708
+ True
709
+ >>> x1, x2 = np.tile([-1, -1, 1, 1], 5), np.tile([1, -1, -1, 1], 5)
710
+ >>> np.sum(x1*x2) # scalar product is zero -> orthogonal signals
711
+ 0
712
+ >>> np.sum(x1**2) # scalar product of x1 with itself
713
+ 20
714
+ >>> Sx11, Sx12 = SFT.spectrogram(x1), SFT.spectrogram(x1, x2)
715
+ >>> np.sum(Sx12) # STFT scalar product is also zero
716
+ -4.163336342344337e-16+0j # may vary
717
+ >>> np.sum(Sx11) # == np.sum(x1**2)
718
+ 19.999999999999996 # may vary
719
+ ...
720
+ ... # Do the plotting:
721
+ >>> fg1, (ax11, ax12) = plt.subplots(1, 2, tight_layout=True, figsize=(8, 4))
722
+ >>> s_fac = np.sqrt(SFT.mfft)
723
+ >>> _ = fg1.suptitle(f"Scaled Unitary Window of {m} Sample Gaussian with " +
724
+ ... rf"{hop=}, $\sigma={std}$, Scale factor: {s_fac}")
725
+ >>> ax11.set(ylabel="Amplitude", xlabel="Samples", xlim=(0, m))
726
+ >>> ax12.set(xlabel="Frequency Bins", ylabel="Magnitude Spectrum",
727
+ ... xlim=(0, 15), ylim=(1e-5, 1.5))
728
+ >>> u_win_str = rf"Unitary $\times{s_fac:g}$"
729
+ >>> for x_, n_ in zip((desired_win, SFT.win*s_fac), ('Desired', u_win_str)):
730
+ ... ax11.plot(x_, '.-', alpha=0.5, label=n_)
731
+ ... X_ = np.fft.rfft(x_) / np.sum(abs(x_))
732
+ ... ax12.semilogy(abs(X_), '.-', alpha=0.5, label=n_)
733
+ >>> for ax_ in (ax11, ax12):
734
+ ... ax_.grid(True)
735
+ ... ax_.legend()
736
+ >>> plt.show()
737
+
738
+ Note that ``fftmode='twosided'`` is used, since we need sum over the complete
739
+ time frequency plane. Due to passing ``scale_to='unitary'`` the window
740
+ ``SFT.win`` is scaled by ``1/np.sqrt(SFT.mfft)``. Hence, ``SFT.win`` needs to
741
+ be scaled by `s_fac` in the plot above.
742
+ """
743
+ if not (desired_win.ndim == 1 and desired_win.size > 0):
744
+ raise ValueError(f"Parameter desired_win is not 1d, but "
745
+ f"{desired_win.shape=}!")
746
+ if issubclass(desired_win.dtype.type, np.integer):
747
+ raise ValueError("Parameter desired_win cannot be of integer type, " +
748
+ f"but {desired_win.dtype=} => cast to float | complex ")
749
+ if not all(np.isfinite(desired_win)):
750
+ raise ValueError("Parameter desired_win must have finite entries!")
751
+ if not (1 <= hop <= len(desired_win) and isinstance(hop, int | np.integer)):
752
+ raise ValueError(f"Parameter {hop=} is not an integer between 1 and " +
753
+ f"{len(desired_win)=}!")
754
+ if scale_to not in ['magnitude', 'psd', 'unitary', None]:
755
+ raise ValueError(f"Parameter {scale_to=} not in " +
756
+ "['magnitude', 'psd', 'unitary', None]!")
757
+
758
+ mfft = len(desired_win) if mfft is None else mfft
759
+ s_fac = np.sqrt(mfft) if scale_to == 'unitary' else 1
760
+
761
+ win = desired_win.copy() # we do not want to modify input parameters
762
+ relative_resolution = np.finfo(win.dtype).resolution * max(win)
763
+ for m in range(hop):
764
+ a = np.linalg.norm(desired_win[m::hop])
765
+ if not (a > relative_resolution):
766
+ raise ValueError("Parameter desired_win does not have valid STFT dual "
767
+ f"window for {hop=}!")
768
+ win[m::hop] /= a
769
+
770
+ SFT = cls(win=win/s_fac, hop=hop, fs=fs, fft_mode=fft_mode, mfft=mfft,
771
+ dual_win=win*s_fac, phase_shift=phase_shift,
772
+ scale_to=None if scale_to=='unitary' else scale_to)
773
+
774
+ if scale_to == 'unitary':
775
+ SFT._scaling = scale_to
776
+ return SFT
777
+
778
+
779
+ @property
780
+ def win(self) -> np.ndarray:
781
+ """Window function as real- or complex-valued 1d array.
782
+
783
+ This attribute is read-only, since `dual_win` depends on it.
784
+ To make this array immutable, its WRITEABLE flag is set to ``FALSE``.
785
+
786
+ See Also
787
+ --------
788
+ dual_win: Dual window.
789
+ m_num: Number of samples in window `win`.
790
+ m_num_mid: Center index of window `win`.
791
+ mfft: Length of input for the FFT used - may be larger than `m_num`.
792
+ hop: ime increment in signal samples for sliding window.
793
+ win: Window function as real- or complex-valued 1d array.
794
+ numpy.ndarray.setflags: Modify array flags.
795
+ ShortTimeFFT: Class this property belongs to.
796
+ """
797
+ return self._win
798
+
799
+ @property
800
+ def hop(self) -> int:
801
+ """Time increment in signal samples for sliding window.
802
+
803
+ This attribute is read only, since `dual_win` depends on it.
804
+
805
+ See Also
806
+ --------
807
+ delta_t: Time increment of STFT (``hop*T``)
808
+ m_num: Number of samples in window `win`.
809
+ m_num_mid: Center index of window `win`.
810
+ mfft: Length of input for the FFT used - may be larger than `m_num`.
811
+ T: Sampling interval of input signal and of the window.
812
+ win: Window function as real- or complex-valued 1d array.
813
+ ShortTimeFFT: Class this property belongs to.
814
+ """
815
+ return self._hop
816
+
817
+ @property
818
+ def T(self) -> float:
819
+ """Sampling interval of input signal and of the window.
820
+
821
+ A ``ValueError`` is raised if it is set to a non-positive value.
822
+
823
+ See Also
824
+ --------
825
+ delta_t: Time increment of STFT (``hop*T``)
826
+ hop: Time increment in signal samples for sliding window.
827
+ fs: Sampling frequency (being ``1/T``)
828
+ t: Times of STFT for an input signal with `n` samples.
829
+ ShortTimeFFT: Class this property belongs to.
830
+ """
831
+ return 1 / self._fs
832
+
833
+ @T.setter
834
+ def T(self, v: float):
835
+ """Sampling interval of input signal and of the window.
836
+
837
+ A ``ValueError`` is raised if it is set to a non-positive value.
838
+ """
839
+ if not (v > 0):
840
+ raise ValueError(f"Sampling interval T={v} must be positive!")
841
+ self._fs = 1 / v
842
+
843
+ @property
844
+ def fs(self) -> float:
845
+ """Sampling frequency of input signal and of the window.
846
+
847
+ The sampling frequency is the inverse of the sampling interval `T`.
848
+ A ``ValueError`` is raised if it is set to a non-positive value.
849
+
850
+ See Also
851
+ --------
852
+ delta_t: Time increment of STFT (``hop*T``)
853
+ hop: Time increment in signal samples for sliding window.
854
+ T: Sampling interval of input signal and of the window (``1/fs``).
855
+ ShortTimeFFT: Class this property belongs to.
856
+ """
857
+ return self._fs
858
+
859
+ @fs.setter
860
+ def fs(self, v: float):
861
+ """Sampling frequency of input signal and of the window.
862
+
863
+ The sampling frequency is the inverse of the sampling interval `T`.
864
+ A ``ValueError`` is raised if it is set to a non-positive value.
865
+ """
866
+ if not (v > 0):
867
+ raise ValueError(f"Sampling frequency fs={v} must be positive!")
868
+ self._fs = v
869
+
870
+ @property
871
+ def fft_mode(self) -> FFT_MODE_TYPE:
872
+ """Mode of utilized FFT ('twosided', 'centered', 'onesided' or
873
+ 'onesided2X').
874
+
875
+ It can have the following values:
876
+
877
+ 'twosided':
878
+ Two-sided FFT, where values for the negative frequencies are in
879
+ upper half of the array. Corresponds to :func:`~scipy.fft.fft()`.
880
+ 'centered':
881
+ Two-sided FFT with the values being ordered along monotonically
882
+ increasing frequencies. Corresponds to applying
883
+ :func:`~scipy.fft.fftshift()` to :func:`~scipy.fft.fft()`.
884
+ 'onesided':
885
+ Calculates only values for non-negative frequency values.
886
+ Corresponds to :func:`~scipy.fft.rfft()`.
887
+ 'onesided2X':
888
+ Like `onesided`, but the non-zero frequencies are doubled if
889
+ `scaling` is set to 'magnitude' or multiplied by ``sqrt(2)`` if
890
+ set to 'psd'. If `scaling` is ``None``, setting `fft_mode` to
891
+ `onesided2X` is not allowed.
892
+ If the FFT length `mfft` is even, the last FFT value is not paired,
893
+ and thus it is not scaled.
894
+
895
+ Note that `onesided` and `onesided2X` do not work for complex-valued signals or
896
+ complex-valued windows. Furthermore, the frequency values can be obtained by
897
+ reading the `f` property, and the number of samples by accessing the `f_pts`
898
+ property.
899
+
900
+ See Also
901
+ --------
902
+ delta_f: Width of the frequency bins of the STFT.
903
+ f: Frequencies values of the STFT.
904
+ f_pts: Width of the frequency bins of the STFT.
905
+ onesided_fft: True if a one-sided FFT is used.
906
+ scaling: Normalization applied to the window function
907
+ ShortTimeFFT: Class this property belongs to.
908
+ """
909
+ return self._fft_mode
910
+
911
+ @fft_mode.setter
912
+ def fft_mode(self, t: FFT_MODE_TYPE):
913
+ """Set mode of FFT.
914
+
915
+ Allowed values are 'twosided', 'centered', 'onesided', 'onesided2X'.
916
+ See the property `fft_mode` for more details.
917
+ """
918
+ if t not in (fft_mode_types := get_args(FFT_MODE_TYPE)):
919
+ raise ValueError(f"fft_mode='{t}' not in {fft_mode_types}!")
920
+
921
+ if t in {'onesided', 'onesided2X'} and np.iscomplexobj(self.win):
922
+ raise ValueError(f"One-sided spectra, i.e., fft_mode='{t}', " +
923
+ "are not allowed for complex-valued windows!")
924
+
925
+ if t == 'onesided2X' and self.scaling is None:
926
+ raise ValueError(f"For scaling is None, fft_mode='{t}' is invalid!"
927
+ "Do scale_to('psd') or scale_to('magnitude')!")
928
+ self._fft_mode = t
929
+
930
+ @property
931
+ def mfft(self) -> int:
932
+ """Length of input for the FFT used - may be larger than window
933
+ length `m_num`.
934
+
935
+ If not set, `mfft` defaults to the window length `m_num`.
936
+
937
+ See Also
938
+ --------
939
+ f_pts: Number of points along the frequency axis.
940
+ f: Frequencies values of the STFT.
941
+ m_num: Number of samples in window `win`.
942
+ ShortTimeFFT: Class this property belongs to.
943
+ """
944
+ return self._mfft
945
+
946
+ @mfft.setter
947
+ def mfft(self, n_: int):
948
+ """Setter for the length of FFT utilized.
949
+
950
+ See the property `mfft` for further details.
951
+ """
952
+ if not (n_ >= self.m_num):
953
+ raise ValueError(f"Attribute mfft={n_} needs to be at least the " +
954
+ f"window length m_num={self.m_num}!")
955
+ self._mfft = n_
956
+
957
+ @property
958
+ def scaling(self) -> Literal['magnitude', 'psd', 'unitary'] | None:
959
+ """Normalization applied to the window function
960
+ ('magnitude', 'psd', 'unitary', or ``None``).
961
+
962
+ If not ``None``, the FFT slices may be either interpreted as a `magnitude` or
963
+ a power spectral density spectrum (`psd`). If set to `unitary`, the STFT may be
964
+ interpreted as a unitary mapping, i.e., preserving the value of the scalar
965
+ product.
966
+
967
+ The window function can be scaled by calling the `scale_to` method,
968
+ or it is set by the initializer parameter ``scale_to``. Note that a
969
+ window cannot to be scaled to be `unitary`. Use `from_win_equals_dual`
970
+ to create a unitary `ShortTimeFFT` instance.
971
+
972
+ See Also
973
+ --------
974
+ fac_magnitude: Scaling factor for to a magnitude spectrum.
975
+ fac_psd: Scaling factor for to a power spectral density spectrum.
976
+ fft_mode: Mode of utilized FFT
977
+ scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
978
+ from_win_equals_dual: Class-method for creating a unitary instance.
979
+ ShortTimeFFT: Class this property belongs to.
980
+ """
981
+ return self._scaling
982
+
983
+ def scale_to(self, scaling: Literal['magnitude', 'psd']):
984
+ """Scale window to obtain 'magnitude' or 'psd' scaling for the STFT.
985
+
986
+ The window of a 'magnitude' spectrum has an integral of one, i.e., unit
987
+ area for non-negative windows. This ensures that absolute the values of
988
+ spectrum does not change if the length of the window changes (given
989
+ the input signal is stationary).
990
+
991
+ To represent the power spectral density ('psd') for varying length
992
+ windows the area of the absolute square of the window needs to be
993
+ unity.
994
+
995
+ The `scaling` property shows the current scaling. The properties
996
+ `fac_magnitude` and `fac_psd` show the scaling factors required to
997
+ scale the STFT values to a magnitude or a psd spectrum.
998
+
999
+ Note that a window cannot to be scaled to be `unitary`. Use
1000
+ `from_win_equals_dual` to create a unitary `ShortTimeFFT` instance.
1001
+
1002
+ This method is called, if the initializer parameter `scale_to` is set.
1003
+
1004
+ See Also
1005
+ --------
1006
+ fac_magnitude: Scaling factor for to a magnitude spectrum.
1007
+ fac_psd: Scaling factor for to a power spectral density spectrum.
1008
+ fft_mode: Mode of utilized FFT
1009
+ scaling: Normalization applied to the window function.
1010
+ ShortTimeFFT: Class this method belongs to.
1011
+ """
1012
+ if scaling not in (scaling_values := {'magnitude', 'psd'}):
1013
+ raise ValueError(f"{scaling=} not in {scaling_values}!")
1014
+ if self._scaling == scaling: # do nothing
1015
+ return
1016
+
1017
+ s_fac = self.fac_psd if scaling == 'psd' else self.fac_magnitude
1018
+ self._win = self._win * s_fac
1019
+ self.win.setflags(write=False)
1020
+ if self._dual_win is not None:
1021
+ self._dual_win = self._dual_win / s_fac
1022
+ self.dual_win.setflags(write=False)
1023
+ self._fac_mag, self._fac_psd = None, None # reset scaling factors
1024
+ self._scaling = scaling
1025
+
1026
+ @property
1027
+ def phase_shift(self) -> int | None:
1028
+ """If set, add linear phase `phase_shift` / `mfft` * `f` to each FFT
1029
+ slice of frequency `f`.
1030
+
1031
+ Shifting (more precisely `rolling`) an `mfft`-point FFT input by
1032
+ `phase_shift` samples results in a multiplication of the output by
1033
+ ``np.exp(2j*np.pi*q*phase_shift/mfft)`` at the frequency q * `delta_f`.
1034
+
1035
+ The default value 0 ensures that there is no phase shift on the
1036
+ zeroth slice (in which t=0 is centered).
1037
+ No phase shift (``phase_shift is None``) is equivalent to
1038
+ ``phase_shift = -mfft//2``. In this case slices are not shifted
1039
+ before calculating the FFT.
1040
+
1041
+ The absolute value of `phase_shift` is limited to be less than `mfft`.
1042
+
1043
+ See Also
1044
+ --------
1045
+ delta_f: Width of the frequency bins of the STFT.
1046
+ f: Frequencies values of the STFT.
1047
+ mfft: Length of input for the FFT used
1048
+ ShortTimeFFT: Class this property belongs to.
1049
+ """
1050
+ return self._phase_shift
1051
+
1052
+ @phase_shift.setter
1053
+ def phase_shift(self, v: int | None):
1054
+ """The absolute value of the phase shift needs to be less than mfft
1055
+ samples.
1056
+
1057
+ See the `phase_shift` getter method for more details.
1058
+ """
1059
+ if v is None:
1060
+ self._phase_shift = v
1061
+ return
1062
+ if not isinstance(v, int | np.integer):
1063
+ raise ValueError(f"phase_shift={v} has the unit samples. Hence " +
1064
+ "it needs to be an int or it may be None!")
1065
+ if not (-self.mfft < v < self.mfft):
1066
+ raise ValueError("-mfft < phase_shift < mfft does not hold " +
1067
+ f"for mfft={self.mfft}, phase_shift={v}!")
1068
+ self._phase_shift = v
1069
+
1070
+ def _x_slices(self, x: np.ndarray, k_off: int, p0: int, p1: int,
1071
+ padding: PAD_TYPE) -> Generator[np.ndarray, None, None]:
1072
+ """Generate signal slices along last axis of `x`.
1073
+
1074
+ This method is only used by `stft_detrend`. The parameters are
1075
+ described in `~ShortTimeFFT.stft`.
1076
+ """
1077
+ if padding not in (padding_types := get_args(PAD_TYPE)):
1078
+ raise ValueError(f"Parameter {padding=} not in {padding_types}!")
1079
+ pad_kws: dict[str, dict] = { # possible keywords to pass to np.pad:
1080
+ 'zeros': dict(mode='constant', constant_values=(0, 0)),
1081
+ 'edge': dict(mode='edge'),
1082
+ 'even': dict(mode='reflect', reflect_type='even'),
1083
+ 'odd': dict(mode='reflect', reflect_type='odd'),
1084
+ } # typing of pad_kws is needed to make mypy happy
1085
+
1086
+ n, n1 = x.shape[-1], (p1 - p0) * self.hop
1087
+ k0 = p0 * self.hop - self.m_num_mid + k_off # start sample
1088
+ k1 = k0 + n1 + self.m_num # end sample
1089
+
1090
+ i0, i1 = max(k0, 0), min(k1, n) # indexes to shorten x
1091
+ # dimensions for padding x:
1092
+ pad_width = [(0, 0)] * (x.ndim-1) + [(-min(k0, 0), max(k1 - n, 0))]
1093
+
1094
+ x1 = np.pad(x[..., i0:i1], pad_width, **pad_kws[padding])
1095
+ for k_ in range(0, n1, self.hop):
1096
+ yield x1[..., k_:k_ + self.m_num]
1097
+
1098
+ def stft(self, x: np.ndarray, p0: int | None = None,
1099
+ p1: int | None = None, *, k_offset: int = 0,
1100
+ padding: PAD_TYPE = 'zeros', axis: int = -1) \
1101
+ -> np.ndarray:
1102
+ """Perform the short-time Fourier transform.
1103
+
1104
+ A two-dimensional matrix with ``p1-p0`` columns is calculated.
1105
+ The `f_pts` rows represent value at the frequencies `f`. The q-th
1106
+ column of the windowed FFT with the window `win` is centered at t[q].
1107
+ The columns represent the values at the frequencies `f`.
1108
+
1109
+ Parameters
1110
+ ----------
1111
+ x : np.ndarray
1112
+ The input signal as real or complex valued array. For complex values, the
1113
+ property `fft_mode` must be set to 'twosided' or 'centered'.
1114
+ p0 : int | None
1115
+ The first element of the range of slices to calculate. If ``None``
1116
+ then it is set to :attr:`p_min`, which is the smallest possible
1117
+ slice.
1118
+ p1 : int | None
1119
+ The end of the array. If ``None`` then `p_max(n)` is used.
1120
+ k_offset : int
1121
+ Index of first sample (t = 0) in `x`.
1122
+ padding : 'zeros' | 'edge' | 'even' | 'odd'
1123
+ Kind of values which are added, when the sliding window sticks out
1124
+ on either the lower or upper end of the input `x`. Zeros are added
1125
+ if the default 'zeros' is set. For 'edge' either the first or the
1126
+ last value of `x` is used. 'even' pads by reflecting the
1127
+ signal on the first or last sample and 'odd' additionally
1128
+ multiplies it with -1.
1129
+ axis : int
1130
+ The axis of `x` over which to compute the STFT.
1131
+ If not given, the last axis is used.
1132
+
1133
+ Returns
1134
+ -------
1135
+ S : np.ndarray
1136
+ A complex array is returned with the dimension always being larger
1137
+ by one than of `x`. The last axis always represents the time slices
1138
+ of the STFT. `axis` defines the frequency axis (default second to
1139
+ last). E.g., for a one-dimensional `x`, a complex 2d array is
1140
+ returned, with axis 0 representing frequency and axis 1 the time
1141
+ slices.
1142
+
1143
+ See Also
1144
+ --------
1145
+ delta_f: Width of the frequency bins of the STFT.
1146
+ delta_t: Time increment of STFT
1147
+ f: Frequencies values of the STFT.
1148
+ invertible: Check if STFT is invertible.
1149
+ :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
1150
+ p_range: Determine and validate slice index range.
1151
+ stft_detrend: STFT with detrended segments.
1152
+ t: Times of STFT for an input signal with `n` samples.
1153
+ :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
1154
+ """
1155
+ return self.stft_detrend(x, None, p0, p1, k_offset=k_offset,
1156
+ padding=padding, axis=axis)
1157
+
1158
+ def stft_detrend(self, x: np.ndarray,
1159
+ detr: Callable[[np.ndarray], np.ndarray] | Literal['linear', 'constant'] | None, # noqa: E501
1160
+ p0: int | None = None, p1: int | None = None, *,
1161
+ k_offset: int = 0, padding: PAD_TYPE = 'zeros',
1162
+ axis: int = -1) \
1163
+ -> np.ndarray:
1164
+ """Calculate short-time Fourier transform with a trend being subtracted from
1165
+ each segment beforehand.
1166
+
1167
+ When the parameter `detr` is ``None``, this method's behavior is identical to
1168
+ the `~ShortTimeFFT.stft` method. Note that due to the detrending, the original
1169
+ signal cannot be reconstructed by the `~ShortTimeFFT.istft`.
1170
+
1171
+ Parameters
1172
+ ----------
1173
+ x : np.ndarray
1174
+ The input signal as real or complex valued array. For complex values, the
1175
+ property `fft_mode` must be set to 'twosided' or 'centered'.
1176
+ detr : 'linear' | 'constant' | Callable[[np.ndarray], np.ndarray] | None
1177
+ If 'constant', the mean is subtracted, if set to "linear", the linear
1178
+ trend is removed from each segment. This is achieved by calling
1179
+ `~scipy.signal.detrend`. If `detr` is a function with one parameter, `detr`
1180
+ is applied to each segment.
1181
+ p0 : int | None
1182
+ The first element of the range of slices to calculate. If ``None``
1183
+ then it is set to :attr:`p_min`, which is the smallest possible
1184
+ slice.
1185
+ p1 : int | None
1186
+ The end of the array. If ``None`` then `p_max(n)` is used.
1187
+ k_offset : int
1188
+ Index of first sample (t = 0) in `x`.
1189
+ padding : 'zeros' | 'edge' | 'even' | 'odd'
1190
+ Kind of values which are added, when the sliding window sticks out
1191
+ on either the lower or upper end of the input `x`. Zeros are added
1192
+ if the default 'zeros' is set. For 'edge' either the first or the
1193
+ last value of `x` is used. 'even' pads by reflecting the
1194
+ signal on the first or last sample and 'odd' additionally
1195
+ multiplies it with -1.
1196
+ axis: int
1197
+ The axis of `x` over which to compute the STFT.
1198
+ If not given, the last axis is used.
1199
+
1200
+ Returns
1201
+ -------
1202
+ S : np.ndarray
1203
+ A complex array is returned with the dimension always being larger
1204
+ by one than of `x`. The last axis always represents the time slices
1205
+ of the STFT. `axis` defines the frequency axis (default second to
1206
+ last). E.g., for a one-dimensional `x`, a complex 2d array is
1207
+ returned, with axis 0 representing frequency and axis 1 the time
1208
+ slices.
1209
+
1210
+ See Also
1211
+ --------
1212
+ invertible: Check if STFT is invertible.
1213
+ :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
1214
+ :meth:`~ShortTimeFFT.stft`: Short-time Fourier transform
1215
+ (without detrending).
1216
+ :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
1217
+ """
1218
+ if self.onesided_fft and np.iscomplexobj(x):
1219
+ raise ValueError(f"Complex-valued `x` not allowed for {self.fft_mode=}'! "
1220
+ "Set property `fft_mode` to 'twosided' or 'centered'.")
1221
+ if isinstance(detr, str):
1222
+ detr = partial(detrend, type=detr)
1223
+ elif not (detr is None or callable(detr)):
1224
+ raise ValueError(f"Parameter {detr=} is not a str, function or " +
1225
+ "None!")
1226
+ n = x.shape[axis]
1227
+ if not (n >= (m2p := self.m_num-self.m_num_mid)):
1228
+ e_str = f'{len(x)=}' if x.ndim == 1 else f'of {axis=} of {x.shape}'
1229
+ raise ValueError(f"{e_str} must be >= ceil(m_num/2) = {m2p}!")
1230
+
1231
+ if x.ndim > 1: # motivated by the NumPy broadcasting mechanisms:
1232
+ x = np.moveaxis(x, axis, -1)
1233
+ # determine slice index range:
1234
+ p0, p1 = self.p_range(n, p0, p1)
1235
+ S_shape_1d = (self.f_pts, p1 - p0)
1236
+ S_shape = x.shape[:-1] + S_shape_1d if x.ndim > 1 else S_shape_1d
1237
+ S = np.zeros(S_shape, dtype=complex)
1238
+ for p_, x_ in enumerate(self._x_slices(x, k_offset, p0, p1, padding)):
1239
+ if detr is not None:
1240
+ x_ = detr(x_)
1241
+ S[..., :, p_] = self._fft_func(x_ * self.win.conj())
1242
+ if x.ndim > 1:
1243
+ return np.moveaxis(S, -2, axis if axis >= 0 else axis-1)
1244
+ return S
1245
+
1246
+ def spectrogram(self, x: np.ndarray, y: np.ndarray | None = None,
1247
+ detr: Callable[[np.ndarray], np.ndarray] | Literal['linear', 'constant'] | None = None, # noqa: E501
1248
+ *,
1249
+ p0: int | None = None, p1: int | None = None,
1250
+ k_offset: int = 0, padding: PAD_TYPE = 'zeros',
1251
+ axis: int = -1) \
1252
+ -> np.ndarray:
1253
+ r"""Calculate spectrogram or cross-spectrogram.
1254
+
1255
+ The spectrogram is the absolute square of the STFT, i.e., it is
1256
+ ``abs(S[q,p])**2`` for given ``S[q,p]`` and thus is always
1257
+ non-negative.
1258
+ For two STFTs ``Sx[q,p], Sy[q,p]``, the cross-spectrogram is defined
1259
+ as ``Sx[q,p] * np.conj(Sy[q,p])`` and is complex-valued.
1260
+ This is a convenience function for calling `~ShortTimeFFT.stft` /
1261
+ `stft_detrend`, hence all parameters are discussed there.
1262
+
1263
+ Parameters
1264
+ ----------
1265
+ x : np.ndarray
1266
+ The input signal as real or complex valued array. For complex values, the
1267
+ property `fft_mode` must be set to 'twosided' or 'centered'.
1268
+ y : np.ndarray
1269
+ The second input signal of the same shape as `x`. If ``None``, it is
1270
+ assumed to be `x`. For complex values, the property `fft_mode` must be
1271
+ set to 'twosided' or 'centered'.
1272
+ detr : 'linear' | 'constant' | Callable[[np.ndarray], np.ndarray] | None
1273
+ If 'constant', the mean is subtracted, if set to "linear", the linear
1274
+ trend is removed from each segment. This is achieved by calling
1275
+ `~scipy.signal.detrend`. If `detr` is a function with one parameter, `detr`
1276
+ is applied to each segment. For ``None`` (default), no trends are removed.
1277
+ p0 : int | None
1278
+ The first element of the range of slices to calculate. If ``None``
1279
+ then it is set to :attr:`p_min`, which is the smallest possible
1280
+ slice.
1281
+ p1 : int | None
1282
+ The end of the array. If ``None`` then `p_max(n)` is used.
1283
+ k_offset : int
1284
+ Index of first sample (t = 0) in `x`.
1285
+ padding : 'zeros' | 'edge' | 'even' | 'odd'
1286
+ Kind of values which are added, when the sliding window sticks out
1287
+ on either the lower or upper end of the input `x`. Zeros are added
1288
+ if the default 'zeros' is set. For 'edge' either the first or the
1289
+ last value of `x` is used. 'even' pads by reflecting the
1290
+ signal on the first or last sample and 'odd' additionally
1291
+ multiplies it with -1.
1292
+ axis : int
1293
+ The axis of `x` over which to compute the STFT.
1294
+ If not given, the last axis is used.
1295
+
1296
+ Returns
1297
+ -------
1298
+ S_xy : np.ndarray
1299
+ A real-valued array with non-negative values is returned, if ``x is y`` or
1300
+ `y` is ``None``. The dimension is always by one larger than of `x`. The
1301
+ last axis always represents the time slices of the spectrogram. `axis`
1302
+ defines the frequency axis (default second to last). E.g., for a
1303
+ one-dimensional `x`, a complex 2d array is returned, with axis 0
1304
+ representing frequency and axis 1 the time slices.
1305
+
1306
+ Notes
1307
+ -----
1308
+ The cross-spectrogram may be interpreted as the time-frequency analogon of the
1309
+ cross-spectral density (consult `csd`). The absolute square `|Sxy|²` of a
1310
+ cross-spectrogram `Sxy` divided by the spectrograms `Sxx` and `Syy` can be
1311
+ interpreted as a coherence spectrogram ``Cxy := abs(Sxy)**2 / (Sxx*Syy)``,
1312
+ which is the time-frequency analogon to `~coherence`.
1313
+
1314
+ If the STFT is parametrized to be a unitary transform, i.e., utilitzing
1315
+ `~from_win_equals_dual`, then the value of the scalar product, hence also the
1316
+ energy, is preserved.
1317
+
1318
+ Examples
1319
+ --------
1320
+ The following example shows the spectrogram of a square wave with varying
1321
+ frequency :math:`f_i(t)` (marked by a green dashed line in the plot) sampled
1322
+ with 20 Hz. The utilized Gaussian window is 50 samples or 2.5 s long. For the
1323
+ `ShortTimeFFT`, the parameter ``mfft=800`` (oversampling factor 16) and the
1324
+ `hop` interval of 2 in was chosen to produce a sufficient number of points.
1325
+
1326
+ The plot's colormap is logarithmically scaled as the power spectral
1327
+ density is in dB. The time extent of the signal `x` is marked by
1328
+ vertical dashed lines, and the shaded areas mark the presence of border
1329
+ effects.
1330
+
1331
+ >>> import matplotlib.pyplot as plt
1332
+ >>> import numpy as np
1333
+ >>> from scipy.signal import square, ShortTimeFFT
1334
+ >>> from scipy.signal.windows import gaussian
1335
+ ...
1336
+ >>> T_x, N = 1 / 20, 1000 # 20 Hz sampling rate for 50 s signal
1337
+ >>> t_x = np.arange(N) * T_x # time indexes for signal
1338
+ >>> f_i = 5e-3*(t_x - t_x[N // 3])**2 + 1 # varying frequency
1339
+ >>> x = square(2*np.pi*np.cumsum(f_i)*T_x) # the signal
1340
+ ...
1341
+ >>> g_std = 12 # standard deviation for Gaussian window in samples
1342
+ >>> win = gaussian(50, std=g_std, sym=True) # symmetric Gaussian wind.
1343
+ >>> SFT = ShortTimeFFT(win, hop=2, fs=1/T_x, mfft=800, scale_to='psd')
1344
+ >>> Sx2 = SFT.spectrogram(x) # calculate absolute square of STFT
1345
+ ...
1346
+ >>> fig1, ax1 = plt.subplots(figsize=(6., 4.)) # enlarge plot a bit
1347
+ >>> t_lo, t_hi = SFT.extent(N)[:2] # time range of plot
1348
+ >>> ax1.set_title(rf"Spectrogram ({SFT.m_num*SFT.T:g}$\,s$ Gaussian " +
1349
+ ... rf"window, $\sigma_t={g_std*SFT.T:g}\,$s)")
1350
+ >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " +
1351
+ ... rf"$\Delta t = {SFT.delta_t:g}\,$s)",
1352
+ ... ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " +
1353
+ ... rf"$\Delta f = {SFT.delta_f:g}\,$Hz)",
1354
+ ... xlim=(t_lo, t_hi))
1355
+ >>> Sx_dB = 10 * np.log10(np.fmax(Sx2, 1e-4)) # limit range to -40 dB
1356
+ >>> im1 = ax1.imshow(Sx_dB, origin='lower', aspect='auto',
1357
+ ... extent=SFT.extent(N), cmap='magma')
1358
+ >>> ax1.plot(t_x, f_i, 'g--', alpha=.5, label='$f_i(t)$')
1359
+ >>> fig1.colorbar(im1, label='Power Spectral Density ' +
1360
+ ... r"$20\,\log_{10}|S_x(t, f)|$ in dB")
1361
+ ...
1362
+ >>> # Shade areas where window slices stick out to the side:
1363
+ >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T),
1364
+ ... (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]:
1365
+ ... ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.3)
1366
+ >>> for t_ in [0, N * SFT.T]: # mark signal borders with vertical line
1367
+ ... ax1.axvline(t_, color='c', linestyle='--', alpha=0.5)
1368
+ >>> ax1.legend()
1369
+ >>> fig1.tight_layout()
1370
+ >>> plt.show()
1371
+
1372
+ The logarithmic scaling reveals the odd harmonics of the square wave,
1373
+ which are reflected at the Nyquist frequency of 10 Hz. This aliasing
1374
+ is also the main source of the noise artifacts in the plot.
1375
+
1376
+ See Also
1377
+ --------
1378
+ :meth:`~ShortTimeFFT.stft`: Perform the short-time Fourier transform.
1379
+ stft_detrend: STFT with a trend subtracted from each segment.
1380
+ :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
1381
+ """
1382
+ Sx = self.stft_detrend(x, detr, p0, p1, k_offset=k_offset,
1383
+ padding=padding, axis=axis)
1384
+ if y is None or y is x: # do spectrogram:
1385
+ return Sx.real**2 + Sx.imag**2
1386
+ # Cross-spectrogram:
1387
+ Sy = self.stft_detrend(y, detr, p0, p1, k_offset=k_offset,
1388
+ padding=padding, axis=axis)
1389
+ return Sx * Sy.conj()
1390
+
1391
+ @property
1392
+ def dual_win(self) -> np.ndarray:
1393
+ """Dual window (canonical dual window by default).
1394
+
1395
+ A STFT can be interpreted as the input signal being expressed as a
1396
+ weighted sum of modulated and time-shifted dual windows. If no dual window is
1397
+ given on instantiation, the canonical dual window, i.e., the window with the
1398
+ minimal energy (i.e., minimal L²-norm) is calculated. Alternative means for
1399
+ determining dual windows are provided by `closest_STFT_dual_window` and the
1400
+ `from_win_equals_dual` class-method. Note that `win` is also always a
1401
+ dual window of `dual_win`.
1402
+
1403
+ `dual_win` has same length as `win`, namely `m_num` samples.
1404
+
1405
+ If the dual window cannot be calculated a ``ValueError`` is raised.
1406
+ This attribute is read only and calculated lazily.
1407
+ To make this array immutable, its WRITEABLE flag is set to ``FALSE``.
1408
+
1409
+ See Also
1410
+ --------
1411
+ m_num: Number of samples in window `win` and `dual_win`.
1412
+ win: Window function as real- or complex-valued 1d array.
1413
+ from_win_equals_dual: Create instance where `win` and `dual_win` are equal.
1414
+ closest_STFT_dual_window: Calculate dual window closest to a desired window.
1415
+ numpy.ndarray.setflags: Modify array flags.
1416
+ ShortTimeFFT: Class this property belongs to.
1417
+ """
1418
+ if self._dual_win is None:
1419
+ self._dual_win = _calc_dual_canonical_window(self.win, self.hop)
1420
+ self.dual_win.setflags(write=False)
1421
+ return self._dual_win
1422
+
1423
+ @property
1424
+ def invertible(self) -> bool:
1425
+ """Check if STFT is invertible.
1426
+
1427
+ This is achieved by trying to calculate the canonical dual window.
1428
+
1429
+ See Also
1430
+ --------
1431
+ :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
1432
+ m_num: Number of samples in window `win` and `dual_win`.
1433
+ dual_win: Dual window.
1434
+ win: Window for STFT.
1435
+ ShortTimeFFT: Class this property belongs to.
1436
+ """
1437
+ try:
1438
+ return len(self.dual_win) > 0 # call self.dual_win()
1439
+ except ValueError:
1440
+ return False
1441
+
1442
+ def istft(self, S: np.ndarray, k0: int = 0, k1: int | None = None, *,
1443
+ f_axis: int = -2, t_axis: int = -1) \
1444
+ -> np.ndarray:
1445
+ """Inverse short-time Fourier transform.
1446
+
1447
+ It returns an array of dimension ``S.ndim - 1`` which is real
1448
+ if `onesided_fft` is set, else complex. If the STFT is not
1449
+ `invertible`, or the parameters are out of bounds a ``ValueError`` is
1450
+ raised.
1451
+
1452
+ Parameters
1453
+ ----------
1454
+ S
1455
+ A complex valued array where `f_axis` denotes the frequency
1456
+ values and the `t-axis` dimension the temporal values of the
1457
+ STFT values.
1458
+ k0, k1
1459
+ The start and the end index of the reconstructed signal. The
1460
+ default (``k0 = 0``, ``k1 = None``) assumes that the maximum length
1461
+ signal should be reconstructed.
1462
+ f_axis, t_axis
1463
+ The axes in `S` denoting the frequency and the time dimension.
1464
+
1465
+ Notes
1466
+ -----
1467
+ It is required that `S` has `f_pts` entries along the `f_axis`. For
1468
+ the `t_axis` it is assumed that the first entry corresponds to
1469
+ `p_min` * `delta_t` (being <= 0). The length of `t_axis` needs to be
1470
+ compatible with `k1`. I.e., ``S.shape[t_axis] >= self.p_max(k1)`` must
1471
+ hold, if `k1` is not ``None``. Else `k1` is set to `k_max` with::
1472
+
1473
+ q_max = S.shape[t_range] + self.p_min
1474
+ k_max = (q_max - 1) * self.hop + self.m_num - self.m_num_mid
1475
+
1476
+ The :ref:`tutorial_stft` section of the :ref:`user_guide` discussed the
1477
+ slicing behavior by means of an example.
1478
+
1479
+ See Also
1480
+ --------
1481
+ invertible: Check if STFT is invertible.
1482
+ :meth:`~ShortTimeFFT.stft`: Perform Short-time Fourier transform.
1483
+ :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
1484
+ """
1485
+ if f_axis == t_axis:
1486
+ raise ValueError(f"{f_axis=} may not be equal to {t_axis=}!")
1487
+ if S.shape[f_axis] != self.f_pts:
1488
+ raise ValueError(f"{S.shape[f_axis]=} must be equal to " +
1489
+ f"{self.f_pts=} ({S.shape=})!")
1490
+ n_min = self.m_num-self.m_num_mid # minimum signal length
1491
+ if not (S.shape[t_axis] >= (q_num := self.p_num(n_min))):
1492
+ raise ValueError(f"{S.shape[t_axis]=} needs to have at least " +
1493
+ f"{q_num} slices ({S.shape=})!")
1494
+ if t_axis != S.ndim - 1 or f_axis != S.ndim - 2:
1495
+ t_axis = S.ndim + t_axis if t_axis < 0 else t_axis
1496
+ f_axis = S.ndim + f_axis if f_axis < 0 else f_axis
1497
+ S = np.moveaxis(S, (f_axis, t_axis), (-2, -1))
1498
+
1499
+ q_max = S.shape[-1] + self.p_min
1500
+ k_max = (q_max - 1) * self.hop + self.m_num - self.m_num_mid
1501
+
1502
+ k1 = k_max if k1 is None else k1
1503
+ if not (self.k_min <= k0 < k1 <= k_max):
1504
+ raise ValueError(f"({self.k_min=}) <= ({k0=}) < ({k1=}) <= " +
1505
+ f"({k_max=}) is false!")
1506
+ if not (num_pts := k1 - k0) >= n_min:
1507
+ raise ValueError(f"({k1=}) - ({k0=}) = {num_pts} has to be at " +
1508
+ f"least the half the window length {n_min}!")
1509
+
1510
+ q0 = (k0 // self.hop + self.p_min if k0 >= 0 else # p_min always <= 0
1511
+ k0 // self.hop)
1512
+ q1 = min(self.p_max(k1), q_max)
1513
+ k_q0, k_q1 = self.nearest_k_p(k0), self.nearest_k_p(k1, left=False)
1514
+ n_pts = k_q1 - k_q0 + self.m_num - self.m_num_mid
1515
+ x = np.zeros(S.shape[:-2] + (n_pts,),
1516
+ dtype=float if self.onesided_fft else complex)
1517
+ for q_ in range(q0, q1):
1518
+ xs = self._ifft_func(S[..., :, q_ - self.p_min]) * self.dual_win
1519
+ i0 = q_ * self.hop - self.m_num_mid
1520
+ i1 = min(i0 + self.m_num, n_pts+k0)
1521
+ j0, j1 = 0, i1 - i0
1522
+ if i0 < k0: # xs sticks out to the left on x:
1523
+ j0 += k0 - i0
1524
+ i0 = k0
1525
+ x[..., i0-k0:i1-k0] += xs[..., j0:j1]
1526
+ x = x[..., :k1-k0]
1527
+ if x.ndim > 1:
1528
+ x = np.moveaxis(x, -1, f_axis if f_axis < x.ndim else t_axis)
1529
+ return x
1530
+
1531
+ @property
1532
+ def fac_magnitude(self) -> float:
1533
+ """Factor to multiply the STFT values by to scale each frequency slice
1534
+ to a magnitude spectrum.
1535
+
1536
+ It is 1 if attribute ``scaling == 'magnitude'``.
1537
+ The window can be scaled to a magnitude spectrum by using the method
1538
+ `scale_to`.
1539
+
1540
+ See Also
1541
+ --------
1542
+ fac_psd: Scaling factor for to a power spectral density spectrum.
1543
+ scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
1544
+ scaling: Normalization applied to the window function.
1545
+ ShortTimeFFT: Class this property belongs to.
1546
+ """
1547
+ if self.scaling == 'magnitude':
1548
+ return 1
1549
+ if self._fac_mag is None:
1550
+ self._fac_mag = 1 / abs(sum(self.win))
1551
+ return self._fac_mag
1552
+
1553
+ @property
1554
+ def fac_psd(self) -> float:
1555
+ """Factor to multiply the STFT values by to scale each frequency slice
1556
+ to a power spectral density (PSD).
1557
+
1558
+ It is 1 if attribute ``scaling == 'psd'``.
1559
+ The window can be scaled to a psd spectrum by using the method
1560
+ `scale_to`.
1561
+
1562
+ See Also
1563
+ --------
1564
+ fac_magnitude: Scaling factor for to a magnitude spectrum.
1565
+ scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
1566
+ scaling: Normalization applied to the window function.
1567
+ ShortTimeFFT: Class this property belongs to.
1568
+ """
1569
+ if self.scaling == 'psd':
1570
+ return 1
1571
+ if self._fac_psd is None:
1572
+ self._fac_psd = 1 / np.sqrt(
1573
+ sum(self.win.real**2+self.win.imag**2) / self.T)
1574
+ return self._fac_psd
1575
+
1576
+ @property
1577
+ def m_num(self) -> int:
1578
+ """Number of samples in window `win`.
1579
+
1580
+ Note that the FFT can be oversampled by zero-padding. This is achieved
1581
+ by setting the `mfft` property.
1582
+
1583
+ See Also
1584
+ --------
1585
+ m_num_mid: Center index of window `win`.
1586
+ mfft: Length of input for the FFT used - may be larger than `m_num`.
1587
+ hop: Time increment in signal samples for sliding window.
1588
+ win: Window function as real- or complex-valued 1d array.
1589
+ ShortTimeFFT: Class this property belongs to.
1590
+ """
1591
+ return len(self.win)
1592
+
1593
+ @property
1594
+ def m_num_mid(self) -> int:
1595
+ """Center index of window `win`.
1596
+
1597
+ For odd `m_num`, ``(m_num - 1) / 2`` is returned and
1598
+ for even `m_num` (per definition) ``m_num / 2`` is returned.
1599
+
1600
+ See Also
1601
+ --------
1602
+ m_num: Number of samples in window `win`.
1603
+ mfft: Length of input for the FFT used - may be larger than `m_num`.
1604
+ hop: ime increment in signal samples for sliding window.
1605
+ win: Window function as real- or complex-valued 1d array.
1606
+ ShortTimeFFT: Class this property belongs to.
1607
+ """
1608
+ return self.m_num // 2
1609
+
1610
+ @cache
1611
+ def _pre_padding(self) -> tuple[int, int]:
1612
+ """Smallest signal index and slice index due to padding.
1613
+
1614
+ Since, per convention, for time t=0, n,q is zero, the returned values
1615
+ are negative or zero.
1616
+ """
1617
+ w2 = self.win.real**2 + self.win.imag**2
1618
+ # move window to the left until the overlap with t >= 0 vanishes:
1619
+ n0 = -self.m_num_mid
1620
+ for q_, n_ in enumerate(range(n0, n0-self.m_num-1, -self.hop)):
1621
+ n_next = n_ - self.hop
1622
+ if n_next + self.m_num <= 0 or all(w2[n_next:] == 0):
1623
+ return n_, -q_
1624
+ raise RuntimeError("This is code line should not have been reached!")
1625
+ # If this case is reached, it probably means the first slice should be
1626
+ # returned, i.e.: return n0, 0
1627
+
1628
+ @property
1629
+ def k_min(self) -> int:
1630
+ """The smallest possible signal index of the STFT.
1631
+
1632
+ `k_min` is the index of the left-most non-zero value of the lowest
1633
+ slice `p_min`. Since the zeroth slice is centered over the zeroth
1634
+ sample of the input signal, `k_min` is never positive.
1635
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1636
+ section of the :ref:`user_guide`.
1637
+
1638
+ See Also
1639
+ --------
1640
+ k_max: First sample index after signal end not touched by a time slice.
1641
+ lower_border_end: Where pre-padding effects end.
1642
+ p_min: The smallest possible slice index.
1643
+ p_max: Index of first non-overlapping upper time slice.
1644
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1645
+ p_range: Determine and validate slice index range.
1646
+ upper_border_begin: Where post-padding effects start.
1647
+ ShortTimeFFT: Class this property belongs to.
1648
+ """
1649
+ return self._pre_padding()[0]
1650
+
1651
+ @property
1652
+ def p_min(self) -> int:
1653
+ """The smallest possible slice index.
1654
+
1655
+ `p_min` is the index of the left-most slice, where the window still
1656
+ sticks into the signal, i.e., has non-zero part for t >= 0.
1657
+ `k_min` is the smallest index where the window function of the slice
1658
+ `p_min` is non-zero.
1659
+
1660
+ Since, per convention the zeroth slice is centered at t=0,
1661
+ `p_min` <= 0 always holds.
1662
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1663
+ section of the :ref:`user_guide`.
1664
+
1665
+ See Also
1666
+ --------
1667
+ k_min: The smallest possible signal index.
1668
+ k_max: First sample index after signal end not touched by a time slice.
1669
+ p_max: Index of first non-overlapping upper time slice.
1670
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1671
+ p_range: Determine and validate slice index range.
1672
+ ShortTimeFFT: Class this property belongs to.
1673
+ """
1674
+ return self._pre_padding()[1]
1675
+
1676
+ @lru_cache(maxsize=256)
1677
+ def _post_padding(self, n: int) -> tuple[int, int]:
1678
+ """Largest signal index and slice index due to padding.
1679
+
1680
+ Parameters
1681
+ ----------
1682
+ n : int
1683
+ Number of samples of input signal (must be ≥ half of the window length).
1684
+ """
1685
+ if not (n >= (m2p := self.m_num - self.m_num_mid)):
1686
+ raise ValueError(f"Parameter n must be >= ceil(m_num/2) = {m2p}!")
1687
+ w2 = self.win.real**2 + self.win.imag**2
1688
+ # move window to the right until the overlap for t < t[n] vanishes:
1689
+ q1 = n // self.hop # last slice index with t[p1] <= t[n]
1690
+ k1 = q1 * self.hop - self.m_num_mid
1691
+ for q_, k_ in enumerate(range(k1, n+self.m_num, self.hop), start=q1):
1692
+ n_next = k_ + self.hop
1693
+ if n_next >= n or all(w2[:n-n_next] == 0):
1694
+ return k_ + self.m_num, q_ + 1
1695
+ raise RuntimeError("This is code line should not have been reached!")
1696
+ # If this case is reached, it probably means the last slice should be
1697
+ # returned, i.e.: return k1 + self.m_num - self.m_num_mid, q1 + 1
1698
+
1699
+ def k_max(self, n: int) -> int:
1700
+ """First sample index after signal end not touched by a time slice.
1701
+
1702
+ `k_max` - 1 is the largest sample index of the slice `p_max` for a
1703
+ given input signal of `n` samples.
1704
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1705
+ section of the :ref:`user_guide`.
1706
+
1707
+ Parameters
1708
+ ----------
1709
+ n : int
1710
+ Number of samples of input signal (must be ≥ half of the window length).
1711
+
1712
+ See Also
1713
+ --------
1714
+ k_min: The smallest possible signal index.
1715
+ p_min: The smallest possible slice index.
1716
+ p_max: Index of first non-overlapping upper time slice.
1717
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1718
+ p_range: Determine and validate slice index range.
1719
+ ShortTimeFFT: Class this method belongs to.
1720
+ """
1721
+ return self._post_padding(n)[0]
1722
+
1723
+ def p_max(self, n: int) -> int:
1724
+ """Index of first non-overlapping upper time slice for `n` sample
1725
+ input.
1726
+
1727
+ Note that center point t[p_max] = (p_max(n)-1) * `delta_t` is typically
1728
+ larger than last time index t[n-1] == (`n`-1) * `T`. The upper border
1729
+ of samples indexes covered by the window slices is given by `k_max`.
1730
+ Furthermore, `p_max` does not denote the number of slices `p_num` since
1731
+ `p_min` is typically less than zero.
1732
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1733
+ section of the :ref:`user_guide`.
1734
+
1735
+ See Also
1736
+ --------
1737
+ k_min: The smallest possible signal index.
1738
+ k_max: First sample index after signal end not touched by a time slice.
1739
+ p_min: The smallest possible slice index.
1740
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1741
+ p_range: Determine and validate slice index range.
1742
+ ShortTimeFFT: Class this method belongs to.
1743
+ """
1744
+ return self._post_padding(n)[1]
1745
+
1746
+ def p_num(self, n: int) -> int:
1747
+ """Number of time slices for an input signal with `n` samples.
1748
+
1749
+ It is given by `p_num` = `p_max` - `p_min` with `p_min` typically
1750
+ being negative.
1751
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1752
+ section of the :ref:`user_guide`.
1753
+
1754
+ See Also
1755
+ --------
1756
+ k_min: The smallest possible signal index.
1757
+ k_max: First sample index after signal end not touched by a time slice.
1758
+ lower_border_end: Where pre-padding effects end.
1759
+ p_min: The smallest possible slice index.
1760
+ p_max: Index of first non-overlapping upper time slice.
1761
+ p_range: Determine and validate slice index range.
1762
+ upper_border_begin: Where post-padding effects start.
1763
+ ShortTimeFFT: Class this method belongs to.
1764
+ """
1765
+ return self.p_max(n) - self.p_min
1766
+
1767
+ @property
1768
+ def lower_border_end(self) -> tuple[int, int]:
1769
+ """First signal index and first slice index unaffected by pre-padding.
1770
+
1771
+ Describes the point where the window does not stick out to the left
1772
+ of the signal domain.
1773
+ A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
1774
+ section of the :ref:`user_guide`.
1775
+
1776
+ See Also
1777
+ --------
1778
+ k_min: The smallest possible signal index.
1779
+ k_max: First sample index after signal end not touched by a time slice.
1780
+ lower_border_end: Where pre-padding effects end.
1781
+ p_min: The smallest possible slice index.
1782
+ p_max: Index of first non-overlapping upper time slice.
1783
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1784
+ p_range: Determine and validate slice index range.
1785
+ upper_border_begin: Where post-padding effects start.
1786
+ ShortTimeFFT: Class this property belongs to.
1787
+ """
1788
+ # not using @cache decorator due to MyPy limitations
1789
+ if self._lower_border_end is not None:
1790
+ return self._lower_border_end
1791
+
1792
+ # first non-zero element in self.win:
1793
+ m0 = np.flatnonzero(self.win.real**2 + self.win.imag**2)[0]
1794
+
1795
+ # move window to the right until does not stick out to the left:
1796
+ k0 = -self.m_num_mid + m0
1797
+ for q_, k_ in enumerate(range(k0, self.hop + 1, self.hop)):
1798
+ if k_ + self.hop >= 0: # next entry does not stick out anymore
1799
+ self._lower_border_end = (k_ + self.m_num, q_ + 1)
1800
+ return self._lower_border_end
1801
+ self._lower_border_end = (0, max(self.p_min, 0)) # ends at first slice
1802
+ return self._lower_border_end
1803
+
1804
+ @lru_cache(maxsize=256)
1805
+ def upper_border_begin(self, n: int) -> tuple[int, int]:
1806
+ """First signal index and first slice index affected by post-padding.
1807
+
1808
+ Describes the point where the window does begin stick out to the right
1809
+ of the signal domain.
1810
+ A detailed example is given :ref:`tutorial_stft_sliding_win` section
1811
+ of the :ref:`user_guide`.
1812
+
1813
+ Parameters
1814
+ ----------
1815
+ n : int
1816
+ Number of samples of input signal (must be ≥ half of the window length).
1817
+
1818
+ Returns
1819
+ -------
1820
+ k_ub : int
1821
+ Lowest signal index, where a touching time slice sticks out past the
1822
+ signal end.
1823
+ p_ub : int
1824
+ Lowest index of time slice of which the end sticks out past the signal end.
1825
+
1826
+ See Also
1827
+ --------
1828
+ k_min: The smallest possible signal index.
1829
+ k_max: First sample index after signal end not touched by a time slice.
1830
+ lower_border_end: Where pre-padding effects end.
1831
+ p_min: The smallest possible slice index.
1832
+ p_max: Index of first non-overlapping upper time slice.
1833
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1834
+ p_range: Determine and validate slice index range.
1835
+ ShortTimeFFT: Class this method belongs to.
1836
+ """
1837
+ if not (n >= (m2p := self.m_num - self.m_num_mid)):
1838
+ raise ValueError(f"Parameter n must be >= ceil(m_num/2) = {m2p}!")
1839
+ w2 = self.win.real**2 + self.win.imag**2
1840
+ q2 = n // self.hop + 1 # first t[q] >= t[n]
1841
+ q1 = max((n-self.m_num) // self.hop - 1, -1)
1842
+ # move window left until does not stick out to the right:
1843
+ for q_ in range(q2, q1, -1):
1844
+ k_ = q_ * self.hop + (self.m_num - self.m_num_mid)
1845
+ if k_ <= n or all(w2[n-k_:] == 0):
1846
+ return (q_ + 1) * self.hop - self.m_num_mid, q_ + 1
1847
+ return 0, 0 # border starts at first slice
1848
+
1849
+ @property
1850
+ def delta_t(self) -> float:
1851
+ """Time increment of STFT.
1852
+
1853
+ The time increment `delta_t` = `T` * `hop` represents the sample
1854
+ increment `hop` converted to time based on the sampling interval `T`.
1855
+
1856
+ See Also
1857
+ --------
1858
+ delta_f: Width of the frequency bins of the STFT.
1859
+ hop: Hop size in signal samples for sliding window.
1860
+ t: Times of STFT for an input signal with `n` samples.
1861
+ T: Sampling interval of input signal and window `win`.
1862
+ ShortTimeFFT: Class this property belongs to
1863
+ """
1864
+ return self.T * self.hop
1865
+
1866
+ def p_range(self, n: int, p0: int | None = None,
1867
+ p1: int | None = None) -> tuple[int, int]:
1868
+ """Determine and validate slice index range.
1869
+
1870
+ Parameters
1871
+ ----------
1872
+ n : int
1873
+ Number of samples of input signal, assuming t[0] = 0.
1874
+ p0 : int | None
1875
+ First slice index. If 0 then the first slice is centered at t = 0.
1876
+ If ``None`` then `p_min` is used. Note that p0 may be < 0 if
1877
+ slices are left of t = 0.
1878
+ p1 : int | None
1879
+ End of interval (last value is p1-1).
1880
+ If ``None`` then `p_max(n)` is used.
1881
+
1882
+
1883
+ Returns
1884
+ -------
1885
+ p0_ : int
1886
+ The fist slice index
1887
+ p1_ : int
1888
+ End of interval (last value is p1-1).
1889
+
1890
+ Notes
1891
+ -----
1892
+ A ``ValueError`` is raised if ``p_min <= p0 < p1 <= p_max(n)`` does not
1893
+ hold.
1894
+
1895
+ See Also
1896
+ --------
1897
+ k_min: The smallest possible signal index.
1898
+ k_max: First sample index after signal end not touched by a time slice.
1899
+ lower_border_end: Where pre-padding effects end.
1900
+ p_min: The smallest possible slice index.
1901
+ p_max: Index of first non-overlapping upper time slice.
1902
+ p_num: Number of time slices, i.e., `p_max` - `p_min`.
1903
+ upper_border_begin: Where post-padding effects start.
1904
+ ShortTimeFFT: Class this property belongs to.
1905
+ """
1906
+ p_max = self.p_max(n) # shorthand
1907
+ p0_ = self.p_min if p0 is None else p0
1908
+ p1_ = p_max if p1 is None else p1
1909
+ if not (self.p_min <= p0_ < p1_ <= p_max):
1910
+ raise ValueError(f"Invalid Parameter {p0=}, {p1=}, i.e., " +
1911
+ f"{self.p_min=} <= p0 < p1 <= {p_max=} " +
1912
+ f"does not hold for signal length {n=}!")
1913
+ return p0_, p1_
1914
+
1915
+ @lru_cache(maxsize=1)
1916
+ def t(self, n: int, p0: int | None = None, p1: int | None = None,
1917
+ k_offset: int = 0) -> np.ndarray:
1918
+ """Times of STFT for an input signal with `n` samples.
1919
+
1920
+ Returns a 1d array with times of the `~ShortTimeFFT.stft` values with
1921
+ the same parametrization. Note that the slices are
1922
+ ``delta_t = hop * T`` time units apart.
1923
+
1924
+ Parameters
1925
+ ----------
1926
+ n
1927
+ Number of sample of the input signal.
1928
+ p0
1929
+ The first element of the range of slices to calculate. If ``None``
1930
+ then it is set to :attr:`p_min`, which is the smallest possible
1931
+ slice.
1932
+ p1
1933
+ The end of the array. If ``None`` then `p_max(n)` is used.
1934
+ k_offset
1935
+ Index of first sample (t = 0) in `x`.
1936
+
1937
+
1938
+ See Also
1939
+ --------
1940
+ delta_t: Time increment of STFT (``hop*T``)
1941
+ hop: Time increment in signal samples for sliding window.
1942
+ nearest_k_p: Nearest sample index k_p for which t[k_p] == t[p] holds.
1943
+ T: Sampling interval of input signal and of the window (``1/fs``).
1944
+ fs: Sampling frequency (being ``1/T``)
1945
+ ShortTimeFFT: Class this method belongs to.
1946
+ """
1947
+ p0, p1 = self.p_range(n, p0, p1)
1948
+ return np.arange(p0, p1) * self.delta_t + k_offset * self.T
1949
+
1950
+ def nearest_k_p(self, k: int, left: bool = True) -> int:
1951
+ """Return nearest sample index k_p for which t[k_p] == t[p] holds.
1952
+
1953
+ The nearest next smaller time sample p (where t[p] is the center
1954
+ position of the window of the p-th slice) is p_k = k // `hop`.
1955
+ If `hop` is a divisor of `k` then `k` is returned.
1956
+ If `left` is set then p_k * `hop` is returned else (p_k+1) * `hop`.
1957
+
1958
+ This method can be used to slice an input signal into chunks for
1959
+ calculating the STFT and iSTFT incrementally.
1960
+
1961
+ See Also
1962
+ --------
1963
+ delta_t: Time increment of STFT (``hop*T``)
1964
+ hop: Time increment in signal samples for sliding window.
1965
+ T: Sampling interval of input signal and of the window (``1/fs``).
1966
+ fs: Sampling frequency (being ``1/T``)
1967
+ t: Times of STFT for an input signal with `n` samples.
1968
+ ShortTimeFFT: Class this method belongs to.
1969
+ """
1970
+ p_q, remainder = divmod(k, self.hop)
1971
+ if remainder == 0:
1972
+ return k
1973
+ return p_q * self.hop if left else (p_q + 1) * self.hop
1974
+
1975
+ @property
1976
+ def delta_f(self) -> float:
1977
+ """Width of the frequency bins of the STFT.
1978
+
1979
+ Return the frequency interval `delta_f` = 1 / (`mfft` * `T`).
1980
+
1981
+ See Also
1982
+ --------
1983
+ delta_t: Time increment of STFT.
1984
+ f_pts: Number of points along the frequency axis.
1985
+ f: Frequencies values of the STFT.
1986
+ mfft: Length of the input for FFT used.
1987
+ T: Sampling interval.
1988
+ t: Times of STFT for an input signal with `n` samples.
1989
+ ShortTimeFFT: Class this property belongs to.
1990
+ """
1991
+ return 1 / (self.mfft * self.T)
1992
+
1993
+ @property
1994
+ def f_pts(self) -> int:
1995
+ """Number of points along the frequency axis.
1996
+
1997
+ See Also
1998
+ --------
1999
+ delta_f: Width of the frequency bins of the STFT.
2000
+ f: Frequencies values of the STFT.
2001
+ mfft: Length of the input for FFT used.
2002
+ ShortTimeFFT: Class this property belongs to.
2003
+ """
2004
+ return self.mfft // 2 + 1 if self.onesided_fft else self.mfft
2005
+
2006
+ @property
2007
+ def onesided_fft(self) -> bool:
2008
+ """Return True if a one-sided FFT is used.
2009
+
2010
+ Returns ``True`` if `fft_mode` is either 'onesided' or 'onesided2X'.
2011
+
2012
+ See Also
2013
+ --------
2014
+ fft_mode: Utilized FFT ('twosided', 'centered', 'onesided' or
2015
+ 'onesided2X')
2016
+ ShortTimeFFT: Class this property belongs to.
2017
+ """
2018
+ return self.fft_mode in {'onesided', 'onesided2X'}
2019
+
2020
+ @property
2021
+ def f(self) -> np.ndarray:
2022
+ """Frequencies values of the STFT.
2023
+
2024
+ A 1d array of length `f_pts` with `delta_f` spaced entries is returned.
2025
+
2026
+ See Also
2027
+ --------
2028
+ delta_f: Width of the frequency bins of the STFT.
2029
+ f_pts: Number of points along the frequency axis.
2030
+ mfft: Length of the input for FFT used.
2031
+ ShortTimeFFT: Class this property belongs to.
2032
+ """
2033
+ if self.fft_mode in {'onesided', 'onesided2X'}:
2034
+ return fft_lib.rfftfreq(self.mfft, self.T)
2035
+ elif self.fft_mode == 'twosided':
2036
+ return fft_lib.fftfreq(self.mfft, self.T)
2037
+ elif self.fft_mode == 'centered':
2038
+ return fft_lib.fftshift(fft_lib.fftfreq(self.mfft, self.T))
2039
+ # This should never happen but makes the Linters happy:
2040
+ fft_modes = get_args(FFT_MODE_TYPE)
2041
+ raise RuntimeError(f"{self.fft_mode=} not in {fft_modes}!")
2042
+
2043
+ def _fft_func(self, x: np.ndarray) -> np.ndarray:
2044
+ """FFT based on the `fft_mode`, `mfft`, `scaling` and `phase_shift`
2045
+ attributes.
2046
+
2047
+ For multidimensional arrays the transformation is carried out on the
2048
+ last axis.
2049
+ """
2050
+ if self.phase_shift is not None:
2051
+ if x.shape[-1] < self.mfft: # zero pad if needed
2052
+ z_shape = list(x.shape)
2053
+ z_shape[-1] = self.mfft - x.shape[-1]
2054
+ x = np.hstack((x, np.zeros(z_shape, dtype=x.dtype)))
2055
+ p_s = (self.phase_shift + self.m_num_mid) % self.m_num
2056
+ x = np.roll(x, -p_s, axis=-1)
2057
+
2058
+ if self.fft_mode == 'twosided':
2059
+ return fft_lib.fft(x, n=self.mfft, axis=-1)
2060
+ if self.fft_mode == 'centered':
2061
+ return fft_lib.fftshift(fft_lib.fft(x, self.mfft, axis=-1), axes=-1)
2062
+ if self.fft_mode == 'onesided':
2063
+ return fft_lib.rfft(x, n=self.mfft, axis=-1)
2064
+ if self.fft_mode == 'onesided2X':
2065
+ X = fft_lib.rfft(x, n=self.mfft, axis=-1)
2066
+ # Either squared magnitude (psd) or magnitude is doubled:
2067
+ fac = np.sqrt(2) if self.scaling == 'psd' else 2
2068
+ # For even input length, the last entry is unpaired:
2069
+ X[..., 1: -1 if self.mfft % 2 == 0 else None] *= fac
2070
+ return X
2071
+ # This should never happen but makes the Linter happy:
2072
+ fft_modes = get_args(FFT_MODE_TYPE)
2073
+ raise RuntimeError(f"{self.fft_mode=} not in {fft_modes}!")
2074
+
2075
+ def _ifft_func(self, X: np.ndarray) -> np.ndarray:
2076
+ """Inverse to `_fft_func`.
2077
+
2078
+ Returned is an array of length `m_num`. If the FFT is `onesided`
2079
+ then a float array is returned else a complex array is returned.
2080
+ For multidimensional arrays the transformation is carried out on the
2081
+ last axis.
2082
+ """
2083
+ if self.fft_mode == 'twosided':
2084
+ x = fft_lib.ifft(X, n=self.mfft, axis=-1)
2085
+ elif self.fft_mode == 'centered':
2086
+ x = fft_lib.ifft(fft_lib.ifftshift(X, axes=-1), n=self.mfft, axis=-1)
2087
+ elif self.fft_mode == 'onesided':
2088
+ x = fft_lib.irfft(X, n=self.mfft, axis=-1)
2089
+ elif self.fft_mode == 'onesided2X':
2090
+ Xc = X.copy() # we do not want to modify function parameters
2091
+ fac = np.sqrt(2) if self.scaling == 'psd' else 2
2092
+ # For even length X the last value is not paired with a negative
2093
+ # value on the two-sided FFT:
2094
+ q1 = -1 if self.mfft % 2 == 0 else None
2095
+ Xc[..., 1:q1] /= fac
2096
+ x = fft_lib.irfft(Xc, n=self.mfft, axis=-1)
2097
+ else: # This should never happen but makes the Linter happy:
2098
+ error_str = f"{self.fft_mode=} not in {get_args(FFT_MODE_TYPE)}!"
2099
+ raise RuntimeError(error_str)
2100
+
2101
+ if self.phase_shift is None:
2102
+ return x[..., :self.m_num]
2103
+ p_s = (self.phase_shift + self.m_num_mid) % self.m_num
2104
+ return np.roll(x, p_s, axis=-1)[..., :self.m_num]
2105
+
2106
+ def extent(self, n: int, axes_seq: Literal['tf', 'ft'] = 'tf',
2107
+ center_bins: bool = False) -> tuple[float, float, float, float]:
2108
+ """Return minimum and maximum values time-frequency values.
2109
+
2110
+ A tuple with four floats ``(t0, t1, f0, f1)`` for 'tf' and
2111
+ ``(f0, f1, t0, t1)`` for 'ft' is returned describing the corners
2112
+ of the time-frequency domain of the `~ShortTimeFFT.stft`.
2113
+ That tuple can be passed to `matplotlib.pyplot.imshow` as a parameter
2114
+ with the same name.
2115
+
2116
+ Parameters
2117
+ ----------
2118
+ n : int
2119
+ Number of samples in input signal.
2120
+ axes_seq : {'tf', 'ft'}
2121
+ Return time extent first and then frequency extent or vice versa.
2122
+ center_bins: bool
2123
+ If set (default ``False``), the values of the time slots and
2124
+ frequency bins are moved from the side the middle. This is useful,
2125
+ when plotting the `~ShortTimeFFT.stft` values as step functions,
2126
+ i.e., with no interpolation.
2127
+
2128
+ See Also
2129
+ --------
2130
+ :func:`matplotlib.pyplot.imshow`: Display data as an image.
2131
+ :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
2132
+
2133
+ Examples
2134
+ --------
2135
+ The following two plots illustrate the effect of the parameter `center_bins`:
2136
+ The grid lines represent the three time and the four frequency values of the
2137
+ STFT.
2138
+ The left plot, where ``(t0, t1, f0, f1) = (0, 3, 0, 4)`` is passed as parameter
2139
+ ``extent`` to `~matplotlib.pyplot.imshow`, shows the standard behavior of the
2140
+ time and frequency values being at the lower edge of the corrsponding bin.
2141
+ The right plot, with ``(t0, t1, f0, f1) = (-0.5, 2.5, -0.5, 3.5)``, shows that
2142
+ the bins are centered over the respective values when passing
2143
+ ``center_bins=True``.
2144
+
2145
+ >>> import matplotlib.pyplot as plt
2146
+ >>> import numpy as np
2147
+ >>> from scipy.signal import ShortTimeFFT
2148
+ ...
2149
+ >>> n, m = 12, 6
2150
+ >>> SFT = ShortTimeFFT.from_window('hann', fs=m, nperseg=m, noverlap=0)
2151
+ >>> Sxx = SFT.stft(np.cos(np.arange(n))) # produces a colorful plot
2152
+ ...
2153
+ >>> fig, axx = plt.subplots(1, 2, tight_layout=True, figsize=(6., 4.))
2154
+ >>> for ax_, center_bins in zip(axx, (False, True)):
2155
+ ... ax_.imshow(abs(Sxx), origin='lower', interpolation=None, aspect='equal',
2156
+ ... cmap='viridis', extent=SFT.extent(n, 'tf', center_bins))
2157
+ ... ax_.set_title(f"{center_bins=}")
2158
+ ... ax_.set_xlabel(f"Time ({SFT.p_num(n)} points, Δt={SFT.delta_t})")
2159
+ ... ax_.set_ylabel(f"Frequency ({SFT.f_pts} points, Δf={SFT.delta_f})")
2160
+ ... ax_.set_xticks(SFT.t(n)) # vertical grid line are timestamps
2161
+ ... ax_.set_yticks(SFT.f) # horizontal grid line are frequency values
2162
+ ... ax_.grid(True)
2163
+ >>> plt.show()
2164
+
2165
+ Note that the step-like behavior with the constant colors is caused by passing
2166
+ ``interpolation=None`` to `~matplotlib.pyplot.imshow`.
2167
+ """
2168
+ if axes_seq not in ('tf', 'ft'):
2169
+ raise ValueError(f"Parameter {axes_seq=} not in ['tf', 'ft']!")
2170
+
2171
+ if self.onesided_fft:
2172
+ q0, q1 = 0, self.f_pts
2173
+ elif self.fft_mode == 'centered':
2174
+ q0 = -(self.mfft // 2)
2175
+ q1 = self.mfft // 2 if self.mfft % 2 == 0 else self.mfft // 2 + 1
2176
+ else:
2177
+ raise ValueError(f"Attribute fft_mode={self.fft_mode} must be " +
2178
+ "in ['centered', 'onesided', 'onesided2X']")
2179
+
2180
+ p0, p1 = self.p_min, self.p_max(n) # shorthand
2181
+ if center_bins:
2182
+ t0, t1 = self.delta_t * (p0 - 0.5), self.delta_t * (p1 - 0.5)
2183
+ f0, f1 = self.delta_f * (q0 - 0.5), self.delta_f * (q1 - 0.5)
2184
+ else:
2185
+ t0, t1 = self.delta_t * p0, self.delta_t * p1
2186
+ f0, f1 = self.delta_f * q0, self.delta_f * q1
2187
+ return (t0, t1, f0, f1) if axes_seq == 'tf' else (f0, f1, t0, t1)