scipy 1.16.2__cp313-cp313-win_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1530) hide show
  1. scipy/__config__.py +161 -0
  2. scipy/__init__.py +150 -0
  3. scipy/_cyutility.cp313-win_arm64.lib +0 -0
  4. scipy/_cyutility.cp313-win_arm64.pyd +0 -0
  5. scipy/_distributor_init.py +18 -0
  6. scipy/_lib/__init__.py +14 -0
  7. scipy/_lib/_array_api.py +931 -0
  8. scipy/_lib/_array_api_compat_vendor.py +9 -0
  9. scipy/_lib/_array_api_no_0d.py +103 -0
  10. scipy/_lib/_bunch.py +229 -0
  11. scipy/_lib/_ccallback.py +251 -0
  12. scipy/_lib/_ccallback_c.cp313-win_arm64.lib +0 -0
  13. scipy/_lib/_ccallback_c.cp313-win_arm64.pyd +0 -0
  14. scipy/_lib/_disjoint_set.py +254 -0
  15. scipy/_lib/_docscrape.py +761 -0
  16. scipy/_lib/_elementwise_iterative_method.py +346 -0
  17. scipy/_lib/_fpumode.cp313-win_arm64.lib +0 -0
  18. scipy/_lib/_fpumode.cp313-win_arm64.pyd +0 -0
  19. scipy/_lib/_gcutils.py +105 -0
  20. scipy/_lib/_pep440.py +487 -0
  21. scipy/_lib/_sparse.py +41 -0
  22. scipy/_lib/_test_ccallback.cp313-win_arm64.lib +0 -0
  23. scipy/_lib/_test_ccallback.cp313-win_arm64.pyd +0 -0
  24. scipy/_lib/_test_deprecation_call.cp313-win_arm64.lib +0 -0
  25. scipy/_lib/_test_deprecation_call.cp313-win_arm64.pyd +0 -0
  26. scipy/_lib/_test_deprecation_def.cp313-win_arm64.lib +0 -0
  27. scipy/_lib/_test_deprecation_def.cp313-win_arm64.pyd +0 -0
  28. scipy/_lib/_testutils.py +373 -0
  29. scipy/_lib/_threadsafety.py +58 -0
  30. scipy/_lib/_tmpdirs.py +86 -0
  31. scipy/_lib/_uarray/LICENSE +29 -0
  32. scipy/_lib/_uarray/__init__.py +116 -0
  33. scipy/_lib/_uarray/_backend.py +707 -0
  34. scipy/_lib/_uarray/_uarray.cp313-win_arm64.lib +0 -0
  35. scipy/_lib/_uarray/_uarray.cp313-win_arm64.pyd +0 -0
  36. scipy/_lib/_util.py +1283 -0
  37. scipy/_lib/array_api_compat/__init__.py +22 -0
  38. scipy/_lib/array_api_compat/_internal.py +59 -0
  39. scipy/_lib/array_api_compat/common/__init__.py +1 -0
  40. scipy/_lib/array_api_compat/common/_aliases.py +727 -0
  41. scipy/_lib/array_api_compat/common/_fft.py +213 -0
  42. scipy/_lib/array_api_compat/common/_helpers.py +1058 -0
  43. scipy/_lib/array_api_compat/common/_linalg.py +232 -0
  44. scipy/_lib/array_api_compat/common/_typing.py +192 -0
  45. scipy/_lib/array_api_compat/cupy/__init__.py +13 -0
  46. scipy/_lib/array_api_compat/cupy/_aliases.py +156 -0
  47. scipy/_lib/array_api_compat/cupy/_info.py +336 -0
  48. scipy/_lib/array_api_compat/cupy/_typing.py +31 -0
  49. scipy/_lib/array_api_compat/cupy/fft.py +36 -0
  50. scipy/_lib/array_api_compat/cupy/linalg.py +49 -0
  51. scipy/_lib/array_api_compat/dask/__init__.py +0 -0
  52. scipy/_lib/array_api_compat/dask/array/__init__.py +12 -0
  53. scipy/_lib/array_api_compat/dask/array/_aliases.py +376 -0
  54. scipy/_lib/array_api_compat/dask/array/_info.py +416 -0
  55. scipy/_lib/array_api_compat/dask/array/fft.py +21 -0
  56. scipy/_lib/array_api_compat/dask/array/linalg.py +72 -0
  57. scipy/_lib/array_api_compat/numpy/__init__.py +28 -0
  58. scipy/_lib/array_api_compat/numpy/_aliases.py +190 -0
  59. scipy/_lib/array_api_compat/numpy/_info.py +366 -0
  60. scipy/_lib/array_api_compat/numpy/_typing.py +30 -0
  61. scipy/_lib/array_api_compat/numpy/fft.py +35 -0
  62. scipy/_lib/array_api_compat/numpy/linalg.py +143 -0
  63. scipy/_lib/array_api_compat/torch/__init__.py +22 -0
  64. scipy/_lib/array_api_compat/torch/_aliases.py +855 -0
  65. scipy/_lib/array_api_compat/torch/_info.py +369 -0
  66. scipy/_lib/array_api_compat/torch/_typing.py +3 -0
  67. scipy/_lib/array_api_compat/torch/fft.py +85 -0
  68. scipy/_lib/array_api_compat/torch/linalg.py +121 -0
  69. scipy/_lib/array_api_extra/__init__.py +38 -0
  70. scipy/_lib/array_api_extra/_delegation.py +171 -0
  71. scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
  72. scipy/_lib/array_api_extra/_lib/_at.py +463 -0
  73. scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
  74. scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
  75. scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
  76. scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
  77. scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
  78. scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
  79. scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
  80. scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
  81. scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
  82. scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
  83. scipy/_lib/array_api_extra/testing.py +359 -0
  84. scipy/_lib/cobyqa/__init__.py +20 -0
  85. scipy/_lib/cobyqa/framework.py +1240 -0
  86. scipy/_lib/cobyqa/main.py +1506 -0
  87. scipy/_lib/cobyqa/models.py +1529 -0
  88. scipy/_lib/cobyqa/problem.py +1296 -0
  89. scipy/_lib/cobyqa/settings.py +132 -0
  90. scipy/_lib/cobyqa/subsolvers/__init__.py +14 -0
  91. scipy/_lib/cobyqa/subsolvers/geometry.py +387 -0
  92. scipy/_lib/cobyqa/subsolvers/optim.py +1203 -0
  93. scipy/_lib/cobyqa/utils/__init__.py +18 -0
  94. scipy/_lib/cobyqa/utils/exceptions.py +22 -0
  95. scipy/_lib/cobyqa/utils/math.py +77 -0
  96. scipy/_lib/cobyqa/utils/versions.py +67 -0
  97. scipy/_lib/decorator.py +399 -0
  98. scipy/_lib/deprecation.py +274 -0
  99. scipy/_lib/doccer.py +366 -0
  100. scipy/_lib/messagestream.cp313-win_arm64.lib +0 -0
  101. scipy/_lib/messagestream.cp313-win_arm64.pyd +0 -0
  102. scipy/_lib/pyprima/__init__.py +212 -0
  103. scipy/_lib/pyprima/cobyla/__init__.py +0 -0
  104. scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
  105. scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
  106. scipy/_lib/pyprima/cobyla/geometry.py +226 -0
  107. scipy/_lib/pyprima/cobyla/initialize.py +215 -0
  108. scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
  109. scipy/_lib/pyprima/cobyla/update.py +289 -0
  110. scipy/_lib/pyprima/common/__init__.py +0 -0
  111. scipy/_lib/pyprima/common/_bounds.py +34 -0
  112. scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
  113. scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
  114. scipy/_lib/pyprima/common/_project.py +173 -0
  115. scipy/_lib/pyprima/common/checkbreak.py +93 -0
  116. scipy/_lib/pyprima/common/consts.py +47 -0
  117. scipy/_lib/pyprima/common/evaluate.py +99 -0
  118. scipy/_lib/pyprima/common/history.py +38 -0
  119. scipy/_lib/pyprima/common/infos.py +30 -0
  120. scipy/_lib/pyprima/common/linalg.py +435 -0
  121. scipy/_lib/pyprima/common/message.py +290 -0
  122. scipy/_lib/pyprima/common/powalg.py +131 -0
  123. scipy/_lib/pyprima/common/preproc.py +277 -0
  124. scipy/_lib/pyprima/common/present.py +5 -0
  125. scipy/_lib/pyprima/common/ratio.py +54 -0
  126. scipy/_lib/pyprima/common/redrho.py +47 -0
  127. scipy/_lib/pyprima/common/selectx.py +296 -0
  128. scipy/_lib/tests/__init__.py +0 -0
  129. scipy/_lib/tests/test__gcutils.py +110 -0
  130. scipy/_lib/tests/test__pep440.py +67 -0
  131. scipy/_lib/tests/test__testutils.py +32 -0
  132. scipy/_lib/tests/test__threadsafety.py +51 -0
  133. scipy/_lib/tests/test__util.py +641 -0
  134. scipy/_lib/tests/test_array_api.py +322 -0
  135. scipy/_lib/tests/test_bunch.py +169 -0
  136. scipy/_lib/tests/test_ccallback.py +196 -0
  137. scipy/_lib/tests/test_config.py +45 -0
  138. scipy/_lib/tests/test_deprecation.py +10 -0
  139. scipy/_lib/tests/test_doccer.py +143 -0
  140. scipy/_lib/tests/test_import_cycles.py +18 -0
  141. scipy/_lib/tests/test_public_api.py +482 -0
  142. scipy/_lib/tests/test_scipy_version.py +28 -0
  143. scipy/_lib/tests/test_tmpdirs.py +48 -0
  144. scipy/_lib/tests/test_warnings.py +137 -0
  145. scipy/_lib/uarray.py +31 -0
  146. scipy/cluster/__init__.py +31 -0
  147. scipy/cluster/_hierarchy.cp313-win_arm64.lib +0 -0
  148. scipy/cluster/_hierarchy.cp313-win_arm64.pyd +0 -0
  149. scipy/cluster/_optimal_leaf_ordering.cp313-win_arm64.lib +0 -0
  150. scipy/cluster/_optimal_leaf_ordering.cp313-win_arm64.pyd +0 -0
  151. scipy/cluster/_vq.cp313-win_arm64.lib +0 -0
  152. scipy/cluster/_vq.cp313-win_arm64.pyd +0 -0
  153. scipy/cluster/hierarchy.py +4348 -0
  154. scipy/cluster/tests/__init__.py +0 -0
  155. scipy/cluster/tests/hierarchy_test_data.py +145 -0
  156. scipy/cluster/tests/test_disjoint_set.py +202 -0
  157. scipy/cluster/tests/test_hierarchy.py +1238 -0
  158. scipy/cluster/tests/test_vq.py +434 -0
  159. scipy/cluster/vq.py +832 -0
  160. scipy/conftest.py +683 -0
  161. scipy/constants/__init__.py +358 -0
  162. scipy/constants/_codata.py +2266 -0
  163. scipy/constants/_constants.py +369 -0
  164. scipy/constants/codata.py +21 -0
  165. scipy/constants/constants.py +53 -0
  166. scipy/constants/tests/__init__.py +0 -0
  167. scipy/constants/tests/test_codata.py +78 -0
  168. scipy/constants/tests/test_constants.py +83 -0
  169. scipy/datasets/__init__.py +90 -0
  170. scipy/datasets/_download_all.py +71 -0
  171. scipy/datasets/_fetchers.py +225 -0
  172. scipy/datasets/_registry.py +26 -0
  173. scipy/datasets/_utils.py +81 -0
  174. scipy/datasets/tests/__init__.py +0 -0
  175. scipy/datasets/tests/test_data.py +128 -0
  176. scipy/differentiate/__init__.py +27 -0
  177. scipy/differentiate/_differentiate.py +1129 -0
  178. scipy/differentiate/tests/__init__.py +0 -0
  179. scipy/differentiate/tests/test_differentiate.py +694 -0
  180. scipy/fft/__init__.py +114 -0
  181. scipy/fft/_backend.py +196 -0
  182. scipy/fft/_basic.py +1650 -0
  183. scipy/fft/_basic_backend.py +197 -0
  184. scipy/fft/_debug_backends.py +22 -0
  185. scipy/fft/_fftlog.py +223 -0
  186. scipy/fft/_fftlog_backend.py +200 -0
  187. scipy/fft/_helper.py +348 -0
  188. scipy/fft/_pocketfft/LICENSE.md +25 -0
  189. scipy/fft/_pocketfft/__init__.py +9 -0
  190. scipy/fft/_pocketfft/basic.py +251 -0
  191. scipy/fft/_pocketfft/helper.py +249 -0
  192. scipy/fft/_pocketfft/pypocketfft.cp313-win_arm64.lib +0 -0
  193. scipy/fft/_pocketfft/pypocketfft.cp313-win_arm64.pyd +0 -0
  194. scipy/fft/_pocketfft/realtransforms.py +109 -0
  195. scipy/fft/_pocketfft/tests/__init__.py +0 -0
  196. scipy/fft/_pocketfft/tests/test_basic.py +1011 -0
  197. scipy/fft/_pocketfft/tests/test_real_transforms.py +505 -0
  198. scipy/fft/_realtransforms.py +706 -0
  199. scipy/fft/_realtransforms_backend.py +63 -0
  200. scipy/fft/tests/__init__.py +0 -0
  201. scipy/fft/tests/mock_backend.py +96 -0
  202. scipy/fft/tests/test_backend.py +98 -0
  203. scipy/fft/tests/test_basic.py +504 -0
  204. scipy/fft/tests/test_fftlog.py +215 -0
  205. scipy/fft/tests/test_helper.py +558 -0
  206. scipy/fft/tests/test_multithreading.py +84 -0
  207. scipy/fft/tests/test_real_transforms.py +247 -0
  208. scipy/fftpack/__init__.py +103 -0
  209. scipy/fftpack/_basic.py +428 -0
  210. scipy/fftpack/_helper.py +115 -0
  211. scipy/fftpack/_pseudo_diffs.py +554 -0
  212. scipy/fftpack/_realtransforms.py +598 -0
  213. scipy/fftpack/basic.py +20 -0
  214. scipy/fftpack/convolve.cp313-win_arm64.lib +0 -0
  215. scipy/fftpack/convolve.cp313-win_arm64.pyd +0 -0
  216. scipy/fftpack/helper.py +19 -0
  217. scipy/fftpack/pseudo_diffs.py +22 -0
  218. scipy/fftpack/realtransforms.py +19 -0
  219. scipy/fftpack/tests/__init__.py +0 -0
  220. scipy/fftpack/tests/fftw_double_ref.npz +0 -0
  221. scipy/fftpack/tests/fftw_longdouble_ref.npz +0 -0
  222. scipy/fftpack/tests/fftw_single_ref.npz +0 -0
  223. scipy/fftpack/tests/test.npz +0 -0
  224. scipy/fftpack/tests/test_basic.py +877 -0
  225. scipy/fftpack/tests/test_helper.py +54 -0
  226. scipy/fftpack/tests/test_import.py +33 -0
  227. scipy/fftpack/tests/test_pseudo_diffs.py +388 -0
  228. scipy/fftpack/tests/test_real_transforms.py +836 -0
  229. scipy/integrate/__init__.py +122 -0
  230. scipy/integrate/_bvp.py +1160 -0
  231. scipy/integrate/_cubature.py +729 -0
  232. scipy/integrate/_dop.cp313-win_arm64.lib +0 -0
  233. scipy/integrate/_dop.cp313-win_arm64.pyd +0 -0
  234. scipy/integrate/_ivp/__init__.py +8 -0
  235. scipy/integrate/_ivp/base.py +290 -0
  236. scipy/integrate/_ivp/bdf.py +478 -0
  237. scipy/integrate/_ivp/common.py +451 -0
  238. scipy/integrate/_ivp/dop853_coefficients.py +193 -0
  239. scipy/integrate/_ivp/ivp.py +755 -0
  240. scipy/integrate/_ivp/lsoda.py +224 -0
  241. scipy/integrate/_ivp/radau.py +572 -0
  242. scipy/integrate/_ivp/rk.py +601 -0
  243. scipy/integrate/_ivp/tests/__init__.py +0 -0
  244. scipy/integrate/_ivp/tests/test_ivp.py +1287 -0
  245. scipy/integrate/_ivp/tests/test_rk.py +37 -0
  246. scipy/integrate/_lebedev.py +5450 -0
  247. scipy/integrate/_lsoda.cp313-win_arm64.lib +0 -0
  248. scipy/integrate/_lsoda.cp313-win_arm64.pyd +0 -0
  249. scipy/integrate/_ode.py +1395 -0
  250. scipy/integrate/_odepack.cp313-win_arm64.lib +0 -0
  251. scipy/integrate/_odepack.cp313-win_arm64.pyd +0 -0
  252. scipy/integrate/_odepack_py.py +273 -0
  253. scipy/integrate/_quad_vec.py +674 -0
  254. scipy/integrate/_quadpack.cp313-win_arm64.lib +0 -0
  255. scipy/integrate/_quadpack.cp313-win_arm64.pyd +0 -0
  256. scipy/integrate/_quadpack_py.py +1283 -0
  257. scipy/integrate/_quadrature.py +1336 -0
  258. scipy/integrate/_rules/__init__.py +12 -0
  259. scipy/integrate/_rules/_base.py +518 -0
  260. scipy/integrate/_rules/_gauss_kronrod.py +202 -0
  261. scipy/integrate/_rules/_gauss_legendre.py +62 -0
  262. scipy/integrate/_rules/_genz_malik.py +210 -0
  263. scipy/integrate/_tanhsinh.py +1385 -0
  264. scipy/integrate/_test_multivariate.cp313-win_arm64.lib +0 -0
  265. scipy/integrate/_test_multivariate.cp313-win_arm64.pyd +0 -0
  266. scipy/integrate/_test_odeint_banded.cp313-win_arm64.lib +0 -0
  267. scipy/integrate/_test_odeint_banded.cp313-win_arm64.pyd +0 -0
  268. scipy/integrate/_vode.cp313-win_arm64.lib +0 -0
  269. scipy/integrate/_vode.cp313-win_arm64.pyd +0 -0
  270. scipy/integrate/dop.py +15 -0
  271. scipy/integrate/lsoda.py +15 -0
  272. scipy/integrate/odepack.py +17 -0
  273. scipy/integrate/quadpack.py +23 -0
  274. scipy/integrate/tests/__init__.py +0 -0
  275. scipy/integrate/tests/test__quad_vec.py +211 -0
  276. scipy/integrate/tests/test_banded_ode_solvers.py +305 -0
  277. scipy/integrate/tests/test_bvp.py +714 -0
  278. scipy/integrate/tests/test_cubature.py +1375 -0
  279. scipy/integrate/tests/test_integrate.py +840 -0
  280. scipy/integrate/tests/test_odeint_jac.py +74 -0
  281. scipy/integrate/tests/test_quadpack.py +680 -0
  282. scipy/integrate/tests/test_quadrature.py +730 -0
  283. scipy/integrate/tests/test_tanhsinh.py +1171 -0
  284. scipy/integrate/vode.py +15 -0
  285. scipy/interpolate/__init__.py +228 -0
  286. scipy/interpolate/_bary_rational.py +715 -0
  287. scipy/interpolate/_bsplines.py +2469 -0
  288. scipy/interpolate/_cubic.py +973 -0
  289. scipy/interpolate/_dfitpack.cp313-win_arm64.lib +0 -0
  290. scipy/interpolate/_dfitpack.cp313-win_arm64.pyd +0 -0
  291. scipy/interpolate/_dierckx.cp313-win_arm64.lib +0 -0
  292. scipy/interpolate/_dierckx.cp313-win_arm64.pyd +0 -0
  293. scipy/interpolate/_fitpack.cp313-win_arm64.lib +0 -0
  294. scipy/interpolate/_fitpack.cp313-win_arm64.pyd +0 -0
  295. scipy/interpolate/_fitpack2.py +2397 -0
  296. scipy/interpolate/_fitpack_impl.py +811 -0
  297. scipy/interpolate/_fitpack_py.py +898 -0
  298. scipy/interpolate/_fitpack_repro.py +996 -0
  299. scipy/interpolate/_interpnd.cp313-win_arm64.lib +0 -0
  300. scipy/interpolate/_interpnd.cp313-win_arm64.pyd +0 -0
  301. scipy/interpolate/_interpolate.py +2266 -0
  302. scipy/interpolate/_ndbspline.py +415 -0
  303. scipy/interpolate/_ndgriddata.py +329 -0
  304. scipy/interpolate/_pade.py +67 -0
  305. scipy/interpolate/_polyint.py +1025 -0
  306. scipy/interpolate/_ppoly.cp313-win_arm64.lib +0 -0
  307. scipy/interpolate/_ppoly.cp313-win_arm64.pyd +0 -0
  308. scipy/interpolate/_rbf.py +290 -0
  309. scipy/interpolate/_rbfinterp.py +550 -0
  310. scipy/interpolate/_rbfinterp_pythran.cp313-win_arm64.lib +0 -0
  311. scipy/interpolate/_rbfinterp_pythran.cp313-win_arm64.pyd +0 -0
  312. scipy/interpolate/_rgi.py +764 -0
  313. scipy/interpolate/_rgi_cython.cp313-win_arm64.lib +0 -0
  314. scipy/interpolate/_rgi_cython.cp313-win_arm64.pyd +0 -0
  315. scipy/interpolate/dfitpack.py +24 -0
  316. scipy/interpolate/fitpack.py +31 -0
  317. scipy/interpolate/fitpack2.py +29 -0
  318. scipy/interpolate/interpnd.py +24 -0
  319. scipy/interpolate/interpolate.py +30 -0
  320. scipy/interpolate/ndgriddata.py +23 -0
  321. scipy/interpolate/polyint.py +24 -0
  322. scipy/interpolate/rbf.py +18 -0
  323. scipy/interpolate/tests/__init__.py +0 -0
  324. scipy/interpolate/tests/data/bug-1310.npz +0 -0
  325. scipy/interpolate/tests/data/estimate_gradients_hang.npy +0 -0
  326. scipy/interpolate/tests/data/gcvspl.npz +0 -0
  327. scipy/interpolate/tests/test_bary_rational.py +368 -0
  328. scipy/interpolate/tests/test_bsplines.py +3754 -0
  329. scipy/interpolate/tests/test_fitpack.py +519 -0
  330. scipy/interpolate/tests/test_fitpack2.py +1431 -0
  331. scipy/interpolate/tests/test_gil.py +64 -0
  332. scipy/interpolate/tests/test_interpnd.py +452 -0
  333. scipy/interpolate/tests/test_interpolate.py +2630 -0
  334. scipy/interpolate/tests/test_ndgriddata.py +308 -0
  335. scipy/interpolate/tests/test_pade.py +107 -0
  336. scipy/interpolate/tests/test_polyint.py +972 -0
  337. scipy/interpolate/tests/test_rbf.py +246 -0
  338. scipy/interpolate/tests/test_rbfinterp.py +534 -0
  339. scipy/interpolate/tests/test_rgi.py +1151 -0
  340. scipy/io/__init__.py +116 -0
  341. scipy/io/_fast_matrix_market/__init__.py +600 -0
  342. scipy/io/_fast_matrix_market/_fmm_core.cp313-win_arm64.lib +0 -0
  343. scipy/io/_fast_matrix_market/_fmm_core.cp313-win_arm64.pyd +0 -0
  344. scipy/io/_fortran.py +354 -0
  345. scipy/io/_harwell_boeing/__init__.py +7 -0
  346. scipy/io/_harwell_boeing/_fortran_format_parser.py +316 -0
  347. scipy/io/_harwell_boeing/hb.py +571 -0
  348. scipy/io/_harwell_boeing/tests/__init__.py +0 -0
  349. scipy/io/_harwell_boeing/tests/test_fortran_format.py +74 -0
  350. scipy/io/_harwell_boeing/tests/test_hb.py +70 -0
  351. scipy/io/_idl.py +917 -0
  352. scipy/io/_mmio.py +968 -0
  353. scipy/io/_netcdf.py +1104 -0
  354. scipy/io/_test_fortran.cp313-win_arm64.lib +0 -0
  355. scipy/io/_test_fortran.cp313-win_arm64.pyd +0 -0
  356. scipy/io/arff/__init__.py +28 -0
  357. scipy/io/arff/_arffread.py +873 -0
  358. scipy/io/arff/arffread.py +19 -0
  359. scipy/io/arff/tests/__init__.py +0 -0
  360. scipy/io/arff/tests/data/iris.arff +225 -0
  361. scipy/io/arff/tests/data/missing.arff +8 -0
  362. scipy/io/arff/tests/data/nodata.arff +11 -0
  363. scipy/io/arff/tests/data/quoted_nominal.arff +13 -0
  364. scipy/io/arff/tests/data/quoted_nominal_spaces.arff +13 -0
  365. scipy/io/arff/tests/data/test1.arff +10 -0
  366. scipy/io/arff/tests/data/test10.arff +8 -0
  367. scipy/io/arff/tests/data/test11.arff +11 -0
  368. scipy/io/arff/tests/data/test2.arff +15 -0
  369. scipy/io/arff/tests/data/test3.arff +6 -0
  370. scipy/io/arff/tests/data/test4.arff +11 -0
  371. scipy/io/arff/tests/data/test5.arff +26 -0
  372. scipy/io/arff/tests/data/test6.arff +12 -0
  373. scipy/io/arff/tests/data/test7.arff +15 -0
  374. scipy/io/arff/tests/data/test8.arff +12 -0
  375. scipy/io/arff/tests/data/test9.arff +14 -0
  376. scipy/io/arff/tests/test_arffread.py +421 -0
  377. scipy/io/harwell_boeing.py +17 -0
  378. scipy/io/idl.py +17 -0
  379. scipy/io/matlab/__init__.py +66 -0
  380. scipy/io/matlab/_byteordercodes.py +75 -0
  381. scipy/io/matlab/_mio.py +375 -0
  382. scipy/io/matlab/_mio4.py +632 -0
  383. scipy/io/matlab/_mio5.py +901 -0
  384. scipy/io/matlab/_mio5_params.py +281 -0
  385. scipy/io/matlab/_mio5_utils.cp313-win_arm64.lib +0 -0
  386. scipy/io/matlab/_mio5_utils.cp313-win_arm64.pyd +0 -0
  387. scipy/io/matlab/_mio_utils.cp313-win_arm64.lib +0 -0
  388. scipy/io/matlab/_mio_utils.cp313-win_arm64.pyd +0 -0
  389. scipy/io/matlab/_miobase.py +435 -0
  390. scipy/io/matlab/_streams.cp313-win_arm64.lib +0 -0
  391. scipy/io/matlab/_streams.cp313-win_arm64.pyd +0 -0
  392. scipy/io/matlab/byteordercodes.py +17 -0
  393. scipy/io/matlab/mio.py +16 -0
  394. scipy/io/matlab/mio4.py +17 -0
  395. scipy/io/matlab/mio5.py +19 -0
  396. scipy/io/matlab/mio5_params.py +18 -0
  397. scipy/io/matlab/mio5_utils.py +17 -0
  398. scipy/io/matlab/mio_utils.py +17 -0
  399. scipy/io/matlab/miobase.py +16 -0
  400. scipy/io/matlab/streams.py +16 -0
  401. scipy/io/matlab/tests/__init__.py +0 -0
  402. scipy/io/matlab/tests/data/bad_miuint32.mat +0 -0
  403. scipy/io/matlab/tests/data/bad_miutf8_array_name.mat +0 -0
  404. scipy/io/matlab/tests/data/big_endian.mat +0 -0
  405. scipy/io/matlab/tests/data/broken_utf8.mat +0 -0
  406. scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat +0 -0
  407. scipy/io/matlab/tests/data/corrupted_zlib_data.mat +0 -0
  408. scipy/io/matlab/tests/data/debigged_m4.mat +0 -0
  409. scipy/io/matlab/tests/data/japanese_utf8.txt +5 -0
  410. scipy/io/matlab/tests/data/little_endian.mat +0 -0
  411. scipy/io/matlab/tests/data/logical_sparse.mat +0 -0
  412. scipy/io/matlab/tests/data/malformed1.mat +0 -0
  413. scipy/io/matlab/tests/data/miuint32_for_miint32.mat +0 -0
  414. scipy/io/matlab/tests/data/miutf8_array_name.mat +0 -0
  415. scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat +0 -0
  416. scipy/io/matlab/tests/data/one_by_zero_char.mat +0 -0
  417. scipy/io/matlab/tests/data/parabola.mat +0 -0
  418. scipy/io/matlab/tests/data/single_empty_string.mat +0 -0
  419. scipy/io/matlab/tests/data/some_functions.mat +0 -0
  420. scipy/io/matlab/tests/data/sqr.mat +0 -0
  421. scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat +0 -0
  422. scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat +0 -0
  423. scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat +0 -0
  424. scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat +0 -0
  425. scipy/io/matlab/tests/data/test_empty_struct.mat +0 -0
  426. scipy/io/matlab/tests/data/test_mat4_le_floats.mat +0 -0
  427. scipy/io/matlab/tests/data/test_skip_variable.mat +0 -0
  428. scipy/io/matlab/tests/data/testbool_8_WIN64.mat +0 -0
  429. scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat +0 -0
  430. scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat +0 -0
  431. scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat +0 -0
  432. scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat +0 -0
  433. scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat +0 -0
  434. scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat +0 -0
  435. scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat +0 -0
  436. scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat +0 -0
  437. scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat +0 -0
  438. scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat +0 -0
  439. scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat +0 -0
  440. scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat +0 -0
  441. scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat +0 -0
  442. scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat +0 -0
  443. scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat +0 -0
  444. scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat +0 -0
  445. scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat +0 -0
  446. scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat +0 -0
  447. scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat +0 -0
  448. scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat +0 -0
  449. scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat +0 -0
  450. scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat +0 -0
  451. scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat +0 -0
  452. scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat +0 -0
  453. scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat +0 -0
  454. scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat +0 -0
  455. scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat +0 -0
  456. scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat +0 -0
  457. scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat +0 -0
  458. scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat +0 -0
  459. scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat +0 -0
  460. scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat +0 -0
  461. scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat +0 -0
  462. scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat +0 -0
  463. scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat +0 -0
  464. scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat +0 -0
  465. scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat +0 -0
  466. scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat +0 -0
  467. scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat +0 -0
  468. scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat +0 -0
  469. scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat +0 -0
  470. scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat +0 -0
  471. scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat +0 -0
  472. scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat +0 -0
  473. scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat +0 -0
  474. scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat +0 -0
  475. scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat +0 -0
  476. scipy/io/matlab/tests/data/testsimplecell.mat +0 -0
  477. scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat +0 -0
  478. scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat +0 -0
  479. scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat +0 -0
  480. scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat +0 -0
  481. scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat +0 -0
  482. scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat +0 -0
  483. scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat +0 -0
  484. scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat +0 -0
  485. scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat +0 -0
  486. scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat +0 -0
  487. scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat +0 -0
  488. scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat +0 -0
  489. scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat +0 -0
  490. scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat +0 -0
  491. scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat +0 -0
  492. scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat +0 -0
  493. scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat +0 -0
  494. scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat +0 -0
  495. scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat +0 -0
  496. scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat +0 -0
  497. scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat +0 -0
  498. scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat +0 -0
  499. scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat +0 -0
  500. scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat +0 -0
  501. scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat +0 -0
  502. scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat +0 -0
  503. scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat +0 -0
  504. scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat +0 -0
  505. scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat +0 -0
  506. scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat +0 -0
  507. scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat +0 -0
  508. scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat +0 -0
  509. scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat +0 -0
  510. scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat +0 -0
  511. scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat +0 -0
  512. scipy/io/matlab/tests/data/testvec_4_GLNX86.mat +0 -0
  513. scipy/io/matlab/tests/test_byteordercodes.py +29 -0
  514. scipy/io/matlab/tests/test_mio.py +1399 -0
  515. scipy/io/matlab/tests/test_mio5_utils.py +179 -0
  516. scipy/io/matlab/tests/test_mio_funcs.py +51 -0
  517. scipy/io/matlab/tests/test_mio_utils.py +45 -0
  518. scipy/io/matlab/tests/test_miobase.py +32 -0
  519. scipy/io/matlab/tests/test_pathological.py +33 -0
  520. scipy/io/matlab/tests/test_streams.py +241 -0
  521. scipy/io/mmio.py +17 -0
  522. scipy/io/netcdf.py +17 -0
  523. scipy/io/tests/__init__.py +0 -0
  524. scipy/io/tests/data/Transparent Busy.ani +0 -0
  525. scipy/io/tests/data/array_float32_1d.sav +0 -0
  526. scipy/io/tests/data/array_float32_2d.sav +0 -0
  527. scipy/io/tests/data/array_float32_3d.sav +0 -0
  528. scipy/io/tests/data/array_float32_4d.sav +0 -0
  529. scipy/io/tests/data/array_float32_5d.sav +0 -0
  530. scipy/io/tests/data/array_float32_6d.sav +0 -0
  531. scipy/io/tests/data/array_float32_7d.sav +0 -0
  532. scipy/io/tests/data/array_float32_8d.sav +0 -0
  533. scipy/io/tests/data/array_float32_pointer_1d.sav +0 -0
  534. scipy/io/tests/data/array_float32_pointer_2d.sav +0 -0
  535. scipy/io/tests/data/array_float32_pointer_3d.sav +0 -0
  536. scipy/io/tests/data/array_float32_pointer_4d.sav +0 -0
  537. scipy/io/tests/data/array_float32_pointer_5d.sav +0 -0
  538. scipy/io/tests/data/array_float32_pointer_6d.sav +0 -0
  539. scipy/io/tests/data/array_float32_pointer_7d.sav +0 -0
  540. scipy/io/tests/data/array_float32_pointer_8d.sav +0 -0
  541. scipy/io/tests/data/example_1.nc +0 -0
  542. scipy/io/tests/data/example_2.nc +0 -0
  543. scipy/io/tests/data/example_3_maskedvals.nc +0 -0
  544. scipy/io/tests/data/fortran-3x3d-2i.dat +0 -0
  545. scipy/io/tests/data/fortran-mixed.dat +0 -0
  546. scipy/io/tests/data/fortran-sf8-11x1x10.dat +0 -0
  547. scipy/io/tests/data/fortran-sf8-15x10x22.dat +0 -0
  548. scipy/io/tests/data/fortran-sf8-1x1x1.dat +0 -0
  549. scipy/io/tests/data/fortran-sf8-1x1x5.dat +0 -0
  550. scipy/io/tests/data/fortran-sf8-1x1x7.dat +0 -0
  551. scipy/io/tests/data/fortran-sf8-1x3x5.dat +0 -0
  552. scipy/io/tests/data/fortran-si4-11x1x10.dat +0 -0
  553. scipy/io/tests/data/fortran-si4-15x10x22.dat +0 -0
  554. scipy/io/tests/data/fortran-si4-1x1x1.dat +0 -0
  555. scipy/io/tests/data/fortran-si4-1x1x5.dat +0 -0
  556. scipy/io/tests/data/fortran-si4-1x1x7.dat +0 -0
  557. scipy/io/tests/data/fortran-si4-1x3x5.dat +0 -0
  558. scipy/io/tests/data/invalid_pointer.sav +0 -0
  559. scipy/io/tests/data/null_pointer.sav +0 -0
  560. scipy/io/tests/data/scalar_byte.sav +0 -0
  561. scipy/io/tests/data/scalar_byte_descr.sav +0 -0
  562. scipy/io/tests/data/scalar_complex32.sav +0 -0
  563. scipy/io/tests/data/scalar_complex64.sav +0 -0
  564. scipy/io/tests/data/scalar_float32.sav +0 -0
  565. scipy/io/tests/data/scalar_float64.sav +0 -0
  566. scipy/io/tests/data/scalar_heap_pointer.sav +0 -0
  567. scipy/io/tests/data/scalar_int16.sav +0 -0
  568. scipy/io/tests/data/scalar_int32.sav +0 -0
  569. scipy/io/tests/data/scalar_int64.sav +0 -0
  570. scipy/io/tests/data/scalar_string.sav +0 -0
  571. scipy/io/tests/data/scalar_uint16.sav +0 -0
  572. scipy/io/tests/data/scalar_uint32.sav +0 -0
  573. scipy/io/tests/data/scalar_uint64.sav +0 -0
  574. scipy/io/tests/data/struct_arrays.sav +0 -0
  575. scipy/io/tests/data/struct_arrays_byte_idl80.sav +0 -0
  576. scipy/io/tests/data/struct_arrays_replicated.sav +0 -0
  577. scipy/io/tests/data/struct_arrays_replicated_3d.sav +0 -0
  578. scipy/io/tests/data/struct_inherit.sav +0 -0
  579. scipy/io/tests/data/struct_pointer_arrays.sav +0 -0
  580. scipy/io/tests/data/struct_pointer_arrays_replicated.sav +0 -0
  581. scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav +0 -0
  582. scipy/io/tests/data/struct_pointers.sav +0 -0
  583. scipy/io/tests/data/struct_pointers_replicated.sav +0 -0
  584. scipy/io/tests/data/struct_pointers_replicated_3d.sav +0 -0
  585. scipy/io/tests/data/struct_scalars.sav +0 -0
  586. scipy/io/tests/data/struct_scalars_replicated.sav +0 -0
  587. scipy/io/tests/data/struct_scalars_replicated_3d.sav +0 -0
  588. scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav +0 -0
  589. scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav +0 -0
  590. scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav +0 -0
  591. scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav +0 -0
  592. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav +0 -0
  593. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav +0 -0
  594. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav +0 -0
  595. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav +0 -0
  596. scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav +0 -0
  597. scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav +0 -0
  598. scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav +0 -0
  599. scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav +0 -0
  600. scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav +0 -0
  601. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav +0 -0
  602. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav +0 -0
  603. scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav +0 -0
  604. scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav +0 -0
  605. scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav +0 -0
  606. scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav +0 -0
  607. scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav +0 -0
  608. scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav +0 -0
  609. scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav +0 -0
  610. scipy/io/tests/data/various_compressed.sav +0 -0
  611. scipy/io/tests/test_fortran.py +264 -0
  612. scipy/io/tests/test_idl.py +483 -0
  613. scipy/io/tests/test_mmio.py +831 -0
  614. scipy/io/tests/test_netcdf.py +550 -0
  615. scipy/io/tests/test_paths.py +93 -0
  616. scipy/io/tests/test_wavfile.py +501 -0
  617. scipy/io/wavfile.py +938 -0
  618. scipy/linalg/__init__.pxd +1 -0
  619. scipy/linalg/__init__.py +236 -0
  620. scipy/linalg/_basic.py +2146 -0
  621. scipy/linalg/_blas_subroutines.h +164 -0
  622. scipy/linalg/_cythonized_array_utils.cp313-win_arm64.lib +0 -0
  623. scipy/linalg/_cythonized_array_utils.cp313-win_arm64.pyd +0 -0
  624. scipy/linalg/_cythonized_array_utils.pxd +40 -0
  625. scipy/linalg/_cythonized_array_utils.pyi +16 -0
  626. scipy/linalg/_decomp.py +1645 -0
  627. scipy/linalg/_decomp_cholesky.py +413 -0
  628. scipy/linalg/_decomp_cossin.py +236 -0
  629. scipy/linalg/_decomp_interpolative.cp313-win_arm64.lib +0 -0
  630. scipy/linalg/_decomp_interpolative.cp313-win_arm64.pyd +0 -0
  631. scipy/linalg/_decomp_ldl.py +356 -0
  632. scipy/linalg/_decomp_lu.py +401 -0
  633. scipy/linalg/_decomp_lu_cython.cp313-win_arm64.lib +0 -0
  634. scipy/linalg/_decomp_lu_cython.cp313-win_arm64.pyd +0 -0
  635. scipy/linalg/_decomp_lu_cython.pyi +6 -0
  636. scipy/linalg/_decomp_polar.py +113 -0
  637. scipy/linalg/_decomp_qr.py +494 -0
  638. scipy/linalg/_decomp_qz.py +452 -0
  639. scipy/linalg/_decomp_schur.py +336 -0
  640. scipy/linalg/_decomp_svd.py +545 -0
  641. scipy/linalg/_decomp_update.cp313-win_arm64.lib +0 -0
  642. scipy/linalg/_decomp_update.cp313-win_arm64.pyd +0 -0
  643. scipy/linalg/_expm_frechet.py +417 -0
  644. scipy/linalg/_fblas.cp313-win_arm64.lib +0 -0
  645. scipy/linalg/_fblas.cp313-win_arm64.pyd +0 -0
  646. scipy/linalg/_flapack.cp313-win_arm64.lib +0 -0
  647. scipy/linalg/_flapack.cp313-win_arm64.pyd +0 -0
  648. scipy/linalg/_lapack_subroutines.h +1521 -0
  649. scipy/linalg/_linalg_pythran.cp313-win_arm64.lib +0 -0
  650. scipy/linalg/_linalg_pythran.cp313-win_arm64.pyd +0 -0
  651. scipy/linalg/_matfuncs.py +1050 -0
  652. scipy/linalg/_matfuncs_expm.cp313-win_arm64.lib +0 -0
  653. scipy/linalg/_matfuncs_expm.cp313-win_arm64.pyd +0 -0
  654. scipy/linalg/_matfuncs_expm.pyi +6 -0
  655. scipy/linalg/_matfuncs_inv_ssq.py +886 -0
  656. scipy/linalg/_matfuncs_schur_sqrtm.cp313-win_arm64.lib +0 -0
  657. scipy/linalg/_matfuncs_schur_sqrtm.cp313-win_arm64.pyd +0 -0
  658. scipy/linalg/_matfuncs_sqrtm.py +107 -0
  659. scipy/linalg/_matfuncs_sqrtm_triu.cp313-win_arm64.lib +0 -0
  660. scipy/linalg/_matfuncs_sqrtm_triu.cp313-win_arm64.pyd +0 -0
  661. scipy/linalg/_misc.py +191 -0
  662. scipy/linalg/_procrustes.py +113 -0
  663. scipy/linalg/_sketches.py +189 -0
  664. scipy/linalg/_solve_toeplitz.cp313-win_arm64.lib +0 -0
  665. scipy/linalg/_solve_toeplitz.cp313-win_arm64.pyd +0 -0
  666. scipy/linalg/_solvers.py +862 -0
  667. scipy/linalg/_special_matrices.py +1322 -0
  668. scipy/linalg/_testutils.py +65 -0
  669. scipy/linalg/basic.py +23 -0
  670. scipy/linalg/blas.py +495 -0
  671. scipy/linalg/cython_blas.cp313-win_arm64.lib +0 -0
  672. scipy/linalg/cython_blas.cp313-win_arm64.pyd +0 -0
  673. scipy/linalg/cython_blas.pxd +169 -0
  674. scipy/linalg/cython_blas.pyx +1432 -0
  675. scipy/linalg/cython_lapack.cp313-win_arm64.lib +0 -0
  676. scipy/linalg/cython_lapack.cp313-win_arm64.pyd +0 -0
  677. scipy/linalg/cython_lapack.pxd +1528 -0
  678. scipy/linalg/cython_lapack.pyx +12045 -0
  679. scipy/linalg/decomp.py +23 -0
  680. scipy/linalg/decomp_cholesky.py +21 -0
  681. scipy/linalg/decomp_lu.py +21 -0
  682. scipy/linalg/decomp_qr.py +20 -0
  683. scipy/linalg/decomp_schur.py +21 -0
  684. scipy/linalg/decomp_svd.py +21 -0
  685. scipy/linalg/interpolative.py +989 -0
  686. scipy/linalg/lapack.py +1081 -0
  687. scipy/linalg/matfuncs.py +23 -0
  688. scipy/linalg/misc.py +21 -0
  689. scipy/linalg/special_matrices.py +22 -0
  690. scipy/linalg/tests/__init__.py +0 -0
  691. scipy/linalg/tests/_cython_examples/extending.pyx +23 -0
  692. scipy/linalg/tests/_cython_examples/meson.build +34 -0
  693. scipy/linalg/tests/data/carex_15_data.npz +0 -0
  694. scipy/linalg/tests/data/carex_18_data.npz +0 -0
  695. scipy/linalg/tests/data/carex_19_data.npz +0 -0
  696. scipy/linalg/tests/data/carex_20_data.npz +0 -0
  697. scipy/linalg/tests/data/carex_6_data.npz +0 -0
  698. scipy/linalg/tests/data/gendare_20170120_data.npz +0 -0
  699. scipy/linalg/tests/test_basic.py +2074 -0
  700. scipy/linalg/tests/test_batch.py +588 -0
  701. scipy/linalg/tests/test_blas.py +1127 -0
  702. scipy/linalg/tests/test_cython_blas.py +118 -0
  703. scipy/linalg/tests/test_cython_lapack.py +22 -0
  704. scipy/linalg/tests/test_cythonized_array_utils.py +130 -0
  705. scipy/linalg/tests/test_decomp.py +3189 -0
  706. scipy/linalg/tests/test_decomp_cholesky.py +268 -0
  707. scipy/linalg/tests/test_decomp_cossin.py +314 -0
  708. scipy/linalg/tests/test_decomp_ldl.py +137 -0
  709. scipy/linalg/tests/test_decomp_lu.py +308 -0
  710. scipy/linalg/tests/test_decomp_polar.py +110 -0
  711. scipy/linalg/tests/test_decomp_update.py +1701 -0
  712. scipy/linalg/tests/test_extending.py +46 -0
  713. scipy/linalg/tests/test_fblas.py +607 -0
  714. scipy/linalg/tests/test_interpolative.py +232 -0
  715. scipy/linalg/tests/test_lapack.py +3620 -0
  716. scipy/linalg/tests/test_matfuncs.py +1125 -0
  717. scipy/linalg/tests/test_matmul_toeplitz.py +136 -0
  718. scipy/linalg/tests/test_procrustes.py +214 -0
  719. scipy/linalg/tests/test_sketches.py +118 -0
  720. scipy/linalg/tests/test_solve_toeplitz.py +150 -0
  721. scipy/linalg/tests/test_solvers.py +844 -0
  722. scipy/linalg/tests/test_special_matrices.py +636 -0
  723. scipy/misc/__init__.py +6 -0
  724. scipy/misc/common.py +6 -0
  725. scipy/misc/doccer.py +6 -0
  726. scipy/ndimage/__init__.py +174 -0
  727. scipy/ndimage/_ctest.cp313-win_arm64.lib +0 -0
  728. scipy/ndimage/_ctest.cp313-win_arm64.pyd +0 -0
  729. scipy/ndimage/_cytest.cp313-win_arm64.lib +0 -0
  730. scipy/ndimage/_cytest.cp313-win_arm64.pyd +0 -0
  731. scipy/ndimage/_delegators.py +303 -0
  732. scipy/ndimage/_filters.py +2422 -0
  733. scipy/ndimage/_fourier.py +306 -0
  734. scipy/ndimage/_interpolation.py +1033 -0
  735. scipy/ndimage/_measurements.py +1689 -0
  736. scipy/ndimage/_morphology.py +2634 -0
  737. scipy/ndimage/_nd_image.cp313-win_arm64.lib +0 -0
  738. scipy/ndimage/_nd_image.cp313-win_arm64.pyd +0 -0
  739. scipy/ndimage/_ndimage_api.py +16 -0
  740. scipy/ndimage/_ni_docstrings.py +214 -0
  741. scipy/ndimage/_ni_label.cp313-win_arm64.lib +0 -0
  742. scipy/ndimage/_ni_label.cp313-win_arm64.pyd +0 -0
  743. scipy/ndimage/_ni_support.py +139 -0
  744. scipy/ndimage/_rank_filter_1d.cp313-win_arm64.lib +0 -0
  745. scipy/ndimage/_rank_filter_1d.cp313-win_arm64.pyd +0 -0
  746. scipy/ndimage/_support_alternative_backends.py +84 -0
  747. scipy/ndimage/filters.py +27 -0
  748. scipy/ndimage/fourier.py +21 -0
  749. scipy/ndimage/interpolation.py +22 -0
  750. scipy/ndimage/measurements.py +24 -0
  751. scipy/ndimage/morphology.py +27 -0
  752. scipy/ndimage/tests/__init__.py +12 -0
  753. scipy/ndimage/tests/data/label_inputs.txt +21 -0
  754. scipy/ndimage/tests/data/label_results.txt +294 -0
  755. scipy/ndimage/tests/data/label_strels.txt +42 -0
  756. scipy/ndimage/tests/dots.png +0 -0
  757. scipy/ndimage/tests/test_c_api.py +102 -0
  758. scipy/ndimage/tests/test_datatypes.py +67 -0
  759. scipy/ndimage/tests/test_filters.py +3083 -0
  760. scipy/ndimage/tests/test_fourier.py +187 -0
  761. scipy/ndimage/tests/test_interpolation.py +1491 -0
  762. scipy/ndimage/tests/test_measurements.py +1592 -0
  763. scipy/ndimage/tests/test_morphology.py +2950 -0
  764. scipy/ndimage/tests/test_ni_support.py +78 -0
  765. scipy/ndimage/tests/test_splines.py +70 -0
  766. scipy/odr/__init__.py +131 -0
  767. scipy/odr/__odrpack.cp313-win_arm64.lib +0 -0
  768. scipy/odr/__odrpack.cp313-win_arm64.pyd +0 -0
  769. scipy/odr/_add_newdocs.py +34 -0
  770. scipy/odr/_models.py +315 -0
  771. scipy/odr/_odrpack.py +1154 -0
  772. scipy/odr/models.py +20 -0
  773. scipy/odr/odrpack.py +21 -0
  774. scipy/odr/tests/__init__.py +0 -0
  775. scipy/odr/tests/test_odr.py +607 -0
  776. scipy/optimize/__init__.pxd +1 -0
  777. scipy/optimize/__init__.py +460 -0
  778. scipy/optimize/_basinhopping.py +741 -0
  779. scipy/optimize/_bglu_dense.cp313-win_arm64.lib +0 -0
  780. scipy/optimize/_bglu_dense.cp313-win_arm64.pyd +0 -0
  781. scipy/optimize/_bracket.py +706 -0
  782. scipy/optimize/_chandrupatla.py +551 -0
  783. scipy/optimize/_cobyla_py.py +297 -0
  784. scipy/optimize/_cobyqa_py.py +72 -0
  785. scipy/optimize/_constraints.py +598 -0
  786. scipy/optimize/_dcsrch.py +728 -0
  787. scipy/optimize/_differentiable_functions.py +835 -0
  788. scipy/optimize/_differentialevolution.py +1970 -0
  789. scipy/optimize/_direct.cp313-win_arm64.lib +0 -0
  790. scipy/optimize/_direct.cp313-win_arm64.pyd +0 -0
  791. scipy/optimize/_direct_py.py +280 -0
  792. scipy/optimize/_dual_annealing.py +732 -0
  793. scipy/optimize/_elementwise.py +798 -0
  794. scipy/optimize/_group_columns.cp313-win_arm64.lib +0 -0
  795. scipy/optimize/_group_columns.cp313-win_arm64.pyd +0 -0
  796. scipy/optimize/_hessian_update_strategy.py +479 -0
  797. scipy/optimize/_highspy/__init__.py +0 -0
  798. scipy/optimize/_highspy/_core.cp313-win_arm64.lib +0 -0
  799. scipy/optimize/_highspy/_core.cp313-win_arm64.pyd +0 -0
  800. scipy/optimize/_highspy/_highs_options.cp313-win_arm64.lib +0 -0
  801. scipy/optimize/_highspy/_highs_options.cp313-win_arm64.pyd +0 -0
  802. scipy/optimize/_highspy/_highs_wrapper.py +338 -0
  803. scipy/optimize/_isotonic.py +157 -0
  804. scipy/optimize/_lbfgsb.cp313-win_arm64.lib +0 -0
  805. scipy/optimize/_lbfgsb.cp313-win_arm64.pyd +0 -0
  806. scipy/optimize/_lbfgsb_py.py +634 -0
  807. scipy/optimize/_linesearch.py +896 -0
  808. scipy/optimize/_linprog.py +733 -0
  809. scipy/optimize/_linprog_doc.py +1434 -0
  810. scipy/optimize/_linprog_highs.py +422 -0
  811. scipy/optimize/_linprog_ip.py +1141 -0
  812. scipy/optimize/_linprog_rs.py +572 -0
  813. scipy/optimize/_linprog_simplex.py +663 -0
  814. scipy/optimize/_linprog_util.py +1521 -0
  815. scipy/optimize/_lsap.cp313-win_arm64.lib +0 -0
  816. scipy/optimize/_lsap.cp313-win_arm64.pyd +0 -0
  817. scipy/optimize/_lsq/__init__.py +5 -0
  818. scipy/optimize/_lsq/bvls.py +183 -0
  819. scipy/optimize/_lsq/common.py +731 -0
  820. scipy/optimize/_lsq/dogbox.py +345 -0
  821. scipy/optimize/_lsq/givens_elimination.cp313-win_arm64.lib +0 -0
  822. scipy/optimize/_lsq/givens_elimination.cp313-win_arm64.pyd +0 -0
  823. scipy/optimize/_lsq/least_squares.py +1044 -0
  824. scipy/optimize/_lsq/lsq_linear.py +361 -0
  825. scipy/optimize/_lsq/trf.py +587 -0
  826. scipy/optimize/_lsq/trf_linear.py +249 -0
  827. scipy/optimize/_milp.py +394 -0
  828. scipy/optimize/_minimize.py +1199 -0
  829. scipy/optimize/_minpack.cp313-win_arm64.lib +0 -0
  830. scipy/optimize/_minpack.cp313-win_arm64.pyd +0 -0
  831. scipy/optimize/_minpack_py.py +1178 -0
  832. scipy/optimize/_moduleTNC.cp313-win_arm64.lib +0 -0
  833. scipy/optimize/_moduleTNC.cp313-win_arm64.pyd +0 -0
  834. scipy/optimize/_nnls.py +96 -0
  835. scipy/optimize/_nonlin.py +1634 -0
  836. scipy/optimize/_numdiff.py +963 -0
  837. scipy/optimize/_optimize.py +4169 -0
  838. scipy/optimize/_pava_pybind.cp313-win_arm64.lib +0 -0
  839. scipy/optimize/_pava_pybind.cp313-win_arm64.pyd +0 -0
  840. scipy/optimize/_qap.py +760 -0
  841. scipy/optimize/_remove_redundancy.py +522 -0
  842. scipy/optimize/_root.py +732 -0
  843. scipy/optimize/_root_scalar.py +538 -0
  844. scipy/optimize/_shgo.py +1606 -0
  845. scipy/optimize/_shgo_lib/__init__.py +0 -0
  846. scipy/optimize/_shgo_lib/_complex.py +1225 -0
  847. scipy/optimize/_shgo_lib/_vertex.py +460 -0
  848. scipy/optimize/_slsqp_py.py +603 -0
  849. scipy/optimize/_slsqplib.cp313-win_arm64.lib +0 -0
  850. scipy/optimize/_slsqplib.cp313-win_arm64.pyd +0 -0
  851. scipy/optimize/_spectral.py +260 -0
  852. scipy/optimize/_tnc.py +438 -0
  853. scipy/optimize/_trlib/__init__.py +12 -0
  854. scipy/optimize/_trlib/_trlib.cp313-win_arm64.lib +0 -0
  855. scipy/optimize/_trlib/_trlib.cp313-win_arm64.pyd +0 -0
  856. scipy/optimize/_trustregion.py +318 -0
  857. scipy/optimize/_trustregion_constr/__init__.py +6 -0
  858. scipy/optimize/_trustregion_constr/canonical_constraint.py +390 -0
  859. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +231 -0
  860. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +584 -0
  861. scipy/optimize/_trustregion_constr/projections.py +411 -0
  862. scipy/optimize/_trustregion_constr/qp_subproblem.py +637 -0
  863. scipy/optimize/_trustregion_constr/report.py +49 -0
  864. scipy/optimize/_trustregion_constr/tests/__init__.py +0 -0
  865. scipy/optimize/_trustregion_constr/tests/test_canonical_constraint.py +296 -0
  866. scipy/optimize/_trustregion_constr/tests/test_nested_minimize.py +39 -0
  867. scipy/optimize/_trustregion_constr/tests/test_projections.py +214 -0
  868. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +645 -0
  869. scipy/optimize/_trustregion_constr/tests/test_report.py +34 -0
  870. scipy/optimize/_trustregion_constr/tr_interior_point.py +361 -0
  871. scipy/optimize/_trustregion_dogleg.py +122 -0
  872. scipy/optimize/_trustregion_exact.py +437 -0
  873. scipy/optimize/_trustregion_krylov.py +65 -0
  874. scipy/optimize/_trustregion_ncg.py +126 -0
  875. scipy/optimize/_tstutils.py +972 -0
  876. scipy/optimize/_zeros.cp313-win_arm64.lib +0 -0
  877. scipy/optimize/_zeros.cp313-win_arm64.pyd +0 -0
  878. scipy/optimize/_zeros_py.py +1475 -0
  879. scipy/optimize/cobyla.py +19 -0
  880. scipy/optimize/cython_optimize/__init__.py +133 -0
  881. scipy/optimize/cython_optimize/_zeros.cp313-win_arm64.lib +0 -0
  882. scipy/optimize/cython_optimize/_zeros.cp313-win_arm64.pyd +0 -0
  883. scipy/optimize/cython_optimize/_zeros.pxd +33 -0
  884. scipy/optimize/cython_optimize/c_zeros.pxd +26 -0
  885. scipy/optimize/cython_optimize.pxd +11 -0
  886. scipy/optimize/elementwise.py +38 -0
  887. scipy/optimize/lbfgsb.py +23 -0
  888. scipy/optimize/linesearch.py +18 -0
  889. scipy/optimize/minpack.py +27 -0
  890. scipy/optimize/minpack2.py +17 -0
  891. scipy/optimize/moduleTNC.py +19 -0
  892. scipy/optimize/nonlin.py +29 -0
  893. scipy/optimize/optimize.py +40 -0
  894. scipy/optimize/slsqp.py +22 -0
  895. scipy/optimize/tests/__init__.py +0 -0
  896. scipy/optimize/tests/_cython_examples/extending.pyx +43 -0
  897. scipy/optimize/tests/_cython_examples/meson.build +32 -0
  898. scipy/optimize/tests/test__basinhopping.py +535 -0
  899. scipy/optimize/tests/test__differential_evolution.py +1703 -0
  900. scipy/optimize/tests/test__dual_annealing.py +416 -0
  901. scipy/optimize/tests/test__linprog_clean_inputs.py +312 -0
  902. scipy/optimize/tests/test__numdiff.py +885 -0
  903. scipy/optimize/tests/test__remove_redundancy.py +228 -0
  904. scipy/optimize/tests/test__root.py +124 -0
  905. scipy/optimize/tests/test__shgo.py +1164 -0
  906. scipy/optimize/tests/test__spectral.py +226 -0
  907. scipy/optimize/tests/test_bracket.py +896 -0
  908. scipy/optimize/tests/test_chandrupatla.py +982 -0
  909. scipy/optimize/tests/test_cobyla.py +195 -0
  910. scipy/optimize/tests/test_cobyqa.py +252 -0
  911. scipy/optimize/tests/test_constraint_conversion.py +286 -0
  912. scipy/optimize/tests/test_constraints.py +255 -0
  913. scipy/optimize/tests/test_cython_optimize.py +92 -0
  914. scipy/optimize/tests/test_differentiable_functions.py +1025 -0
  915. scipy/optimize/tests/test_direct.py +321 -0
  916. scipy/optimize/tests/test_extending.py +28 -0
  917. scipy/optimize/tests/test_hessian_update_strategy.py +300 -0
  918. scipy/optimize/tests/test_isotonic_regression.py +167 -0
  919. scipy/optimize/tests/test_lbfgsb_hessinv.py +65 -0
  920. scipy/optimize/tests/test_lbfgsb_setulb.py +122 -0
  921. scipy/optimize/tests/test_least_squares.py +986 -0
  922. scipy/optimize/tests/test_linear_assignment.py +116 -0
  923. scipy/optimize/tests/test_linesearch.py +328 -0
  924. scipy/optimize/tests/test_linprog.py +2577 -0
  925. scipy/optimize/tests/test_lsq_common.py +297 -0
  926. scipy/optimize/tests/test_lsq_linear.py +287 -0
  927. scipy/optimize/tests/test_milp.py +459 -0
  928. scipy/optimize/tests/test_minimize_constrained.py +845 -0
  929. scipy/optimize/tests/test_minpack.py +1194 -0
  930. scipy/optimize/tests/test_nnls.py +469 -0
  931. scipy/optimize/tests/test_nonlin.py +572 -0
  932. scipy/optimize/tests/test_optimize.py +3344 -0
  933. scipy/optimize/tests/test_quadratic_assignment.py +455 -0
  934. scipy/optimize/tests/test_regression.py +40 -0
  935. scipy/optimize/tests/test_slsqp.py +645 -0
  936. scipy/optimize/tests/test_tnc.py +345 -0
  937. scipy/optimize/tests/test_trustregion.py +110 -0
  938. scipy/optimize/tests/test_trustregion_exact.py +351 -0
  939. scipy/optimize/tests/test_trustregion_krylov.py +170 -0
  940. scipy/optimize/tests/test_zeros.py +998 -0
  941. scipy/optimize/tnc.py +22 -0
  942. scipy/optimize/zeros.py +26 -0
  943. scipy/signal/__init__.py +316 -0
  944. scipy/signal/_arraytools.py +264 -0
  945. scipy/signal/_czt.py +575 -0
  946. scipy/signal/_delegators.py +568 -0
  947. scipy/signal/_filter_design.py +5893 -0
  948. scipy/signal/_fir_filter_design.py +1458 -0
  949. scipy/signal/_lti_conversion.py +534 -0
  950. scipy/signal/_ltisys.py +3546 -0
  951. scipy/signal/_max_len_seq.py +139 -0
  952. scipy/signal/_max_len_seq_inner.cp313-win_arm64.lib +0 -0
  953. scipy/signal/_max_len_seq_inner.cp313-win_arm64.pyd +0 -0
  954. scipy/signal/_peak_finding.py +1310 -0
  955. scipy/signal/_peak_finding_utils.cp313-win_arm64.lib +0 -0
  956. scipy/signal/_peak_finding_utils.cp313-win_arm64.pyd +0 -0
  957. scipy/signal/_polyutils.py +172 -0
  958. scipy/signal/_savitzky_golay.py +357 -0
  959. scipy/signal/_short_time_fft.py +2228 -0
  960. scipy/signal/_signal_api.py +30 -0
  961. scipy/signal/_signaltools.py +5309 -0
  962. scipy/signal/_sigtools.cp313-win_arm64.lib +0 -0
  963. scipy/signal/_sigtools.cp313-win_arm64.pyd +0 -0
  964. scipy/signal/_sosfilt.cp313-win_arm64.lib +0 -0
  965. scipy/signal/_sosfilt.cp313-win_arm64.pyd +0 -0
  966. scipy/signal/_spectral_py.py +2471 -0
  967. scipy/signal/_spline.cp313-win_arm64.lib +0 -0
  968. scipy/signal/_spline.cp313-win_arm64.pyd +0 -0
  969. scipy/signal/_spline.pyi +34 -0
  970. scipy/signal/_spline_filters.py +848 -0
  971. scipy/signal/_support_alternative_backends.py +73 -0
  972. scipy/signal/_upfirdn.py +219 -0
  973. scipy/signal/_upfirdn_apply.cp313-win_arm64.lib +0 -0
  974. scipy/signal/_upfirdn_apply.cp313-win_arm64.pyd +0 -0
  975. scipy/signal/_waveforms.py +687 -0
  976. scipy/signal/_wavelets.py +29 -0
  977. scipy/signal/bsplines.py +21 -0
  978. scipy/signal/filter_design.py +28 -0
  979. scipy/signal/fir_filter_design.py +21 -0
  980. scipy/signal/lti_conversion.py +20 -0
  981. scipy/signal/ltisys.py +25 -0
  982. scipy/signal/signaltools.py +27 -0
  983. scipy/signal/spectral.py +21 -0
  984. scipy/signal/spline.py +18 -0
  985. scipy/signal/tests/__init__.py +0 -0
  986. scipy/signal/tests/_scipy_spectral_test_shim.py +311 -0
  987. scipy/signal/tests/mpsig.py +122 -0
  988. scipy/signal/tests/test_array_tools.py +111 -0
  989. scipy/signal/tests/test_bsplines.py +365 -0
  990. scipy/signal/tests/test_cont2discrete.py +424 -0
  991. scipy/signal/tests/test_czt.py +221 -0
  992. scipy/signal/tests/test_dltisys.py +599 -0
  993. scipy/signal/tests/test_filter_design.py +4744 -0
  994. scipy/signal/tests/test_fir_filter_design.py +851 -0
  995. scipy/signal/tests/test_ltisys.py +1225 -0
  996. scipy/signal/tests/test_max_len_seq.py +71 -0
  997. scipy/signal/tests/test_peak_finding.py +915 -0
  998. scipy/signal/tests/test_result_type.py +51 -0
  999. scipy/signal/tests/test_savitzky_golay.py +363 -0
  1000. scipy/signal/tests/test_short_time_fft.py +1107 -0
  1001. scipy/signal/tests/test_signaltools.py +4735 -0
  1002. scipy/signal/tests/test_spectral.py +2141 -0
  1003. scipy/signal/tests/test_splines.py +427 -0
  1004. scipy/signal/tests/test_upfirdn.py +322 -0
  1005. scipy/signal/tests/test_waveforms.py +400 -0
  1006. scipy/signal/tests/test_wavelets.py +59 -0
  1007. scipy/signal/tests/test_windows.py +987 -0
  1008. scipy/signal/waveforms.py +20 -0
  1009. scipy/signal/wavelets.py +17 -0
  1010. scipy/signal/windows/__init__.py +52 -0
  1011. scipy/signal/windows/_windows.py +2513 -0
  1012. scipy/signal/windows/windows.py +23 -0
  1013. scipy/sparse/__init__.py +350 -0
  1014. scipy/sparse/_base.py +1613 -0
  1015. scipy/sparse/_bsr.py +880 -0
  1016. scipy/sparse/_compressed.py +1328 -0
  1017. scipy/sparse/_construct.py +1454 -0
  1018. scipy/sparse/_coo.py +1581 -0
  1019. scipy/sparse/_csc.py +367 -0
  1020. scipy/sparse/_csparsetools.cp313-win_arm64.lib +0 -0
  1021. scipy/sparse/_csparsetools.cp313-win_arm64.pyd +0 -0
  1022. scipy/sparse/_csr.py +558 -0
  1023. scipy/sparse/_data.py +569 -0
  1024. scipy/sparse/_dia.py +677 -0
  1025. scipy/sparse/_dok.py +669 -0
  1026. scipy/sparse/_extract.py +178 -0
  1027. scipy/sparse/_index.py +444 -0
  1028. scipy/sparse/_lil.py +632 -0
  1029. scipy/sparse/_matrix.py +169 -0
  1030. scipy/sparse/_matrix_io.py +167 -0
  1031. scipy/sparse/_sparsetools.cp313-win_arm64.lib +0 -0
  1032. scipy/sparse/_sparsetools.cp313-win_arm64.pyd +0 -0
  1033. scipy/sparse/_spfuncs.py +76 -0
  1034. scipy/sparse/_sputils.py +632 -0
  1035. scipy/sparse/base.py +24 -0
  1036. scipy/sparse/bsr.py +22 -0
  1037. scipy/sparse/compressed.py +20 -0
  1038. scipy/sparse/construct.py +38 -0
  1039. scipy/sparse/coo.py +23 -0
  1040. scipy/sparse/csc.py +22 -0
  1041. scipy/sparse/csgraph/__init__.py +210 -0
  1042. scipy/sparse/csgraph/_flow.cp313-win_arm64.lib +0 -0
  1043. scipy/sparse/csgraph/_flow.cp313-win_arm64.pyd +0 -0
  1044. scipy/sparse/csgraph/_laplacian.py +563 -0
  1045. scipy/sparse/csgraph/_matching.cp313-win_arm64.lib +0 -0
  1046. scipy/sparse/csgraph/_matching.cp313-win_arm64.pyd +0 -0
  1047. scipy/sparse/csgraph/_min_spanning_tree.cp313-win_arm64.lib +0 -0
  1048. scipy/sparse/csgraph/_min_spanning_tree.cp313-win_arm64.pyd +0 -0
  1049. scipy/sparse/csgraph/_reordering.cp313-win_arm64.lib +0 -0
  1050. scipy/sparse/csgraph/_reordering.cp313-win_arm64.pyd +0 -0
  1051. scipy/sparse/csgraph/_shortest_path.cp313-win_arm64.lib +0 -0
  1052. scipy/sparse/csgraph/_shortest_path.cp313-win_arm64.pyd +0 -0
  1053. scipy/sparse/csgraph/_tools.cp313-win_arm64.lib +0 -0
  1054. scipy/sparse/csgraph/_tools.cp313-win_arm64.pyd +0 -0
  1055. scipy/sparse/csgraph/_traversal.cp313-win_arm64.lib +0 -0
  1056. scipy/sparse/csgraph/_traversal.cp313-win_arm64.pyd +0 -0
  1057. scipy/sparse/csgraph/_validation.py +66 -0
  1058. scipy/sparse/csgraph/tests/__init__.py +0 -0
  1059. scipy/sparse/csgraph/tests/test_connected_components.py +119 -0
  1060. scipy/sparse/csgraph/tests/test_conversions.py +61 -0
  1061. scipy/sparse/csgraph/tests/test_flow.py +209 -0
  1062. scipy/sparse/csgraph/tests/test_graph_laplacian.py +368 -0
  1063. scipy/sparse/csgraph/tests/test_matching.py +307 -0
  1064. scipy/sparse/csgraph/tests/test_pydata_sparse.py +197 -0
  1065. scipy/sparse/csgraph/tests/test_reordering.py +70 -0
  1066. scipy/sparse/csgraph/tests/test_shortest_path.py +540 -0
  1067. scipy/sparse/csgraph/tests/test_spanning_tree.py +66 -0
  1068. scipy/sparse/csgraph/tests/test_traversal.py +148 -0
  1069. scipy/sparse/csr.py +22 -0
  1070. scipy/sparse/data.py +18 -0
  1071. scipy/sparse/dia.py +22 -0
  1072. scipy/sparse/dok.py +22 -0
  1073. scipy/sparse/extract.py +23 -0
  1074. scipy/sparse/lil.py +22 -0
  1075. scipy/sparse/linalg/__init__.py +148 -0
  1076. scipy/sparse/linalg/_dsolve/__init__.py +71 -0
  1077. scipy/sparse/linalg/_dsolve/_add_newdocs.py +147 -0
  1078. scipy/sparse/linalg/_dsolve/_superlu.cp313-win_arm64.lib +0 -0
  1079. scipy/sparse/linalg/_dsolve/_superlu.cp313-win_arm64.pyd +0 -0
  1080. scipy/sparse/linalg/_dsolve/linsolve.py +882 -0
  1081. scipy/sparse/linalg/_dsolve/tests/__init__.py +0 -0
  1082. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +928 -0
  1083. scipy/sparse/linalg/_eigen/__init__.py +22 -0
  1084. scipy/sparse/linalg/_eigen/_svds.py +540 -0
  1085. scipy/sparse/linalg/_eigen/_svds_doc.py +382 -0
  1086. scipy/sparse/linalg/_eigen/arpack/COPYING +45 -0
  1087. scipy/sparse/linalg/_eigen/arpack/__init__.py +20 -0
  1088. scipy/sparse/linalg/_eigen/arpack/_arpack.cp313-win_arm64.lib +0 -0
  1089. scipy/sparse/linalg/_eigen/arpack/_arpack.cp313-win_arm64.pyd +0 -0
  1090. scipy/sparse/linalg/_eigen/arpack/arpack.py +1706 -0
  1091. scipy/sparse/linalg/_eigen/arpack/tests/__init__.py +0 -0
  1092. scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py +717 -0
  1093. scipy/sparse/linalg/_eigen/lobpcg/__init__.py +16 -0
  1094. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +1110 -0
  1095. scipy/sparse/linalg/_eigen/lobpcg/tests/__init__.py +0 -0
  1096. scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py +725 -0
  1097. scipy/sparse/linalg/_eigen/tests/__init__.py +0 -0
  1098. scipy/sparse/linalg/_eigen/tests/test_svds.py +886 -0
  1099. scipy/sparse/linalg/_expm_multiply.py +816 -0
  1100. scipy/sparse/linalg/_interface.py +920 -0
  1101. scipy/sparse/linalg/_isolve/__init__.py +20 -0
  1102. scipy/sparse/linalg/_isolve/_gcrotmk.py +503 -0
  1103. scipy/sparse/linalg/_isolve/iterative.py +1051 -0
  1104. scipy/sparse/linalg/_isolve/lgmres.py +230 -0
  1105. scipy/sparse/linalg/_isolve/lsmr.py +486 -0
  1106. scipy/sparse/linalg/_isolve/lsqr.py +589 -0
  1107. scipy/sparse/linalg/_isolve/minres.py +372 -0
  1108. scipy/sparse/linalg/_isolve/tests/__init__.py +0 -0
  1109. scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py +183 -0
  1110. scipy/sparse/linalg/_isolve/tests/test_iterative.py +809 -0
  1111. scipy/sparse/linalg/_isolve/tests/test_lgmres.py +225 -0
  1112. scipy/sparse/linalg/_isolve/tests/test_lsmr.py +185 -0
  1113. scipy/sparse/linalg/_isolve/tests/test_lsqr.py +120 -0
  1114. scipy/sparse/linalg/_isolve/tests/test_minres.py +97 -0
  1115. scipy/sparse/linalg/_isolve/tests/test_utils.py +9 -0
  1116. scipy/sparse/linalg/_isolve/tfqmr.py +179 -0
  1117. scipy/sparse/linalg/_isolve/utils.py +121 -0
  1118. scipy/sparse/linalg/_matfuncs.py +940 -0
  1119. scipy/sparse/linalg/_norm.py +195 -0
  1120. scipy/sparse/linalg/_onenormest.py +467 -0
  1121. scipy/sparse/linalg/_propack/_cpropack.cp313-win_arm64.lib +0 -0
  1122. scipy/sparse/linalg/_propack/_cpropack.cp313-win_arm64.pyd +0 -0
  1123. scipy/sparse/linalg/_propack/_dpropack.cp313-win_arm64.lib +0 -0
  1124. scipy/sparse/linalg/_propack/_dpropack.cp313-win_arm64.pyd +0 -0
  1125. scipy/sparse/linalg/_propack/_spropack.cp313-win_arm64.lib +0 -0
  1126. scipy/sparse/linalg/_propack/_spropack.cp313-win_arm64.pyd +0 -0
  1127. scipy/sparse/linalg/_propack/_zpropack.cp313-win_arm64.lib +0 -0
  1128. scipy/sparse/linalg/_propack/_zpropack.cp313-win_arm64.pyd +0 -0
  1129. scipy/sparse/linalg/_special_sparse_arrays.py +949 -0
  1130. scipy/sparse/linalg/_svdp.py +309 -0
  1131. scipy/sparse/linalg/dsolve.py +22 -0
  1132. scipy/sparse/linalg/eigen.py +21 -0
  1133. scipy/sparse/linalg/interface.py +20 -0
  1134. scipy/sparse/linalg/isolve.py +22 -0
  1135. scipy/sparse/linalg/matfuncs.py +18 -0
  1136. scipy/sparse/linalg/tests/__init__.py +0 -0
  1137. scipy/sparse/linalg/tests/propack_test_data.npz +0 -0
  1138. scipy/sparse/linalg/tests/test_expm_multiply.py +367 -0
  1139. scipy/sparse/linalg/tests/test_interface.py +561 -0
  1140. scipy/sparse/linalg/tests/test_matfuncs.py +592 -0
  1141. scipy/sparse/linalg/tests/test_norm.py +154 -0
  1142. scipy/sparse/linalg/tests/test_onenormest.py +252 -0
  1143. scipy/sparse/linalg/tests/test_propack.py +165 -0
  1144. scipy/sparse/linalg/tests/test_pydata_sparse.py +272 -0
  1145. scipy/sparse/linalg/tests/test_special_sparse_arrays.py +337 -0
  1146. scipy/sparse/sparsetools.py +17 -0
  1147. scipy/sparse/spfuncs.py +17 -0
  1148. scipy/sparse/sputils.py +17 -0
  1149. scipy/sparse/tests/__init__.py +0 -0
  1150. scipy/sparse/tests/data/csc_py2.npz +0 -0
  1151. scipy/sparse/tests/data/csc_py3.npz +0 -0
  1152. scipy/sparse/tests/test_arithmetic1d.py +341 -0
  1153. scipy/sparse/tests/test_array_api.py +561 -0
  1154. scipy/sparse/tests/test_base.py +5870 -0
  1155. scipy/sparse/tests/test_common1d.py +447 -0
  1156. scipy/sparse/tests/test_construct.py +872 -0
  1157. scipy/sparse/tests/test_coo.py +1119 -0
  1158. scipy/sparse/tests/test_csc.py +98 -0
  1159. scipy/sparse/tests/test_csr.py +214 -0
  1160. scipy/sparse/tests/test_dok.py +209 -0
  1161. scipy/sparse/tests/test_extract.py +51 -0
  1162. scipy/sparse/tests/test_indexing1d.py +603 -0
  1163. scipy/sparse/tests/test_matrix_io.py +109 -0
  1164. scipy/sparse/tests/test_minmax1d.py +128 -0
  1165. scipy/sparse/tests/test_sparsetools.py +344 -0
  1166. scipy/sparse/tests/test_spfuncs.py +97 -0
  1167. scipy/sparse/tests/test_sputils.py +424 -0
  1168. scipy/spatial/__init__.py +129 -0
  1169. scipy/spatial/_ckdtree.cp313-win_arm64.lib +0 -0
  1170. scipy/spatial/_ckdtree.cp313-win_arm64.pyd +0 -0
  1171. scipy/spatial/_distance_pybind.cp313-win_arm64.lib +0 -0
  1172. scipy/spatial/_distance_pybind.cp313-win_arm64.pyd +0 -0
  1173. scipy/spatial/_distance_wrap.cp313-win_arm64.lib +0 -0
  1174. scipy/spatial/_distance_wrap.cp313-win_arm64.pyd +0 -0
  1175. scipy/spatial/_geometric_slerp.py +238 -0
  1176. scipy/spatial/_hausdorff.cp313-win_arm64.lib +0 -0
  1177. scipy/spatial/_hausdorff.cp313-win_arm64.pyd +0 -0
  1178. scipy/spatial/_kdtree.py +920 -0
  1179. scipy/spatial/_plotutils.py +274 -0
  1180. scipy/spatial/_procrustes.py +132 -0
  1181. scipy/spatial/_qhull.cp313-win_arm64.lib +0 -0
  1182. scipy/spatial/_qhull.cp313-win_arm64.pyd +0 -0
  1183. scipy/spatial/_qhull.pyi +213 -0
  1184. scipy/spatial/_spherical_voronoi.py +341 -0
  1185. scipy/spatial/_voronoi.cp313-win_arm64.lib +0 -0
  1186. scipy/spatial/_voronoi.cp313-win_arm64.pyd +0 -0
  1187. scipy/spatial/_voronoi.pyi +4 -0
  1188. scipy/spatial/ckdtree.py +18 -0
  1189. scipy/spatial/distance.py +3147 -0
  1190. scipy/spatial/distance.pyi +210 -0
  1191. scipy/spatial/kdtree.py +25 -0
  1192. scipy/spatial/qhull.py +25 -0
  1193. scipy/spatial/qhull_src/COPYING_QHULL.txt +39 -0
  1194. scipy/spatial/tests/__init__.py +0 -0
  1195. scipy/spatial/tests/data/cdist-X1.txt +10 -0
  1196. scipy/spatial/tests/data/cdist-X2.txt +20 -0
  1197. scipy/spatial/tests/data/degenerate_pointset.npz +0 -0
  1198. scipy/spatial/tests/data/iris.txt +150 -0
  1199. scipy/spatial/tests/data/pdist-boolean-inp.txt +20 -0
  1200. scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt +1 -0
  1201. scipy/spatial/tests/data/pdist-chebyshev-ml.txt +1 -0
  1202. scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt +1 -0
  1203. scipy/spatial/tests/data/pdist-cityblock-ml.txt +1 -0
  1204. scipy/spatial/tests/data/pdist-correlation-ml-iris.txt +1 -0
  1205. scipy/spatial/tests/data/pdist-correlation-ml.txt +1 -0
  1206. scipy/spatial/tests/data/pdist-cosine-ml-iris.txt +1 -0
  1207. scipy/spatial/tests/data/pdist-cosine-ml.txt +1 -0
  1208. scipy/spatial/tests/data/pdist-double-inp.txt +20 -0
  1209. scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt +1 -0
  1210. scipy/spatial/tests/data/pdist-euclidean-ml.txt +1 -0
  1211. scipy/spatial/tests/data/pdist-hamming-ml.txt +1 -0
  1212. scipy/spatial/tests/data/pdist-jaccard-ml.txt +1 -0
  1213. scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt +1 -0
  1214. scipy/spatial/tests/data/pdist-jensenshannon-ml.txt +1 -0
  1215. scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt +1 -0
  1216. scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt +1 -0
  1217. scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt +1 -0
  1218. scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt +1 -0
  1219. scipy/spatial/tests/data/pdist-seuclidean-ml.txt +1 -0
  1220. scipy/spatial/tests/data/pdist-spearman-ml.txt +1 -0
  1221. scipy/spatial/tests/data/random-bool-data.txt +100 -0
  1222. scipy/spatial/tests/data/random-double-data.txt +100 -0
  1223. scipy/spatial/tests/data/random-int-data.txt +100 -0
  1224. scipy/spatial/tests/data/random-uint-data.txt +100 -0
  1225. scipy/spatial/tests/data/selfdual-4d-polytope.txt +27 -0
  1226. scipy/spatial/tests/test__plotutils.py +91 -0
  1227. scipy/spatial/tests/test__procrustes.py +116 -0
  1228. scipy/spatial/tests/test_distance.py +2389 -0
  1229. scipy/spatial/tests/test_hausdorff.py +199 -0
  1230. scipy/spatial/tests/test_kdtree.py +1536 -0
  1231. scipy/spatial/tests/test_qhull.py +1313 -0
  1232. scipy/spatial/tests/test_slerp.py +417 -0
  1233. scipy/spatial/tests/test_spherical_voronoi.py +358 -0
  1234. scipy/spatial/transform/__init__.py +31 -0
  1235. scipy/spatial/transform/_rigid_transform.cp313-win_arm64.lib +0 -0
  1236. scipy/spatial/transform/_rigid_transform.cp313-win_arm64.pyd +0 -0
  1237. scipy/spatial/transform/_rotation.cp313-win_arm64.lib +0 -0
  1238. scipy/spatial/transform/_rotation.cp313-win_arm64.pyd +0 -0
  1239. scipy/spatial/transform/_rotation_groups.py +140 -0
  1240. scipy/spatial/transform/_rotation_spline.py +460 -0
  1241. scipy/spatial/transform/rotation.py +21 -0
  1242. scipy/spatial/transform/tests/__init__.py +0 -0
  1243. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  1244. scipy/spatial/transform/tests/test_rotation.py +2569 -0
  1245. scipy/spatial/transform/tests/test_rotation_groups.py +169 -0
  1246. scipy/spatial/transform/tests/test_rotation_spline.py +183 -0
  1247. scipy/special/__init__.pxd +1 -0
  1248. scipy/special/__init__.py +841 -0
  1249. scipy/special/_add_newdocs.py +9961 -0
  1250. scipy/special/_basic.py +3576 -0
  1251. scipy/special/_comb.cp313-win_arm64.lib +0 -0
  1252. scipy/special/_comb.cp313-win_arm64.pyd +0 -0
  1253. scipy/special/_ellip_harm.py +214 -0
  1254. scipy/special/_ellip_harm_2.cp313-win_arm64.lib +0 -0
  1255. scipy/special/_ellip_harm_2.cp313-win_arm64.pyd +0 -0
  1256. scipy/special/_gufuncs.cp313-win_arm64.lib +0 -0
  1257. scipy/special/_gufuncs.cp313-win_arm64.pyd +0 -0
  1258. scipy/special/_input_validation.py +17 -0
  1259. scipy/special/_lambertw.py +149 -0
  1260. scipy/special/_logsumexp.py +426 -0
  1261. scipy/special/_mptestutils.py +453 -0
  1262. scipy/special/_multiufuncs.py +610 -0
  1263. scipy/special/_orthogonal.py +2592 -0
  1264. scipy/special/_orthogonal.pyi +330 -0
  1265. scipy/special/_precompute/__init__.py +0 -0
  1266. scipy/special/_precompute/cosine_cdf.py +17 -0
  1267. scipy/special/_precompute/expn_asy.py +54 -0
  1268. scipy/special/_precompute/gammainc_asy.py +116 -0
  1269. scipy/special/_precompute/gammainc_data.py +124 -0
  1270. scipy/special/_precompute/hyp2f1_data.py +484 -0
  1271. scipy/special/_precompute/lambertw.py +68 -0
  1272. scipy/special/_precompute/loggamma.py +43 -0
  1273. scipy/special/_precompute/struve_convergence.py +131 -0
  1274. scipy/special/_precompute/utils.py +38 -0
  1275. scipy/special/_precompute/wright_bessel.py +342 -0
  1276. scipy/special/_precompute/wright_bessel_data.py +152 -0
  1277. scipy/special/_precompute/wrightomega.py +41 -0
  1278. scipy/special/_precompute/zetac.py +27 -0
  1279. scipy/special/_sf_error.py +15 -0
  1280. scipy/special/_specfun.cp313-win_arm64.lib +0 -0
  1281. scipy/special/_specfun.cp313-win_arm64.pyd +0 -0
  1282. scipy/special/_special_ufuncs.cp313-win_arm64.lib +0 -0
  1283. scipy/special/_special_ufuncs.cp313-win_arm64.pyd +0 -0
  1284. scipy/special/_spfun_stats.py +106 -0
  1285. scipy/special/_spherical_bessel.py +397 -0
  1286. scipy/special/_support_alternative_backends.py +295 -0
  1287. scipy/special/_test_internal.cp313-win_arm64.lib +0 -0
  1288. scipy/special/_test_internal.cp313-win_arm64.pyd +0 -0
  1289. scipy/special/_test_internal.pyi +9 -0
  1290. scipy/special/_testutils.py +321 -0
  1291. scipy/special/_ufuncs.cp313-win_arm64.lib +0 -0
  1292. scipy/special/_ufuncs.cp313-win_arm64.pyd +0 -0
  1293. scipy/special/_ufuncs.pyi +522 -0
  1294. scipy/special/_ufuncs.pyx +13173 -0
  1295. scipy/special/_ufuncs_cxx.cp313-win_arm64.lib +0 -0
  1296. scipy/special/_ufuncs_cxx.cp313-win_arm64.pyd +0 -0
  1297. scipy/special/_ufuncs_cxx.pxd +142 -0
  1298. scipy/special/_ufuncs_cxx.pyx +427 -0
  1299. scipy/special/_ufuncs_cxx_defs.h +147 -0
  1300. scipy/special/_ufuncs_defs.h +57 -0
  1301. scipy/special/add_newdocs.py +15 -0
  1302. scipy/special/basic.py +87 -0
  1303. scipy/special/cython_special.cp313-win_arm64.lib +0 -0
  1304. scipy/special/cython_special.cp313-win_arm64.pyd +0 -0
  1305. scipy/special/cython_special.pxd +259 -0
  1306. scipy/special/cython_special.pyi +3 -0
  1307. scipy/special/orthogonal.py +45 -0
  1308. scipy/special/sf_error.py +20 -0
  1309. scipy/special/specfun.py +24 -0
  1310. scipy/special/spfun_stats.py +17 -0
  1311. scipy/special/tests/__init__.py +0 -0
  1312. scipy/special/tests/_cython_examples/extending.pyx +12 -0
  1313. scipy/special/tests/_cython_examples/meson.build +34 -0
  1314. scipy/special/tests/data/__init__.py +0 -0
  1315. scipy/special/tests/data/boost.npz +0 -0
  1316. scipy/special/tests/data/gsl.npz +0 -0
  1317. scipy/special/tests/data/local.npz +0 -0
  1318. scipy/special/tests/test_basic.py +4815 -0
  1319. scipy/special/tests/test_bdtr.py +112 -0
  1320. scipy/special/tests/test_boost_ufuncs.py +64 -0
  1321. scipy/special/tests/test_boxcox.py +125 -0
  1322. scipy/special/tests/test_cdflib.py +712 -0
  1323. scipy/special/tests/test_cdft_asymptotic.py +49 -0
  1324. scipy/special/tests/test_cephes_intp_cast.py +29 -0
  1325. scipy/special/tests/test_cosine_distr.py +83 -0
  1326. scipy/special/tests/test_cython_special.py +363 -0
  1327. scipy/special/tests/test_data.py +719 -0
  1328. scipy/special/tests/test_dd.py +42 -0
  1329. scipy/special/tests/test_digamma.py +45 -0
  1330. scipy/special/tests/test_ellip_harm.py +278 -0
  1331. scipy/special/tests/test_erfinv.py +89 -0
  1332. scipy/special/tests/test_exponential_integrals.py +118 -0
  1333. scipy/special/tests/test_extending.py +28 -0
  1334. scipy/special/tests/test_faddeeva.py +85 -0
  1335. scipy/special/tests/test_gamma.py +12 -0
  1336. scipy/special/tests/test_gammainc.py +152 -0
  1337. scipy/special/tests/test_hyp2f1.py +2566 -0
  1338. scipy/special/tests/test_hypergeometric.py +234 -0
  1339. scipy/special/tests/test_iv_ratio.py +249 -0
  1340. scipy/special/tests/test_kolmogorov.py +491 -0
  1341. scipy/special/tests/test_lambertw.py +109 -0
  1342. scipy/special/tests/test_legendre.py +1518 -0
  1343. scipy/special/tests/test_log1mexp.py +85 -0
  1344. scipy/special/tests/test_loggamma.py +70 -0
  1345. scipy/special/tests/test_logit.py +162 -0
  1346. scipy/special/tests/test_logsumexp.py +469 -0
  1347. scipy/special/tests/test_mpmath.py +2293 -0
  1348. scipy/special/tests/test_nan_inputs.py +65 -0
  1349. scipy/special/tests/test_ndtr.py +77 -0
  1350. scipy/special/tests/test_ndtri_exp.py +94 -0
  1351. scipy/special/tests/test_orthogonal.py +821 -0
  1352. scipy/special/tests/test_orthogonal_eval.py +275 -0
  1353. scipy/special/tests/test_owens_t.py +53 -0
  1354. scipy/special/tests/test_pcf.py +24 -0
  1355. scipy/special/tests/test_pdtr.py +48 -0
  1356. scipy/special/tests/test_powm1.py +65 -0
  1357. scipy/special/tests/test_precompute_expn_asy.py +24 -0
  1358. scipy/special/tests/test_precompute_gammainc.py +108 -0
  1359. scipy/special/tests/test_precompute_utils.py +36 -0
  1360. scipy/special/tests/test_round.py +18 -0
  1361. scipy/special/tests/test_sf_error.py +146 -0
  1362. scipy/special/tests/test_sici.py +36 -0
  1363. scipy/special/tests/test_specfun.py +48 -0
  1364. scipy/special/tests/test_spence.py +32 -0
  1365. scipy/special/tests/test_spfun_stats.py +61 -0
  1366. scipy/special/tests/test_sph_harm.py +85 -0
  1367. scipy/special/tests/test_spherical_bessel.py +400 -0
  1368. scipy/special/tests/test_support_alternative_backends.py +248 -0
  1369. scipy/special/tests/test_trig.py +72 -0
  1370. scipy/special/tests/test_ufunc_signatures.py +46 -0
  1371. scipy/special/tests/test_wright_bessel.py +205 -0
  1372. scipy/special/tests/test_wrightomega.py +117 -0
  1373. scipy/special/tests/test_zeta.py +301 -0
  1374. scipy/stats/__init__.py +670 -0
  1375. scipy/stats/_ansari_swilk_statistics.cp313-win_arm64.lib +0 -0
  1376. scipy/stats/_ansari_swilk_statistics.cp313-win_arm64.pyd +0 -0
  1377. scipy/stats/_axis_nan_policy.py +692 -0
  1378. scipy/stats/_biasedurn.cp313-win_arm64.lib +0 -0
  1379. scipy/stats/_biasedurn.cp313-win_arm64.pyd +0 -0
  1380. scipy/stats/_biasedurn.pxd +27 -0
  1381. scipy/stats/_binned_statistic.py +795 -0
  1382. scipy/stats/_binomtest.py +375 -0
  1383. scipy/stats/_bws_test.py +177 -0
  1384. scipy/stats/_censored_data.py +459 -0
  1385. scipy/stats/_common.py +5 -0
  1386. scipy/stats/_constants.py +42 -0
  1387. scipy/stats/_continued_fraction.py +387 -0
  1388. scipy/stats/_continuous_distns.py +12486 -0
  1389. scipy/stats/_correlation.py +210 -0
  1390. scipy/stats/_covariance.py +636 -0
  1391. scipy/stats/_crosstab.py +204 -0
  1392. scipy/stats/_discrete_distns.py +2098 -0
  1393. scipy/stats/_distn_infrastructure.py +4201 -0
  1394. scipy/stats/_distr_params.py +299 -0
  1395. scipy/stats/_distribution_infrastructure.py +5750 -0
  1396. scipy/stats/_entropy.py +428 -0
  1397. scipy/stats/_finite_differences.py +145 -0
  1398. scipy/stats/_fit.py +1351 -0
  1399. scipy/stats/_hypotests.py +2060 -0
  1400. scipy/stats/_kde.py +732 -0
  1401. scipy/stats/_ksstats.py +600 -0
  1402. scipy/stats/_levy_stable/__init__.py +1231 -0
  1403. scipy/stats/_levy_stable/levyst.cp313-win_arm64.lib +0 -0
  1404. scipy/stats/_levy_stable/levyst.cp313-win_arm64.pyd +0 -0
  1405. scipy/stats/_mannwhitneyu.py +492 -0
  1406. scipy/stats/_mgc.py +550 -0
  1407. scipy/stats/_morestats.py +4626 -0
  1408. scipy/stats/_mstats_basic.py +3658 -0
  1409. scipy/stats/_mstats_extras.py +521 -0
  1410. scipy/stats/_multicomp.py +449 -0
  1411. scipy/stats/_multivariate.py +7281 -0
  1412. scipy/stats/_new_distributions.py +452 -0
  1413. scipy/stats/_odds_ratio.py +466 -0
  1414. scipy/stats/_page_trend_test.py +486 -0
  1415. scipy/stats/_probability_distribution.py +1964 -0
  1416. scipy/stats/_qmc.py +2956 -0
  1417. scipy/stats/_qmc_cy.cp313-win_arm64.lib +0 -0
  1418. scipy/stats/_qmc_cy.cp313-win_arm64.pyd +0 -0
  1419. scipy/stats/_qmc_cy.pyi +54 -0
  1420. scipy/stats/_qmvnt.py +454 -0
  1421. scipy/stats/_qmvnt_cy.cp313-win_arm64.lib +0 -0
  1422. scipy/stats/_qmvnt_cy.cp313-win_arm64.pyd +0 -0
  1423. scipy/stats/_quantile.py +335 -0
  1424. scipy/stats/_rcont/__init__.py +4 -0
  1425. scipy/stats/_rcont/rcont.cp313-win_arm64.lib +0 -0
  1426. scipy/stats/_rcont/rcont.cp313-win_arm64.pyd +0 -0
  1427. scipy/stats/_relative_risk.py +263 -0
  1428. scipy/stats/_resampling.py +2352 -0
  1429. scipy/stats/_result_classes.py +40 -0
  1430. scipy/stats/_sampling.py +1314 -0
  1431. scipy/stats/_sensitivity_analysis.py +713 -0
  1432. scipy/stats/_sobol.cp313-win_arm64.lib +0 -0
  1433. scipy/stats/_sobol.cp313-win_arm64.pyd +0 -0
  1434. scipy/stats/_sobol.pyi +54 -0
  1435. scipy/stats/_sobol_direction_numbers.npz +0 -0
  1436. scipy/stats/_stats.cp313-win_arm64.lib +0 -0
  1437. scipy/stats/_stats.cp313-win_arm64.pyd +0 -0
  1438. scipy/stats/_stats.pxd +10 -0
  1439. scipy/stats/_stats_mstats_common.py +322 -0
  1440. scipy/stats/_stats_py.py +11089 -0
  1441. scipy/stats/_stats_pythran.cp313-win_arm64.lib +0 -0
  1442. scipy/stats/_stats_pythran.cp313-win_arm64.pyd +0 -0
  1443. scipy/stats/_survival.py +683 -0
  1444. scipy/stats/_tukeylambda_stats.py +199 -0
  1445. scipy/stats/_unuran/__init__.py +0 -0
  1446. scipy/stats/_unuran/unuran_wrapper.cp313-win_arm64.lib +0 -0
  1447. scipy/stats/_unuran/unuran_wrapper.cp313-win_arm64.pyd +0 -0
  1448. scipy/stats/_unuran/unuran_wrapper.pyi +179 -0
  1449. scipy/stats/_variation.py +126 -0
  1450. scipy/stats/_warnings_errors.py +38 -0
  1451. scipy/stats/_wilcoxon.py +265 -0
  1452. scipy/stats/biasedurn.py +16 -0
  1453. scipy/stats/contingency.py +521 -0
  1454. scipy/stats/distributions.py +24 -0
  1455. scipy/stats/kde.py +18 -0
  1456. scipy/stats/morestats.py +27 -0
  1457. scipy/stats/mstats.py +140 -0
  1458. scipy/stats/mstats_basic.py +42 -0
  1459. scipy/stats/mstats_extras.py +25 -0
  1460. scipy/stats/mvn.py +17 -0
  1461. scipy/stats/qmc.py +236 -0
  1462. scipy/stats/sampling.py +73 -0
  1463. scipy/stats/stats.py +41 -0
  1464. scipy/stats/tests/__init__.py +0 -0
  1465. scipy/stats/tests/common_tests.py +356 -0
  1466. scipy/stats/tests/data/_mvt.py +171 -0
  1467. scipy/stats/tests/data/fisher_exact_results_from_r.py +607 -0
  1468. scipy/stats/tests/data/jf_skew_t_gamlss_pdf_data.npy +0 -0
  1469. scipy/stats/tests/data/levy_stable/stable-Z1-cdf-sample-data.npy +0 -0
  1470. scipy/stats/tests/data/levy_stable/stable-Z1-pdf-sample-data.npy +0 -0
  1471. scipy/stats/tests/data/levy_stable/stable-loc-scale-sample-data.npy +0 -0
  1472. scipy/stats/tests/data/nist_anova/AtmWtAg.dat +108 -0
  1473. scipy/stats/tests/data/nist_anova/SiRstv.dat +85 -0
  1474. scipy/stats/tests/data/nist_anova/SmLs01.dat +249 -0
  1475. scipy/stats/tests/data/nist_anova/SmLs02.dat +1869 -0
  1476. scipy/stats/tests/data/nist_anova/SmLs03.dat +18069 -0
  1477. scipy/stats/tests/data/nist_anova/SmLs04.dat +249 -0
  1478. scipy/stats/tests/data/nist_anova/SmLs05.dat +1869 -0
  1479. scipy/stats/tests/data/nist_anova/SmLs06.dat +18069 -0
  1480. scipy/stats/tests/data/nist_anova/SmLs07.dat +249 -0
  1481. scipy/stats/tests/data/nist_anova/SmLs08.dat +1869 -0
  1482. scipy/stats/tests/data/nist_anova/SmLs09.dat +18069 -0
  1483. scipy/stats/tests/data/nist_linregress/Norris.dat +97 -0
  1484. scipy/stats/tests/data/rel_breitwigner_pdf_sample_data_ROOT.npy +0 -0
  1485. scipy/stats/tests/data/studentized_range_mpmath_ref.json +1499 -0
  1486. scipy/stats/tests/test_axis_nan_policy.py +1388 -0
  1487. scipy/stats/tests/test_binned_statistic.py +568 -0
  1488. scipy/stats/tests/test_censored_data.py +152 -0
  1489. scipy/stats/tests/test_contingency.py +294 -0
  1490. scipy/stats/tests/test_continued_fraction.py +173 -0
  1491. scipy/stats/tests/test_continuous.py +2198 -0
  1492. scipy/stats/tests/test_continuous_basic.py +1053 -0
  1493. scipy/stats/tests/test_continuous_fit_censored.py +683 -0
  1494. scipy/stats/tests/test_correlation.py +80 -0
  1495. scipy/stats/tests/test_crosstab.py +115 -0
  1496. scipy/stats/tests/test_discrete_basic.py +580 -0
  1497. scipy/stats/tests/test_discrete_distns.py +700 -0
  1498. scipy/stats/tests/test_distributions.py +10413 -0
  1499. scipy/stats/tests/test_entropy.py +322 -0
  1500. scipy/stats/tests/test_fast_gen_inversion.py +435 -0
  1501. scipy/stats/tests/test_fit.py +1090 -0
  1502. scipy/stats/tests/test_hypotests.py +1991 -0
  1503. scipy/stats/tests/test_kdeoth.py +676 -0
  1504. scipy/stats/tests/test_marray.py +289 -0
  1505. scipy/stats/tests/test_mgc.py +217 -0
  1506. scipy/stats/tests/test_morestats.py +3259 -0
  1507. scipy/stats/tests/test_mstats_basic.py +2071 -0
  1508. scipy/stats/tests/test_mstats_extras.py +172 -0
  1509. scipy/stats/tests/test_multicomp.py +405 -0
  1510. scipy/stats/tests/test_multivariate.py +4381 -0
  1511. scipy/stats/tests/test_odds_ratio.py +148 -0
  1512. scipy/stats/tests/test_qmc.py +1492 -0
  1513. scipy/stats/tests/test_quantile.py +199 -0
  1514. scipy/stats/tests/test_rank.py +345 -0
  1515. scipy/stats/tests/test_relative_risk.py +95 -0
  1516. scipy/stats/tests/test_resampling.py +2000 -0
  1517. scipy/stats/tests/test_sampling.py +1450 -0
  1518. scipy/stats/tests/test_sensitivity_analysis.py +310 -0
  1519. scipy/stats/tests/test_stats.py +9707 -0
  1520. scipy/stats/tests/test_survival.py +466 -0
  1521. scipy/stats/tests/test_tukeylambda_stats.py +85 -0
  1522. scipy/stats/tests/test_variation.py +216 -0
  1523. scipy/version.py +12 -0
  1524. scipy-1.16.2.dist-info/DELVEWHEEL +2 -0
  1525. scipy-1.16.2.dist-info/LICENSE.txt +912 -0
  1526. scipy-1.16.2.dist-info/METADATA +1061 -0
  1527. scipy-1.16.2.dist-info/RECORD +1530 -0
  1528. scipy-1.16.2.dist-info/WHEEL +4 -0
  1529. scipy.libs/msvcp140-5f1c5dd31916990d94181e07bc3afb32.dll +0 -0
  1530. scipy.libs/scipy_openblas-f3ac85b1f412f7e86514c923dc4058d1.dll +0 -0
@@ -0,0 +1,2471 @@
1
+ """Tools for spectral analysis.
2
+ """
3
+ import numpy as np
4
+ import numpy.typing as npt
5
+ from scipy import fft as sp_fft
6
+ from . import _signaltools
7
+ from ._short_time_fft import ShortTimeFFT, FFT_MODE_TYPE
8
+ from .windows import get_window
9
+ from ._arraytools import const_ext, even_ext, odd_ext, zero_ext
10
+ import warnings
11
+ from typing import cast, Literal
12
+
13
+
14
+ __all__ = ['periodogram', 'welch', 'lombscargle', 'csd', 'coherence',
15
+ 'spectrogram', 'stft', 'istft', 'check_COLA', 'check_NOLA']
16
+
17
+
18
+ def lombscargle(
19
+ x: npt.ArrayLike,
20
+ y: npt.ArrayLike,
21
+ freqs: npt.ArrayLike,
22
+ precenter: bool = False,
23
+ normalize: bool | Literal["power", "normalize", "amplitude"] = False,
24
+ *,
25
+ weights: npt.NDArray | None = None,
26
+ floating_mean: bool = False,
27
+ ) -> npt.NDArray:
28
+ """
29
+ Compute the generalized Lomb-Scargle periodogram.
30
+
31
+ The Lomb-Scargle periodogram was developed by Lomb [1]_ and further
32
+ extended by Scargle [2]_ to find, and test the significance of weak
33
+ periodic signals with uneven temporal sampling. The algorithm used
34
+ here is based on a weighted least-squares fit of the form
35
+ ``y(ω) = a*cos(ω*x) + b*sin(ω*x) + c``, where the fit is calculated for
36
+ each frequency independently. This algorithm was developed by Zechmeister
37
+ and Kürster which improves the Lomb-Scargle periodogram by enabling
38
+ the weighting of individual samples and calculating an unknown y offset
39
+ (also called a "floating-mean" model) [3]_. For more details, and practical
40
+ considerations, see the excellent reference on the Lomb-Scargle periodogram [4]_.
41
+
42
+ When *normalize* is False (or "power") (default) the computed periodogram
43
+ is unnormalized, it takes the value ``(A**2) * N/4`` for a harmonic
44
+ signal with amplitude A for sufficiently large N. Where N is the length of x or y.
45
+
46
+ When *normalize* is True (or "normalize") the computed periodogram is normalized
47
+ by the residuals of the data around a constant reference model (at zero).
48
+
49
+ When *normalize* is "amplitude" the computed periodogram is the complex
50
+ representation of the amplitude and phase.
51
+
52
+ Input arrays should be 1-D of a real floating data type, which are converted into
53
+ float64 arrays before processing.
54
+
55
+ Parameters
56
+ ----------
57
+ x : array_like
58
+ Sample times.
59
+ y : array_like
60
+ Measurement values. Values are assumed to have a baseline of ``y = 0``. If
61
+ there is a possibility of a y offset, it is recommended to set `floating_mean`
62
+ to True.
63
+ freqs : array_like
64
+ Angular frequencies (e.g., having unit rad/s=2π/s for `x` having unit s) for
65
+ output periodogram. Frequencies are normally >= 0, as any peak at ``-freq`` will
66
+ also exist at ``+freq``.
67
+ precenter : bool, optional
68
+ Pre-center measurement values by subtracting the mean, if True. This is
69
+ a legacy parameter and unnecessary if `floating_mean` is True.
70
+ normalize : bool | str, optional
71
+ Compute normalized or complex (amplitude + phase) periodogram.
72
+ Valid options are: ``False``/``"power"``, ``True``/``"normalize"``, or
73
+ ``"amplitude"``.
74
+ weights : array_like, optional
75
+ Weights for each sample. Weights must be nonnegative.
76
+ floating_mean : bool, optional
77
+ Determines a y offset for each frequency independently, if True.
78
+ Else the y offset is assumed to be `0`.
79
+
80
+ Returns
81
+ -------
82
+ pgram : array_like
83
+ Lomb-Scargle periodogram.
84
+
85
+ Raises
86
+ ------
87
+ ValueError
88
+ If any of the input arrays x, y, freqs, or weights are not 1D, or if any are
89
+ zero length. Or, if the input arrays x, y, and weights do not have the same
90
+ shape as each other.
91
+ ValueError
92
+ If any weight is < 0, or the sum of the weights is <= 0.
93
+ ValueError
94
+ If the normalize parameter is not one of the allowed options.
95
+
96
+ See Also
97
+ --------
98
+ periodogram: Power spectral density using a periodogram
99
+ welch: Power spectral density by Welch's method
100
+ csd: Cross spectral density by Welch's method
101
+
102
+ Notes
103
+ -----
104
+ The algorithm used will not automatically account for any unknown y offset, unless
105
+ floating_mean is True. Therefore, for most use cases, if there is a possibility of
106
+ a y offset, it is recommended to set floating_mean to True. If precenter is True,
107
+ it performs the operation ``y -= y.mean()``. However, precenter is a legacy
108
+ parameter, and unnecessary when floating_mean is True. Furthermore, the mean
109
+ removed by precenter does not account for sample weights, nor will it correct for
110
+ any bias due to consistently missing observations at peaks and/or troughs. When the
111
+ normalize parameter is "amplitude", for any frequency in freqs that is below
112
+ ``(2*pi)/(x.max() - x.min())``, the predicted amplitude will tend towards infinity.
113
+ The concept of a "Nyquist frequency" limit (see Nyquist-Shannon sampling theorem)
114
+ is not generally applicable to unevenly sampled data. Therefore, with unevenly
115
+ sampled data, valid frequencies in freqs can often be much higher than expected.
116
+
117
+ References
118
+ ----------
119
+ .. [1] N.R. Lomb "Least-squares frequency analysis of unequally spaced
120
+ data", Astrophysics and Space Science, vol 39, pp. 447-462, 1976
121
+ :doi:`10.1007/bf00648343`
122
+
123
+ .. [2] J.D. Scargle "Studies in astronomical time series analysis. II -
124
+ Statistical aspects of spectral analysis of unevenly spaced data",
125
+ The Astrophysical Journal, vol 263, pp. 835-853, 1982
126
+ :doi:`10.1086/160554`
127
+
128
+ .. [3] M. Zechmeister and M. Kürster, "The generalised Lomb-Scargle periodogram.
129
+ A new formalism for the floating-mean and Keplerian periodograms,"
130
+ Astronomy and Astrophysics, vol. 496, pp. 577-584, 2009
131
+ :doi:`10.1051/0004-6361:200811296`
132
+
133
+ .. [4] J.T. VanderPlas, "Understanding the Lomb-Scargle Periodogram,"
134
+ The Astrophysical Journal Supplement Series, vol. 236, no. 1, p. 16,
135
+ May 2018
136
+ :doi:`10.3847/1538-4365/aab766`
137
+
138
+
139
+ Examples
140
+ --------
141
+ >>> import numpy as np
142
+ >>> rng = np.random.default_rng()
143
+
144
+ First define some input parameters for the signal:
145
+
146
+ >>> A = 2. # amplitude
147
+ >>> c = 2. # offset
148
+ >>> w0 = 1. # rad/sec
149
+ >>> nin = 150
150
+ >>> nout = 1002
151
+
152
+ Randomly generate sample times:
153
+
154
+ >>> x = rng.uniform(0, 10*np.pi, nin)
155
+
156
+ Plot a sine wave for the selected times:
157
+
158
+ >>> y = A * np.cos(w0*x) + c
159
+
160
+ Define the array of frequencies for which to compute the periodogram:
161
+
162
+ >>> w = np.linspace(0.25, 10, nout)
163
+
164
+ Calculate Lomb-Scargle periodogram for each of the normalize options:
165
+
166
+ >>> from scipy.signal import lombscargle
167
+ >>> pgram_power = lombscargle(x, y, w, normalize=False)
168
+ >>> pgram_norm = lombscargle(x, y, w, normalize=True)
169
+ >>> pgram_amp = lombscargle(x, y, w, normalize='amplitude')
170
+ ...
171
+ >>> pgram_power_f = lombscargle(x, y, w, normalize=False, floating_mean=True)
172
+ >>> pgram_norm_f = lombscargle(x, y, w, normalize=True, floating_mean=True)
173
+ >>> pgram_amp_f = lombscargle(x, y, w, normalize='amplitude', floating_mean=True)
174
+
175
+ Now make a plot of the input data:
176
+
177
+ >>> import matplotlib.pyplot as plt
178
+ >>> fig, (ax_t, ax_p, ax_n, ax_a) = plt.subplots(4, 1, figsize=(5, 6))
179
+ >>> ax_t.plot(x, y, 'b+')
180
+ >>> ax_t.set_xlabel('Time [s]')
181
+ >>> ax_t.set_ylabel('Amplitude')
182
+
183
+ Then plot the periodogram for each of the normalize options, as well as with and
184
+ without floating_mean=True:
185
+
186
+ >>> ax_p.plot(w, pgram_power, label='default')
187
+ >>> ax_p.plot(w, pgram_power_f, label='floating_mean=True')
188
+ >>> ax_p.set_xlabel('Angular frequency [rad/s]')
189
+ >>> ax_p.set_ylabel('Power')
190
+ >>> ax_p.legend(prop={'size': 7})
191
+ ...
192
+ >>> ax_n.plot(w, pgram_norm, label='default')
193
+ >>> ax_n.plot(w, pgram_norm_f, label='floating_mean=True')
194
+ >>> ax_n.set_xlabel('Angular frequency [rad/s]')
195
+ >>> ax_n.set_ylabel('Normalized')
196
+ >>> ax_n.legend(prop={'size': 7})
197
+ ...
198
+ >>> ax_a.plot(w, np.abs(pgram_amp), label='default')
199
+ >>> ax_a.plot(w, np.abs(pgram_amp_f), label='floating_mean=True')
200
+ >>> ax_a.set_xlabel('Angular frequency [rad/s]')
201
+ >>> ax_a.set_ylabel('Amplitude')
202
+ >>> ax_a.legend(prop={'size': 7})
203
+ ...
204
+ >>> plt.tight_layout()
205
+ >>> plt.show()
206
+
207
+ """
208
+
209
+ # if no weights are provided, assume all data points are equally important
210
+ if weights is None:
211
+ weights = np.ones_like(y, dtype=np.float64)
212
+ else:
213
+ # if provided, make sure weights is an array and cast to float64
214
+ weights = np.asarray(weights, dtype=np.float64)
215
+
216
+ # make sure other inputs are arrays and cast to float64
217
+ # done before validation, in case they were not arrays
218
+ x = np.asarray(x, dtype=np.float64)
219
+ y = np.asarray(y, dtype=np.float64)
220
+ freqs = np.asarray(freqs, dtype=np.float64)
221
+
222
+ # validate input shapes
223
+ if not (x.ndim == 1 and x.size > 0 and x.shape == y.shape == weights.shape):
224
+ raise ValueError("Parameters x, y, weights must be 1-D arrays of "
225
+ "equal non-zero length!")
226
+ if not (freqs.ndim == 1 and freqs.size > 0):
227
+ raise ValueError("Parameter freqs must be a 1-D array of non-zero length!")
228
+
229
+ # validate weights
230
+ if not (np.all(weights >= 0) and np.sum(weights) > 0):
231
+ raise ValueError("Parameter weights must have only non-negative entries "
232
+ "which sum to a positive value!")
233
+
234
+ # validate normalize parameter
235
+ if isinstance(normalize, bool):
236
+ # if bool, convert to str literal
237
+ normalize = "normalize" if normalize else "power"
238
+
239
+ if normalize not in ["power", "normalize", "amplitude"]:
240
+ raise ValueError(
241
+ "Normalize must be: False (or 'power'), True (or 'normalize'), "
242
+ "or 'amplitude'."
243
+ )
244
+
245
+ # weight vector must sum to 1
246
+ weights = weights * (1.0 / weights.sum())
247
+
248
+ # if requested, perform precenter
249
+ if precenter:
250
+ y = y - y.mean()
251
+
252
+ # transform arrays
253
+ # row vector
254
+ freqs = freqs.reshape(1, -1)
255
+ # column vectors
256
+ x = x.reshape(-1, 1)
257
+ y = y.reshape(-1, 1)
258
+ weights = weights.reshape(-1, 1)
259
+
260
+ # store frequent intermediates
261
+ weights_y = weights * y
262
+ freqst = freqs * x
263
+ coswt = np.cos(freqst)
264
+ sinwt = np.sin(freqst)
265
+
266
+ Y = np.dot(weights.T, y) # Eq. 7
267
+ CC = np.dot(weights.T, coswt * coswt) # Eq. 13
268
+ SS = 1.0 - CC # trig identity: S^2 = 1 - C^2 Eq.14
269
+ CS = np.dot(weights.T, coswt * sinwt) # Eq. 15
270
+
271
+ if floating_mean:
272
+ C = np.dot(weights.T, coswt) # Eq. 8
273
+ S = np.dot(weights.T, sinwt) # Eq. 9
274
+ CC -= C * C # Eq. 13
275
+ SS -= S * S # Eq. 14
276
+ CS -= C * S # Eq. 15
277
+
278
+ # calculate tau (phase offset to eliminate CS variable)
279
+ tau = 0.5 * np.arctan2(2.0 * CS, CC - SS) # Eq. 19
280
+ freqst_tau = freqst - tau
281
+
282
+ # coswt and sinwt are now offset by tau, which eliminates CS
283
+ coswt_tau = np.cos(freqst_tau)
284
+ sinwt_tau = np.sin(freqst_tau)
285
+
286
+ YC = np.dot(weights_y.T, coswt_tau) # Eq. 11
287
+ YS = np.dot(weights_y.T, sinwt_tau) # Eq. 12
288
+ CC = np.dot(weights.T, coswt_tau * coswt_tau) # Eq. 13, CC range is [0.5, 1.0]
289
+ SS = 1.0 - CC # trig identity: S^2 = 1 - C^2 Eq. 14, SS range is [0.0, 0.5]
290
+
291
+ if floating_mean:
292
+ C = np.dot(weights.T, coswt_tau) # Eq. 8
293
+ S = np.dot(weights.T, sinwt_tau) # Eq. 9
294
+ YC -= Y * C # Eq. 11
295
+ YS -= Y * S # Eq. 12
296
+ CC -= C * C # Eq. 13, CC range is now [0.0, 1.0]
297
+ SS -= S * S # Eq. 14, SS range is now [0.0, 0.5]
298
+
299
+ # to prevent division by zero errors with a and b, as well as correcting for
300
+ # numerical precision errors that lead to CC or SS being approximately -0.0,
301
+ # make sure CC and SS are both > 0
302
+ epsneg = np.finfo(dtype=y.dtype).epsneg
303
+ CC[CC < epsneg] = epsneg
304
+ SS[SS < epsneg] = epsneg
305
+
306
+ # calculate a and b
307
+ # where: y(w) = a*cos(w) + b*sin(w) + c
308
+ a = YC / CC # Eq. A.4 and 6, eliminating CS
309
+ b = YS / SS # Eq. A.4 and 6, eliminating CS
310
+ # c = Y - a * C - b * S
311
+
312
+ # store final value as power in A^2 (i.e., (y units)^2)
313
+ pgram = 2.0 * (a * YC + b * YS)
314
+
315
+ # squeeze back to a vector
316
+ pgram = np.squeeze(pgram)
317
+
318
+ if normalize == "power": # (default)
319
+ # return the legacy power units ((A**2) * N/4)
320
+
321
+ pgram *= float(x.shape[0]) / 4.0
322
+
323
+ elif normalize == "normalize":
324
+ # return the normalized power (power at current frequency wrt the entire signal)
325
+ # range will be [0, 1]
326
+
327
+ YY = np.dot(weights_y.T, y) # Eq. 10
328
+ if floating_mean:
329
+ YY -= Y * Y # Eq. 10
330
+
331
+ pgram *= 0.5 / np.squeeze(YY) # Eq. 20
332
+
333
+ else: # normalize == "amplitude":
334
+ # return the complex representation of the best-fit amplitude and phase
335
+
336
+ # squeeze back to vectors
337
+ a = np.squeeze(a)
338
+ b = np.squeeze(b)
339
+ tau = np.squeeze(tau)
340
+
341
+ # calculate the complex representation, and correct for tau rotation
342
+ pgram = (a + 1j * b) * np.exp(1j * tau)
343
+
344
+ return pgram
345
+
346
+
347
+ def periodogram(x, fs=1.0, window='boxcar', nfft=None, detrend='constant',
348
+ return_onesided=True, scaling='density', axis=-1):
349
+ """
350
+ Estimate power spectral density using a periodogram.
351
+
352
+ Parameters
353
+ ----------
354
+ x : array_like
355
+ Time series of measurement values
356
+ fs : float, optional
357
+ Sampling frequency of the `x` time series. Defaults to 1.0.
358
+ window : str or tuple or array_like, optional
359
+ Desired window to use. If `window` is a string or tuple, it is
360
+ passed to `get_window` to generate the window values, which are
361
+ DFT-even by default. See `get_window` for a list of windows and
362
+ required parameters. If `window` is array_like it will be used
363
+ directly as the window and its length must be equal to the length
364
+ of the axis over which the periodogram is computed. Defaults
365
+ to 'boxcar'.
366
+ nfft : int, optional
367
+ Length of the FFT used. If `None` the length of `x` will be
368
+ used.
369
+ detrend : str or function or `False`, optional
370
+ Specifies how to detrend each segment. If `detrend` is a
371
+ string, it is passed as the `type` argument to the `detrend`
372
+ function. If it is a function, it takes a segment and returns a
373
+ detrended segment. If `detrend` is `False`, no detrending is
374
+ done. Defaults to 'constant'.
375
+ return_onesided : bool, optional
376
+ If `True`, return a one-sided spectrum for real data. If
377
+ `False` return a two-sided spectrum. Defaults to `True`, but for
378
+ complex data, a two-sided spectrum is always returned.
379
+ scaling : { 'density', 'spectrum' }, optional
380
+ Selects between computing the power spectral density ('density')
381
+ where `Pxx` has units of V²/Hz and computing the squared magnitude
382
+ spectrum ('spectrum') where `Pxx` has units of V², if `x`
383
+ is measured in V and `fs` is measured in Hz. Defaults to
384
+ 'density'
385
+ axis : int, optional
386
+ Axis along which the periodogram is computed; the default is
387
+ over the last axis (i.e. ``axis=-1``).
388
+
389
+ Returns
390
+ -------
391
+ f : ndarray
392
+ Array of sample frequencies.
393
+ Pxx : ndarray
394
+ Power spectral density or power spectrum of `x`.
395
+
396
+ See Also
397
+ --------
398
+ welch: Estimate power spectral density using Welch's method
399
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
400
+
401
+ Notes
402
+ -----
403
+ The ratio of the squared magnitude (``scaling='spectrum'``) divided by the spectral
404
+ power density (``scaling='density'``) is the constant factor of
405
+ ``sum(abs(window)**2)*fs / abs(sum(window))**2``.
406
+ If `return_onesided` is ``True``, the values of the negative frequencies are added
407
+ to values of the corresponding positive ones.
408
+
409
+ Consult the :ref:`tutorial_SpectralAnalysis` section of the :ref:`user_guide`
410
+ for a discussion of the scalings of the power spectral density and
411
+ the magnitude (squared) spectrum.
412
+
413
+ .. versionadded:: 0.12.0
414
+
415
+ Examples
416
+ --------
417
+ >>> import numpy as np
418
+ >>> from scipy import signal
419
+ >>> import matplotlib.pyplot as plt
420
+ >>> rng = np.random.default_rng()
421
+
422
+ Generate a test signal, a 2 Vrms sine wave at 1234 Hz, corrupted by
423
+ 0.001 V**2/Hz of white noise sampled at 10 kHz.
424
+
425
+ >>> fs = 10e3
426
+ >>> N = 1e5
427
+ >>> amp = 2*np.sqrt(2)
428
+ >>> freq = 1234.0
429
+ >>> noise_power = 0.001 * fs / 2
430
+ >>> time = np.arange(N) / fs
431
+ >>> x = amp*np.sin(2*np.pi*freq*time)
432
+ >>> x += rng.normal(scale=np.sqrt(noise_power), size=time.shape)
433
+
434
+ Compute and plot the power spectral density.
435
+
436
+ >>> f, Pxx_den = signal.periodogram(x, fs)
437
+ >>> plt.semilogy(f, Pxx_den)
438
+ >>> plt.ylim([1e-7, 1e2])
439
+ >>> plt.xlabel('frequency [Hz]')
440
+ >>> plt.ylabel('PSD [V**2/Hz]')
441
+ >>> plt.show()
442
+
443
+ If we average the last half of the spectral density, to exclude the
444
+ peak, we can recover the noise power on the signal.
445
+
446
+ >>> np.mean(Pxx_den[25000:])
447
+ 0.000985320699252543
448
+
449
+ Now compute and plot the power spectrum.
450
+
451
+ >>> f, Pxx_spec = signal.periodogram(x, fs, 'flattop', scaling='spectrum')
452
+ >>> plt.figure()
453
+ >>> plt.semilogy(f, np.sqrt(Pxx_spec))
454
+ >>> plt.ylim([1e-4, 1e1])
455
+ >>> plt.xlabel('frequency [Hz]')
456
+ >>> plt.ylabel('Linear spectrum [V RMS]')
457
+ >>> plt.show()
458
+
459
+ The peak height in the power spectrum is an estimate of the RMS
460
+ amplitude.
461
+
462
+ >>> np.sqrt(Pxx_spec.max())
463
+ 2.0077340678640727
464
+
465
+ """
466
+ x = np.asarray(x)
467
+
468
+ if x.size == 0:
469
+ return np.empty(x.shape), np.empty(x.shape)
470
+
471
+ if window is None:
472
+ window = 'boxcar'
473
+
474
+ if nfft is None:
475
+ nperseg = x.shape[axis]
476
+ elif nfft == x.shape[axis]:
477
+ nperseg = nfft
478
+ elif nfft > x.shape[axis]:
479
+ nperseg = x.shape[axis]
480
+ elif nfft < x.shape[axis]:
481
+ s = [np.s_[:]]*len(x.shape)
482
+ s[axis] = np.s_[:nfft]
483
+ x = x[tuple(s)]
484
+ nperseg = nfft
485
+ nfft = None
486
+
487
+ if hasattr(window, 'size'):
488
+ if window.size != nperseg:
489
+ raise ValueError('the size of the window must be the same size '
490
+ 'of the input on the specified axis')
491
+
492
+ return welch(x, fs=fs, window=window, nperseg=nperseg, noverlap=0,
493
+ nfft=nfft, detrend=detrend, return_onesided=return_onesided,
494
+ scaling=scaling, axis=axis)
495
+
496
+
497
+ def welch(x, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None,
498
+ detrend='constant', return_onesided=True, scaling='density',
499
+ axis=-1, average='mean'):
500
+ r"""
501
+ Estimate power spectral density using Welch's method.
502
+
503
+ Welch's method [1]_ computes an estimate of the power spectral
504
+ density by dividing the data into overlapping segments, computing a
505
+ modified periodogram for each segment and averaging the
506
+ periodograms.
507
+
508
+ Parameters
509
+ ----------
510
+ x : array_like
511
+ Time series of measurement values
512
+ fs : float, optional
513
+ Sampling frequency of the `x` time series. Defaults to 1.0.
514
+ window : str or tuple or array_like, optional
515
+ Desired window to use. If `window` is a string or tuple, it is
516
+ passed to `get_window` to generate the window values, which are
517
+ DFT-even by default. See `get_window` for a list of windows and
518
+ required parameters. If `window` is array_like it will be used
519
+ directly as the window and its length must be nperseg. Defaults
520
+ to a Hann window.
521
+ nperseg : int, optional
522
+ Length of each segment. Defaults to None, but if window is str or
523
+ tuple, is set to 256, and if window is array_like, is set to the
524
+ length of the window.
525
+ noverlap : int, optional
526
+ Number of points to overlap between segments. If `None`,
527
+ ``noverlap = nperseg // 2``. Defaults to `None`.
528
+ nfft : int, optional
529
+ Length of the FFT used, if a zero padded FFT is desired. If
530
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
531
+ detrend : str or function or `False`, optional
532
+ Specifies how to detrend each segment. If `detrend` is a
533
+ string, it is passed as the `type` argument to the `detrend`
534
+ function. If it is a function, it takes a segment and returns a
535
+ detrended segment. If `detrend` is `False`, no detrending is
536
+ done. Defaults to 'constant'.
537
+ return_onesided : bool, optional
538
+ If `True`, return a one-sided spectrum for real data. If
539
+ `False` return a two-sided spectrum. Defaults to `True`, but for
540
+ complex data, a two-sided spectrum is always returned.
541
+ scaling : { 'density', 'spectrum' }, optional
542
+ Selects between computing the power spectral density ('density')
543
+ where `Pxx` has units of V**2/Hz and computing the squared magnitude
544
+ spectrum ('spectrum') where `Pxx` has units of V**2, if `x`
545
+ is measured in V and `fs` is measured in Hz. Defaults to
546
+ 'density'
547
+ axis : int, optional
548
+ Axis along which the periodogram is computed; the default is
549
+ over the last axis (i.e. ``axis=-1``).
550
+ average : { 'mean', 'median' }, optional
551
+ Method to use when averaging periodograms. Defaults to 'mean'.
552
+
553
+ .. versionadded:: 1.2.0
554
+
555
+ Returns
556
+ -------
557
+ f : ndarray
558
+ Array of sample frequencies.
559
+ Pxx : ndarray
560
+ Power spectral density or power spectrum of x.
561
+
562
+ See Also
563
+ --------
564
+ csd: Cross power spectral density using Welch's method
565
+ periodogram: Simple, optionally modified periodogram
566
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
567
+
568
+ Notes
569
+ -----
570
+ An appropriate amount of overlap will depend on the choice of window
571
+ and on your requirements. For the default Hann window an overlap of
572
+ 50% is a reasonable trade-off between accurately estimating the
573
+ signal power, while not over counting any of the data. Narrower
574
+ windows may require a larger overlap. If `noverlap` is 0, this
575
+ method is equivalent to Bartlett's method [2]_.
576
+
577
+ The ratio of the squared magnitude (``scaling='spectrum'``) divided by the spectral
578
+ power density (``scaling='density'``) is the constant factor of
579
+ ``sum(abs(window)**2)*fs / abs(sum(window))**2``.
580
+ If `return_onesided` is ``True``, the values of the negative frequencies are added
581
+ to values of the corresponding positive ones.
582
+
583
+ Consult the :ref:`tutorial_SpectralAnalysis` section of the :ref:`user_guide`
584
+ for a discussion of the scalings of the power spectral density and
585
+ the (squared) magnitude spectrum.
586
+
587
+ .. versionadded:: 0.12.0
588
+
589
+ References
590
+ ----------
591
+ .. [1] P. Welch, "The use of the fast Fourier transform for the
592
+ estimation of power spectra: A method based on time averaging
593
+ over short, modified periodograms", IEEE Trans. Audio
594
+ Electroacoust. vol. 15, pp. 70-73, 1967.
595
+ .. [2] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra",
596
+ Biometrika, vol. 37, pp. 1-16, 1950.
597
+
598
+ Examples
599
+ --------
600
+ >>> import numpy as np
601
+ >>> from scipy import signal
602
+ >>> import matplotlib.pyplot as plt
603
+ >>> rng = np.random.default_rng()
604
+
605
+ Generate a test signal, a 2 Vrms sine wave at 1234 Hz, corrupted by
606
+ 0.001 V**2/Hz of white noise sampled at 10 kHz.
607
+
608
+ >>> fs = 10e3
609
+ >>> N = 1e5
610
+ >>> amp = 2*np.sqrt(2)
611
+ >>> freq = 1234.0
612
+ >>> noise_power = 0.001 * fs / 2
613
+ >>> time = np.arange(N) / fs
614
+ >>> x = amp*np.sin(2*np.pi*freq*time)
615
+ >>> x += rng.normal(scale=np.sqrt(noise_power), size=time.shape)
616
+
617
+ Compute and plot the power spectral density.
618
+
619
+ >>> f, Pxx_den = signal.welch(x, fs, nperseg=1024)
620
+ >>> plt.semilogy(f, Pxx_den)
621
+ >>> plt.ylim([0.5e-3, 1])
622
+ >>> plt.xlabel('frequency [Hz]')
623
+ >>> plt.ylabel('PSD [V**2/Hz]')
624
+ >>> plt.show()
625
+
626
+ If we average the last half of the spectral density, to exclude the
627
+ peak, we can recover the noise power on the signal.
628
+
629
+ >>> np.mean(Pxx_den[256:])
630
+ 0.0009924865443739191
631
+
632
+ Now compute and plot the power spectrum.
633
+
634
+ >>> f, Pxx_spec = signal.welch(x, fs, 'flattop', 1024, scaling='spectrum')
635
+ >>> plt.figure()
636
+ >>> plt.semilogy(f, np.sqrt(Pxx_spec))
637
+ >>> plt.xlabel('frequency [Hz]')
638
+ >>> plt.ylabel('Linear spectrum [V RMS]')
639
+ >>> plt.show()
640
+
641
+ The peak height in the power spectrum is an estimate of the RMS
642
+ amplitude.
643
+
644
+ >>> np.sqrt(Pxx_spec.max())
645
+ 2.0077340678640727
646
+
647
+ If we now introduce a discontinuity in the signal, by increasing the
648
+ amplitude of a small portion of the signal by 50, we can see the
649
+ corruption of the mean average power spectral density, but using a
650
+ median average better estimates the normal behaviour.
651
+
652
+ >>> x[int(N//2):int(N//2)+10] *= 50.
653
+ >>> f, Pxx_den = signal.welch(x, fs, nperseg=1024)
654
+ >>> f_med, Pxx_den_med = signal.welch(x, fs, nperseg=1024, average='median')
655
+ >>> plt.semilogy(f, Pxx_den, label='mean')
656
+ >>> plt.semilogy(f_med, Pxx_den_med, label='median')
657
+ >>> plt.ylim([0.5e-3, 1])
658
+ >>> plt.xlabel('frequency [Hz]')
659
+ >>> plt.ylabel('PSD [V**2/Hz]')
660
+ >>> plt.legend()
661
+ >>> plt.show()
662
+
663
+ """
664
+ freqs, Pxx = csd(x, x, fs=fs, window=window, nperseg=nperseg,
665
+ noverlap=noverlap, nfft=nfft, detrend=detrend,
666
+ return_onesided=return_onesided, scaling=scaling,
667
+ axis=axis, average=average)
668
+
669
+ return freqs, Pxx.real
670
+
671
+
672
+ def csd(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None,
673
+ detrend='constant', return_onesided=True, scaling='density',
674
+ axis=-1, average='mean'):
675
+ r"""
676
+ Estimate the cross power spectral density, Pxy, using Welch's method.
677
+
678
+ Parameters
679
+ ----------
680
+ x : array_like
681
+ Time series of measurement values
682
+ y : array_like
683
+ Time series of measurement values
684
+ fs : float, optional
685
+ Sampling frequency of the `x` and `y` time series. Defaults
686
+ to 1.0.
687
+ window : str or tuple or array_like, optional
688
+ Desired window to use. If `window` is a string or tuple, it is
689
+ passed to `get_window` to generate the window values, which are
690
+ DFT-even by default. See `get_window` for a list of windows and
691
+ required parameters. If `window` is array_like it will be used
692
+ directly as the window and its length must be nperseg. Defaults
693
+ to a Hann window.
694
+ nperseg : int, optional
695
+ Length of each segment. Defaults to None, but if window is str or
696
+ tuple, is set to 256, and if window is array_like, is set to the
697
+ length of the window.
698
+ noverlap: int, optional
699
+ Number of points to overlap between segments. If `None`,
700
+ ``noverlap = nperseg // 2``. Defaults to `None` and may
701
+ not be greater than `nperseg`.
702
+ nfft : int, optional
703
+ Length of the FFT used, if a zero padded FFT is desired. If
704
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
705
+ detrend : str or function or `False`, optional
706
+ Specifies how to detrend each segment. If `detrend` is a
707
+ string, it is passed as the `type` argument to the `detrend`
708
+ function. If it is a function, it takes a segment and returns a
709
+ detrended segment. If `detrend` is `False`, no detrending is
710
+ done. Defaults to 'constant'.
711
+ return_onesided : bool, optional
712
+ If `True`, return a one-sided spectrum for real data. If
713
+ `False` return a two-sided spectrum. Defaults to `True`, but for
714
+ complex data, a two-sided spectrum is always returned.
715
+ scaling : { 'density', 'spectrum' }, optional
716
+ Selects between computing the cross spectral density ('density')
717
+ where `Pxy` has units of V**2/Hz and computing the cross spectrum
718
+ ('spectrum') where `Pxy` has units of V**2, if `x` and `y` are
719
+ measured in V and `fs` is measured in Hz. Defaults to 'density'
720
+ axis : int, optional
721
+ Axis along which the CSD is computed for both inputs; the
722
+ default is over the last axis (i.e. ``axis=-1``).
723
+ average : { 'mean', 'median' }, optional
724
+ Method to use when averaging periodograms. If the spectrum is
725
+ complex, the average is computed separately for the real and
726
+ imaginary parts. Defaults to 'mean'.
727
+
728
+ .. versionadded:: 1.2.0
729
+
730
+ Returns
731
+ -------
732
+ f : ndarray
733
+ Array of sample frequencies.
734
+ Pxy : ndarray
735
+ Cross spectral density or cross power spectrum of x,y.
736
+
737
+ See Also
738
+ --------
739
+ periodogram: Simple, optionally modified periodogram
740
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
741
+ welch: Power spectral density by Welch's method. [Equivalent to
742
+ csd(x,x)]
743
+ coherence: Magnitude squared coherence by Welch's method.
744
+
745
+ Notes
746
+ -----
747
+ By convention, Pxy is computed with the conjugate FFT of X
748
+ multiplied by the FFT of Y.
749
+
750
+ If the input series differ in length, the shorter series will be
751
+ zero-padded to match.
752
+
753
+ An appropriate amount of overlap will depend on the choice of window
754
+ and on your requirements. For the default Hann window an overlap of
755
+ 50% is a reasonable trade-off between accurately estimating the
756
+ signal power, while not over counting any of the data. Narrower
757
+ windows may require a larger overlap.
758
+
759
+ The ratio of the cross spectrum (``scaling='spectrum'``) divided by the cross
760
+ spectral density (``scaling='density'``) is the constant factor of
761
+ ``sum(abs(window)**2)*fs / abs(sum(window))**2``.
762
+ If `return_onesided` is ``True``, the values of the negative frequencies are added
763
+ to values of the corresponding positive ones.
764
+
765
+ Consult the :ref:`tutorial_SpectralAnalysis` section of the :ref:`user_guide`
766
+ for a discussion of the scalings of a spectral density and an (amplitude) spectrum.
767
+
768
+ Welch's method may be interpreted as taking the average over the time slices of a
769
+ (cross-) spectrogram. Internally, this function utilizes the `ShortTimeFFT` to
770
+ determine the required (cross-) spectrogram. An example below illustrates that it
771
+ is straightforward to calculate `Pxy` directly with the `ShortTimeFFT`. However,
772
+ there are some notable differences in the behavior of the `ShortTimeFFT`:
773
+
774
+ * There is no direct `ShortTimeFFT` equivalent for the `csd` parameter
775
+ combination ``return_onesided=True, scaling='density'``, since
776
+ ``fft_mode='onesided2X'`` requires ``'psd'`` scaling. The is due to `csd`
777
+ returning the doubled squared magnitude in this case, which does not have a
778
+ sensible interpretation.
779
+ * `ShortTimeFFT` uses `float64` / `complex128` internally, which is due to the
780
+ behavior of the utilized `~scipy.fft` module. Thus, those are the dtypes being
781
+ returned. The `csd` function casts the return values to `float32` / `complex64`
782
+ if the input is `float32` / `complex64` as well.
783
+ * The `csd` function calculates ``np.conj(Sx[q,p]) * Sy[q,p]``, whereas
784
+ `~ShortTimeFFT.spectrogram` calculates ``Sx[q,p] * np.conj(Sy[q,p])`` where
785
+ ``Sx[q,p]``, ``Sy[q,p]`` are the STFTs of `x` and `y`. Also, the window
786
+ positioning is different.
787
+
788
+ .. versionadded:: 0.16.0
789
+
790
+ References
791
+ ----------
792
+ .. [1] P. Welch, "The use of the fast Fourier transform for the
793
+ estimation of power spectra: A method based on time averaging
794
+ over short, modified periodograms", IEEE Trans. Audio
795
+ Electroacoust. vol. 15, pp. 70-73, 1967.
796
+ .. [2] Rabiner, Lawrence R., and B. Gold. "Theory and Application of
797
+ Digital Signal Processing" Prentice-Hall, pp. 414-419, 1975
798
+
799
+ Examples
800
+ --------
801
+ The following example plots the cross power spectral density of two signals with
802
+ some common features:
803
+
804
+ >>> import numpy as np
805
+ >>> from scipy import signal
806
+ >>> import matplotlib.pyplot as plt
807
+ >>> rng = np.random.default_rng()
808
+ ...
809
+ ... # Generate two test signals with some common features:
810
+ >>> N, fs = 100_000, 10e3 # number of samples and sampling frequency
811
+ >>> amp, freq = 20, 1234.0 # amplitude and frequency of utilized sine signal
812
+ >>> noise_power = 0.001 * fs / 2
813
+ >>> time = np.arange(N) / fs
814
+ >>> b, a = signal.butter(2, 0.25, 'low')
815
+ >>> x = rng.normal(scale=np.sqrt(noise_power), size=time.shape)
816
+ >>> y = signal.lfilter(b, a, x)
817
+ >>> x += amp*np.sin(2*np.pi*freq*time)
818
+ >>> y += rng.normal(scale=0.1*np.sqrt(noise_power), size=time.shape)
819
+ ...
820
+ ... # Compute and plot the magnitude of the cross spectral density:
821
+ >>> nperseg, noverlap, win = 1024, 512, 'hann'
822
+ >>> f, Pxy = signal.csd(x, y, fs, win, nperseg, noverlap)
823
+ >>> fig0, ax0 = plt.subplots(tight_layout=True)
824
+ >>> ax0.set_title(f"CSD ({win.title()}-window, {nperseg=}, {noverlap=})")
825
+ >>> ax0.set(xlabel="Frequency $f$ in kHz", ylabel="CSD Magnitude in V²/Hz")
826
+ >>> ax0.semilogy(f/1e3, np.abs(Pxy))
827
+ >>> ax0.grid()
828
+ >>> plt.show()
829
+
830
+ The cross spectral density is calculated by taking the average over the time slices
831
+ of a spectrogram:
832
+
833
+ >>> SFT = signal.ShortTimeFFT.from_window('hann', fs, nperseg, noverlap,
834
+ ... scale_to='psd', fft_mode='onesided2X',
835
+ ... phase_shift=None)
836
+ >>> Sxy1 = SFT.spectrogram(y, x, detr='constant', k_offset=nperseg//2,
837
+ ... p0=0, p1=(N-noverlap) // SFT.hop)
838
+ >>> Pxy1 = Sxy1.mean(axis=-1)
839
+ >>> np.allclose(Pxy, Pxy1) # same result as with csd()
840
+ True
841
+
842
+ As discussed in the Notes section, the results of using an approach analogous to
843
+ the code snippet above and the `csd` function may deviate due to implementation
844
+ details.
845
+
846
+ Note that the code snippet above can be easily adapted to determine other
847
+ statistical properties than the mean value.
848
+ """
849
+ # The following lines are resembling the behavior of the originally utilized
850
+ # `_spectral_helper()` function:
851
+ same_data, axis = y is x, int(axis)
852
+ x = np.asarray(x)
853
+
854
+ if not same_data:
855
+ y = np.asarray(y)
856
+ # Check if we can broadcast the outer axes together
857
+ x_outer, y_outer = list(x.shape), list(y.shape)
858
+ x_outer.pop(axis)
859
+ y_outer.pop(axis)
860
+ try:
861
+ outer_shape = np.broadcast_shapes(x_outer, y_outer)
862
+ except ValueError as e:
863
+ raise ValueError('x and y cannot be broadcast together.') from e
864
+ if x.size == 0 or y.size == 0:
865
+ out_shape = outer_shape + (min([x.shape[axis], y.shape[axis]]),)
866
+ empty_out = np.moveaxis(np.empty(out_shape), -1, axis)
867
+ return empty_out, empty_out
868
+ out_dtype = np.result_type(x, y, np.complex64)
869
+ else: # x is y:
870
+ if x.size == 0:
871
+ return np.empty(x.shape), np.empty(x.shape)
872
+ out_dtype = np.result_type(x, np.complex64)
873
+
874
+ n = x.shape[axis] if same_data else max(x.shape[axis], y.shape[axis])
875
+ if isinstance(window, str) or isinstance(window, tuple):
876
+ nperseg = int(nperseg) if nperseg is not None else 256
877
+ if nperseg < 1:
878
+ raise ValueError(f"Parameter {nperseg=} is not a positive integer!")
879
+ elif n < nperseg:
880
+ warnings.warn(f"{nperseg=} is greater than signal length max(len(x), " +
881
+ f"len(y)) = {n}, using nperseg = {n}", stacklevel=3)
882
+ nperseg = n
883
+ win = get_window(window, nperseg)
884
+ else:
885
+ win = np.asarray(window)
886
+ if nperseg is None:
887
+ nperseg = len(win)
888
+ if nperseg != len(win):
889
+ raise ValueError(f"{nperseg=} does not equal {len(win)=}")
890
+
891
+ nfft = int(nfft) if nfft is not None else nperseg
892
+ if nfft < nperseg:
893
+ raise ValueError(f"{nfft=} must be greater than or equal to {nperseg=}!")
894
+ noverlap = int(noverlap) if noverlap is not None else nperseg // 2
895
+ if noverlap >= nperseg:
896
+ raise ValueError(f"{noverlap=} must be less than {nperseg=}!")
897
+ if np.iscomplexobj(x) and return_onesided:
898
+ return_onesided = False
899
+
900
+ if x.shape[axis] < y.shape[axis]: # zero-pad x to shape of y:
901
+ z_shape = list(y.shape)
902
+ z_shape[axis] = y.shape[axis] - x.shape[axis]
903
+ x = np.concatenate((x, np.zeros(z_shape)), axis=axis)
904
+ elif y.shape[axis] < x.shape[axis]: # zero-pad y to shape of x:
905
+ z_shape = list(x.shape)
906
+ z_shape[axis] = x.shape[axis] - y.shape[axis]
907
+ y = np.concatenate((y, np.zeros(z_shape)), axis=axis)
908
+
909
+ # using cast() to make mypy happy:
910
+ fft_mode = cast(FFT_MODE_TYPE, 'onesided' if return_onesided else 'twosided')
911
+ if scaling not in (scales := {'spectrum': 'magnitude', 'density': 'psd'}):
912
+ raise ValueError(f"Parameter {scaling=} not in {scales}!")
913
+
914
+ SFT = ShortTimeFFT(win, nperseg - noverlap, fs, fft_mode=fft_mode, mfft=nfft,
915
+ scale_to=scales[scaling], phase_shift=None)
916
+ # csd() calculates X.conj()*Y instead of X*Y.conj():
917
+ Pxy = SFT.spectrogram(y, x, detr=None if detrend is False else detrend,
918
+ p0=0, p1=(n - noverlap) // SFT.hop, k_offset=nperseg // 2,
919
+ axis=axis)
920
+
921
+ # Note:
922
+ # 'onesided2X' scaling of ShortTimeFFT conflicts with the
923
+ # scaling='spectrum' parameter, since it doubles the squared magnitude,
924
+ # which in the view of the ShortTimeFFT implementation does not make sense.
925
+ # Hence, the doubling of the square is implemented here:
926
+ if return_onesided:
927
+ f_axis = Pxy.ndim - 1 + axis if axis < 0 else axis
928
+ Pxy = np.moveaxis(Pxy, f_axis, -1)
929
+ Pxy[..., 1:-1 if SFT.mfft % 2 == 0 else None] *= 2
930
+ Pxy = np.moveaxis(Pxy, -1, f_axis)
931
+
932
+ # Average over windows.
933
+ if Pxy.shape[-1] > 1:
934
+ if average == 'median':
935
+ # np.median must be passed real arrays for the desired result
936
+ bias = _median_bias(Pxy.shape[-1])
937
+ if np.iscomplexobj(Pxy):
938
+ Pxy = (np.median(np.real(Pxy), axis=-1) +
939
+ np.median(np.imag(Pxy), axis=-1) * 1j)
940
+ else:
941
+ Pxy = np.median(Pxy, axis=-1)
942
+ Pxy /= bias
943
+ elif average == 'mean':
944
+ Pxy = Pxy.mean(axis=-1)
945
+ else:
946
+ raise ValueError(f"Parameter {average=} must be 'median' or 'mean'!")
947
+ else:
948
+ Pxy = np.reshape(Pxy, Pxy.shape[:-1])
949
+
950
+ # cast output type;
951
+ Pxy = Pxy.astype(out_dtype)
952
+ if same_data:
953
+ Pxy = Pxy.real
954
+ return SFT.f, Pxy
955
+
956
+
957
+ def spectrogram(x, fs=1.0, window=('tukey', .25), nperseg=None, noverlap=None,
958
+ nfft=None, detrend='constant', return_onesided=True,
959
+ scaling='density', axis=-1, mode='psd'):
960
+ """Compute a spectrogram with consecutive Fourier transforms (legacy function).
961
+
962
+ Spectrograms can be used as a way of visualizing the change of a
963
+ nonstationary signal's frequency content over time.
964
+
965
+ .. legacy:: function
966
+
967
+ :class:`ShortTimeFFT` is a newer STFT / ISTFT implementation with more
968
+ features also including a :meth:`~ShortTimeFFT.spectrogram` method.
969
+ A :ref:`comparison <tutorial_stft_legacy_stft>` between the
970
+ implementations can be found in the :ref:`tutorial_stft` section of
971
+ the :ref:`user_guide`.
972
+
973
+ Parameters
974
+ ----------
975
+ x : array_like
976
+ Time series of measurement values
977
+ fs : float, optional
978
+ Sampling frequency of the `x` time series. Defaults to 1.0.
979
+ window : str or tuple or array_like, optional
980
+ Desired window to use. If `window` is a string or tuple, it is
981
+ passed to `get_window` to generate the window values, which are
982
+ DFT-even by default. See `get_window` for a list of windows and
983
+ required parameters. If `window` is array_like it will be used
984
+ directly as the window and its length must be nperseg.
985
+ Defaults to a Tukey window with shape parameter of 0.25.
986
+ nperseg : int, optional
987
+ Length of each segment. Defaults to None, but if window is str or
988
+ tuple, is set to 256, and if window is array_like, is set to the
989
+ length of the window.
990
+ noverlap : int, optional
991
+ Number of points to overlap between segments. If `None`,
992
+ ``noverlap = nperseg // 8``. Defaults to `None`.
993
+ nfft : int, optional
994
+ Length of the FFT used, if a zero padded FFT is desired. If
995
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
996
+ detrend : str or function or `False`, optional
997
+ Specifies how to detrend each segment. If `detrend` is a
998
+ string, it is passed as the `type` argument to the `detrend`
999
+ function. If it is a function, it takes a segment and returns a
1000
+ detrended segment. If `detrend` is `False`, no detrending is
1001
+ done. Defaults to 'constant'.
1002
+ return_onesided : bool, optional
1003
+ If `True`, return a one-sided spectrum for real data. If
1004
+ `False` return a two-sided spectrum. Defaults to `True`, but for
1005
+ complex data, a two-sided spectrum is always returned.
1006
+ scaling : { 'density', 'spectrum' }, optional
1007
+ Selects between computing the power spectral density ('density')
1008
+ where `Sxx` has units of V**2/Hz and computing the power
1009
+ spectrum ('spectrum') where `Sxx` has units of V**2, if `x`
1010
+ is measured in V and `fs` is measured in Hz. Defaults to
1011
+ 'density'.
1012
+ axis : int, optional
1013
+ Axis along which the spectrogram is computed; the default is over
1014
+ the last axis (i.e. ``axis=-1``).
1015
+ mode : str, optional
1016
+ Defines what kind of return values are expected. Options are
1017
+ ['psd', 'complex', 'magnitude', 'angle', 'phase']. 'complex' is
1018
+ equivalent to the output of `stft` with no padding or boundary
1019
+ extension. 'magnitude' returns the absolute magnitude of the
1020
+ STFT. 'angle' and 'phase' return the complex angle of the STFT,
1021
+ with and without unwrapping, respectively.
1022
+
1023
+ Returns
1024
+ -------
1025
+ f : ndarray
1026
+ Array of sample frequencies.
1027
+ t : ndarray
1028
+ Array of segment times.
1029
+ Sxx : ndarray
1030
+ Spectrogram of x. By default, the last axis of Sxx corresponds
1031
+ to the segment times.
1032
+
1033
+ See Also
1034
+ --------
1035
+ periodogram: Simple, optionally modified periodogram
1036
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
1037
+ welch: Power spectral density by Welch's method.
1038
+ csd: Cross spectral density by Welch's method.
1039
+ ShortTimeFFT: Newer STFT/ISTFT implementation providing more features,
1040
+ which also includes a :meth:`~ShortTimeFFT.spectrogram`
1041
+ method.
1042
+
1043
+ Notes
1044
+ -----
1045
+ An appropriate amount of overlap will depend on the choice of window
1046
+ and on your requirements. In contrast to welch's method, where the
1047
+ entire data stream is averaged over, one may wish to use a smaller
1048
+ overlap (or perhaps none at all) when computing a spectrogram, to
1049
+ maintain some statistical independence between individual segments.
1050
+ It is for this reason that the default window is a Tukey window with
1051
+ 1/8th of a window's length overlap at each end.
1052
+
1053
+
1054
+ .. versionadded:: 0.16.0
1055
+
1056
+ References
1057
+ ----------
1058
+ .. [1] Oppenheim, Alan V., Ronald W. Schafer, John R. Buck
1059
+ "Discrete-Time Signal Processing", Prentice Hall, 1999.
1060
+
1061
+ Examples
1062
+ --------
1063
+ >>> import numpy as np
1064
+ >>> from scipy import signal
1065
+ >>> from scipy.fft import fftshift
1066
+ >>> import matplotlib.pyplot as plt
1067
+ >>> rng = np.random.default_rng()
1068
+
1069
+ Generate a test signal, a 2 Vrms sine wave whose frequency is slowly
1070
+ modulated around 3kHz, corrupted by white noise of exponentially
1071
+ decreasing magnitude sampled at 10 kHz.
1072
+
1073
+ >>> fs = 10e3
1074
+ >>> N = 1e5
1075
+ >>> amp = 2 * np.sqrt(2)
1076
+ >>> noise_power = 0.01 * fs / 2
1077
+ >>> time = np.arange(N) / float(fs)
1078
+ >>> mod = 500*np.cos(2*np.pi*0.25*time)
1079
+ >>> carrier = amp * np.sin(2*np.pi*3e3*time + mod)
1080
+ >>> noise = rng.normal(scale=np.sqrt(noise_power), size=time.shape)
1081
+ >>> noise *= np.exp(-time/5)
1082
+ >>> x = carrier + noise
1083
+
1084
+ Compute and plot the spectrogram.
1085
+
1086
+ >>> f, t, Sxx = signal.spectrogram(x, fs)
1087
+ >>> plt.pcolormesh(t, f, Sxx, shading='gouraud')
1088
+ >>> plt.ylabel('Frequency [Hz]')
1089
+ >>> plt.xlabel('Time [sec]')
1090
+ >>> plt.show()
1091
+
1092
+ Note, if using output that is not one sided, then use the following:
1093
+
1094
+ >>> f, t, Sxx = signal.spectrogram(x, fs, return_onesided=False)
1095
+ >>> plt.pcolormesh(t, fftshift(f), fftshift(Sxx, axes=0), shading='gouraud')
1096
+ >>> plt.ylabel('Frequency [Hz]')
1097
+ >>> plt.xlabel('Time [sec]')
1098
+ >>> plt.show()
1099
+
1100
+ """
1101
+ modelist = ['psd', 'complex', 'magnitude', 'angle', 'phase']
1102
+ if mode not in modelist:
1103
+ raise ValueError(f'unknown value for mode {mode}, must be one of {modelist}')
1104
+
1105
+ # need to set default for nperseg before setting default for noverlap below
1106
+ window, nperseg = _triage_segments(window, nperseg,
1107
+ input_length=x.shape[axis])
1108
+
1109
+ # Less overlap than welch, so samples are more statistically independent
1110
+ if noverlap is None:
1111
+ noverlap = nperseg // 8
1112
+
1113
+ if mode == 'psd':
1114
+ freqs, time, Sxx = _spectral_helper(x, x, fs, window, nperseg,
1115
+ noverlap, nfft, detrend,
1116
+ return_onesided, scaling, axis,
1117
+ mode='psd')
1118
+
1119
+ else:
1120
+ freqs, time, Sxx = _spectral_helper(x, x, fs, window, nperseg,
1121
+ noverlap, nfft, detrend,
1122
+ return_onesided, scaling, axis,
1123
+ mode='stft')
1124
+
1125
+ if mode == 'magnitude':
1126
+ Sxx = np.abs(Sxx)
1127
+ elif mode in ['angle', 'phase']:
1128
+ Sxx = np.angle(Sxx)
1129
+ if mode == 'phase':
1130
+ # Sxx has one additional dimension for time strides
1131
+ if axis < 0:
1132
+ axis -= 1
1133
+ Sxx = np.unwrap(Sxx, axis=axis)
1134
+
1135
+ # mode =='complex' is same as `stft`, doesn't need modification
1136
+
1137
+ return freqs, time, Sxx
1138
+
1139
+
1140
+ def check_COLA(window, nperseg, noverlap, tol=1e-10):
1141
+ r"""Check whether the Constant OverLap Add (COLA) constraint is met
1142
+ (legacy function).
1143
+
1144
+ .. legacy:: function
1145
+
1146
+ The COLA constraint is equivalent of having a constant dual window, i.e.,
1147
+ ``all(ShortTimeFFT.dual_win == ShortTimeFFT.dual_win[0])``. Hence,
1148
+ `closest_STFT_dual_window` generalizes this function, as the following
1149
+ example shows:
1150
+
1151
+ >>> import numpy as np
1152
+ >>> from scipy.signal import check_COLA, closest_STFT_dual_window, windows
1153
+ ...
1154
+ >>> w, w_rect, hop = windows.hann(12, sym=False), np.ones(12), 6
1155
+ >>> dual_win, alpha = closest_STFT_dual_window(w, hop, w_rect, scaled=True)
1156
+ >>> np.allclose(dual_win/alpha, w_rect, atol=1e-10, rtol=0)
1157
+ True
1158
+ >>> check_COLA(w, len(w), len(w) - hop) # equivalent legacy function call
1159
+ True
1160
+
1161
+
1162
+ Parameters
1163
+ ----------
1164
+ window : str or tuple or array_like
1165
+ Desired window to use. If `window` is a string or tuple, it is
1166
+ passed to `get_window` to generate the window values, which are
1167
+ DFT-even by default. See `get_window` for a list of windows and
1168
+ required parameters. If `window` is array_like it will be used
1169
+ directly as the window and its length must be nperseg.
1170
+ nperseg : int
1171
+ Length of each segment.
1172
+ noverlap : int
1173
+ Number of points to overlap between segments.
1174
+ tol : float, optional
1175
+ The allowed variance of a bin's weighted sum from the median bin
1176
+ sum.
1177
+
1178
+ Returns
1179
+ -------
1180
+ verdict : bool
1181
+ `True` if chosen combination satisfies COLA within `tol`,
1182
+ `False` otherwise
1183
+
1184
+ See Also
1185
+ --------
1186
+ closest_STFT_dual_window: Allows determining the closest window meeting the
1187
+ COLA constraint for a given window
1188
+ check_NOLA: Check whether the Nonzero Overlap Add (NOLA) constraint is met
1189
+ ShortTimeFFT: Provide short-time Fourier transform and its inverse
1190
+ stft: Short-time Fourier transform (legacy)
1191
+ istft: Inverse Short-time Fourier transform (legacy)
1192
+
1193
+ Notes
1194
+ -----
1195
+ In order to invert a short-time Fourier transfrom (STFT) with the so-called
1196
+ "overlap-add method", the signal windowing must obey the constraint of
1197
+ "Constant OverLap Add" (COLA). This ensures that every point in the input
1198
+ data is equally weighted, thereby avoiding aliasing and allowing full
1199
+ reconstruction. Note that the algorithms implemented in `ShortTimeFFT.istft`
1200
+ and in `istft` (legacy) only require that the weaker "nonzero overlap-add"
1201
+ condition (as in `check_NOLA`) is met.
1202
+
1203
+ Some examples of windows that satisfy COLA:
1204
+ - Rectangular window at overlap of 0, 1/2, 2/3, 3/4, ...
1205
+ - Bartlett window at overlap of 1/2, 3/4, 5/6, ...
1206
+ - Hann window at 1/2, 2/3, 3/4, ...
1207
+ - Any Blackman family window at 2/3 overlap
1208
+ - Any window with ``noverlap = nperseg-1``
1209
+
1210
+ A very comprehensive list of other windows may be found in [2]_,
1211
+ wherein the COLA condition is satisfied when the "Amplitude
1212
+ Flatness" is unity.
1213
+
1214
+ .. versionadded:: 0.19.0
1215
+
1216
+ References
1217
+ ----------
1218
+ .. [1] Julius O. Smith III, "Spectral Audio Signal Processing", W3K
1219
+ Publishing, 2011,ISBN 978-0-9745607-3-1.
1220
+ .. [2] G. Heinzel, A. Ruediger and R. Schilling, "Spectrum and
1221
+ spectral density estimation by the Discrete Fourier transform
1222
+ (DFT), including a comprehensive list of window functions and
1223
+ some new at-top windows", 2002,
1224
+ http://hdl.handle.net/11858/00-001M-0000-0013-557A-5
1225
+
1226
+ Examples
1227
+ --------
1228
+ >>> from scipy import signal
1229
+
1230
+ Confirm COLA condition for rectangular window of 75% (3/4) overlap:
1231
+
1232
+ >>> signal.check_COLA(signal.windows.boxcar(100), 100, 75)
1233
+ True
1234
+
1235
+ COLA is not true for 25% (1/4) overlap, though:
1236
+
1237
+ >>> signal.check_COLA(signal.windows.boxcar(100), 100, 25)
1238
+ False
1239
+
1240
+ "Symmetrical" Hann window (for filter design) is not COLA:
1241
+
1242
+ >>> signal.check_COLA(signal.windows.hann(120, sym=True), 120, 60)
1243
+ False
1244
+
1245
+ "Periodic" or "DFT-even" Hann window (for FFT analysis) is COLA for
1246
+ overlap of 1/2, 2/3, 3/4, etc.:
1247
+
1248
+ >>> signal.check_COLA(signal.windows.hann(120, sym=False), 120, 60)
1249
+ True
1250
+
1251
+ >>> signal.check_COLA(signal.windows.hann(120, sym=False), 120, 80)
1252
+ True
1253
+
1254
+ >>> signal.check_COLA(signal.windows.hann(120, sym=False), 120, 90)
1255
+ True
1256
+
1257
+ """
1258
+ nperseg = int(nperseg)
1259
+
1260
+ if nperseg < 1:
1261
+ raise ValueError('nperseg must be a positive integer')
1262
+
1263
+ if noverlap >= nperseg:
1264
+ raise ValueError('noverlap must be less than nperseg.')
1265
+ noverlap = int(noverlap)
1266
+
1267
+ if isinstance(window, str) or type(window) is tuple:
1268
+ win = get_window(window, nperseg)
1269
+ else:
1270
+ win = np.asarray(window)
1271
+ if len(win.shape) != 1:
1272
+ raise ValueError('window must be 1-D')
1273
+ if win.shape[0] != nperseg:
1274
+ raise ValueError('window must have length of nperseg')
1275
+
1276
+ step = nperseg - noverlap
1277
+ binsums = sum(win[ii*step:(ii+1)*step] for ii in range(nperseg//step))
1278
+
1279
+ if nperseg % step != 0:
1280
+ binsums[:nperseg % step] += win[-(nperseg % step):]
1281
+
1282
+ deviation = binsums - np.median(binsums)
1283
+ return np.max(np.abs(deviation)) < tol
1284
+
1285
+
1286
+ def check_NOLA(window, nperseg, noverlap, tol=1e-10):
1287
+ r"""Check whether the Nonzero Overlap Add (NOLA) constraint is met.
1288
+
1289
+ Parameters
1290
+ ----------
1291
+ window : str or tuple or array_like
1292
+ Desired window to use. If `window` is a string or tuple, it is
1293
+ passed to `get_window` to generate the window values, which are
1294
+ DFT-even by default. See `get_window` for a list of windows and
1295
+ required parameters. If `window` is array_like it will be used
1296
+ directly as the window and its length must be nperseg.
1297
+ nperseg : int
1298
+ Length of each segment.
1299
+ noverlap : int
1300
+ Number of points to overlap between segments.
1301
+ tol : float, optional
1302
+ The allowed variance of a bin's weighted sum from the median bin
1303
+ sum.
1304
+
1305
+ Returns
1306
+ -------
1307
+ verdict : bool
1308
+ `True` if chosen combination satisfies the NOLA constraint within
1309
+ `tol`, `False` otherwise
1310
+
1311
+ See Also
1312
+ --------
1313
+ check_COLA: Check whether the Constant OverLap Add (COLA) constraint is met
1314
+ stft: Short Time Fourier Transform
1315
+ istft: Inverse Short Time Fourier Transform
1316
+
1317
+ Notes
1318
+ -----
1319
+ In order to enable inversion of an STFT via the inverse STFT in
1320
+ `istft`, the signal windowing must obey the constraint of "nonzero
1321
+ overlap add" (NOLA):
1322
+
1323
+ .. math:: \sum_{t}w^{2}[n-tH] \ne 0
1324
+
1325
+ for all :math:`n`, where :math:`w` is the window function, :math:`t` is the
1326
+ frame index, and :math:`H` is the hop size (:math:`H` = `nperseg` -
1327
+ `noverlap`).
1328
+
1329
+ This ensures that the normalization factors in the denominator of the
1330
+ overlap-add inversion equation are not zero. Only very pathological windows
1331
+ will fail the NOLA constraint.
1332
+
1333
+ .. versionadded:: 1.2.0
1334
+
1335
+ References
1336
+ ----------
1337
+ .. [1] Julius O. Smith III, "Spectral Audio Signal Processing", W3K
1338
+ Publishing, 2011,ISBN 978-0-9745607-3-1.
1339
+ .. [2] G. Heinzel, A. Ruediger and R. Schilling, "Spectrum and
1340
+ spectral density estimation by the Discrete Fourier transform
1341
+ (DFT), including a comprehensive list of window functions and
1342
+ some new at-top windows", 2002,
1343
+ http://hdl.handle.net/11858/00-001M-0000-0013-557A-5
1344
+
1345
+ Examples
1346
+ --------
1347
+ >>> import numpy as np
1348
+ >>> from scipy import signal
1349
+
1350
+ Confirm NOLA condition for rectangular window of 75% (3/4) overlap:
1351
+
1352
+ >>> signal.check_NOLA(signal.windows.boxcar(100), 100, 75)
1353
+ True
1354
+
1355
+ NOLA is also true for 25% (1/4) overlap:
1356
+
1357
+ >>> signal.check_NOLA(signal.windows.boxcar(100), 100, 25)
1358
+ True
1359
+
1360
+ "Symmetrical" Hann window (for filter design) is also NOLA:
1361
+
1362
+ >>> signal.check_NOLA(signal.windows.hann(120, sym=True), 120, 60)
1363
+ True
1364
+
1365
+ As long as there is overlap, it takes quite a pathological window to fail
1366
+ NOLA:
1367
+
1368
+ >>> w = np.ones(64, dtype="float")
1369
+ >>> w[::2] = 0
1370
+ >>> signal.check_NOLA(w, 64, 32)
1371
+ False
1372
+
1373
+ If there is not enough overlap, a window with zeros at the ends will not
1374
+ work:
1375
+
1376
+ >>> signal.check_NOLA(signal.windows.hann(64), 64, 0)
1377
+ False
1378
+ >>> signal.check_NOLA(signal.windows.hann(64), 64, 1)
1379
+ False
1380
+ >>> signal.check_NOLA(signal.windows.hann(64), 64, 2)
1381
+ True
1382
+
1383
+ """
1384
+ nperseg = int(nperseg)
1385
+
1386
+ if nperseg < 1:
1387
+ raise ValueError('nperseg must be a positive integer')
1388
+
1389
+ if noverlap >= nperseg:
1390
+ raise ValueError('noverlap must be less than nperseg')
1391
+ if noverlap < 0:
1392
+ raise ValueError('noverlap must be a nonnegative integer')
1393
+ noverlap = int(noverlap)
1394
+
1395
+ if isinstance(window, str) or type(window) is tuple:
1396
+ win = get_window(window, nperseg)
1397
+ else:
1398
+ win = np.asarray(window)
1399
+ if len(win.shape) != 1:
1400
+ raise ValueError('window must be 1-D')
1401
+ if win.shape[0] != nperseg:
1402
+ raise ValueError('window must have length of nperseg')
1403
+
1404
+ step = nperseg - noverlap
1405
+ binsums = sum(win[ii*step:(ii+1)*step]**2 for ii in range(nperseg//step))
1406
+
1407
+ if nperseg % step != 0:
1408
+ binsums[:nperseg % step] += win[-(nperseg % step):]**2
1409
+
1410
+ return np.min(binsums) > tol
1411
+
1412
+
1413
+ def stft(x, fs=1.0, window='hann', nperseg=256, noverlap=None, nfft=None,
1414
+ detrend=False, return_onesided=True, boundary='zeros', padded=True,
1415
+ axis=-1, scaling='spectrum'):
1416
+ r"""Compute the Short Time Fourier Transform (legacy function).
1417
+
1418
+ STFTs can be used as a way of quantifying the change of a
1419
+ nonstationary signal's frequency and phase content over time.
1420
+
1421
+ .. legacy:: function
1422
+
1423
+ `ShortTimeFFT` is a newer STFT / ISTFT implementation with more
1424
+ features. A :ref:`comparison <tutorial_stft_legacy_stft>` between the
1425
+ implementations can be found in the :ref:`tutorial_stft` section of the
1426
+ :ref:`user_guide`.
1427
+
1428
+ Parameters
1429
+ ----------
1430
+ x : array_like
1431
+ Time series of measurement values
1432
+ fs : float, optional
1433
+ Sampling frequency of the `x` time series. Defaults to 1.0.
1434
+ window : str or tuple or array_like, optional
1435
+ Desired window to use. If `window` is a string or tuple, it is
1436
+ passed to `get_window` to generate the window values, which are
1437
+ DFT-even by default. See `get_window` for a list of windows and
1438
+ required parameters. If `window` is array_like it will be used
1439
+ directly as the window and its length must be nperseg. Defaults
1440
+ to a Hann window.
1441
+ nperseg : int, optional
1442
+ Length of each segment. Defaults to 256.
1443
+ noverlap : int, optional
1444
+ Number of points to overlap between segments. If `None`,
1445
+ ``noverlap = nperseg // 2``. Defaults to `None`. When
1446
+ specified, the COLA constraint must be met (see Notes below).
1447
+ nfft : int, optional
1448
+ Length of the FFT used, if a zero padded FFT is desired. If
1449
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
1450
+ detrend : str or function or `False`, optional
1451
+ Specifies how to detrend each segment. If `detrend` is a
1452
+ string, it is passed as the `type` argument to the `detrend`
1453
+ function. If it is a function, it takes a segment and returns a
1454
+ detrended segment. If `detrend` is `False`, no detrending is
1455
+ done. Defaults to `False`.
1456
+ return_onesided : bool, optional
1457
+ If `True`, return a one-sided spectrum for real data. If
1458
+ `False` return a two-sided spectrum. Defaults to `True`, but for
1459
+ complex data, a two-sided spectrum is always returned.
1460
+ boundary : str or None, optional
1461
+ Specifies whether the input signal is extended at both ends, and
1462
+ how to generate the new values, in order to center the first
1463
+ windowed segment on the first input point. This has the benefit
1464
+ of enabling reconstruction of the first input point when the
1465
+ employed window function starts at zero. Valid options are
1466
+ ``['even', 'odd', 'constant', 'zeros', None]``. Defaults to
1467
+ 'zeros', for zero padding extension. I.e. ``[1, 2, 3, 4]`` is
1468
+ extended to ``[0, 1, 2, 3, 4, 0]`` for ``nperseg=3``.
1469
+ padded : bool, optional
1470
+ Specifies whether the input signal is zero-padded at the end to
1471
+ make the signal fit exactly into an integer number of window
1472
+ segments, so that all of the signal is included in the output.
1473
+ Defaults to `True`. Padding occurs after boundary extension, if
1474
+ `boundary` is not `None`, and `padded` is `True`, as is the
1475
+ default.
1476
+ axis : int, optional
1477
+ Axis along which the STFT is computed; the default is over the
1478
+ last axis (i.e. ``axis=-1``).
1479
+ scaling: {'spectrum', 'psd'}
1480
+ The default 'spectrum' scaling allows each frequency line of `Zxx` to
1481
+ be interpreted as a magnitude spectrum. The 'psd' option scales each
1482
+ line to a power spectral density - it allows to calculate the signal's
1483
+ energy by numerically integrating over ``abs(Zxx)**2``.
1484
+
1485
+ .. versionadded:: 1.9.0
1486
+
1487
+ Returns
1488
+ -------
1489
+ f : ndarray
1490
+ Array of sample frequencies.
1491
+ t : ndarray
1492
+ Array of segment times.
1493
+ Zxx : ndarray
1494
+ STFT of `x`. By default, the last axis of `Zxx` corresponds
1495
+ to the segment times.
1496
+
1497
+ See Also
1498
+ --------
1499
+ istft: Inverse Short Time Fourier Transform
1500
+ ShortTimeFFT: Newer STFT/ISTFT implementation providing more features.
1501
+ check_COLA: Check whether the Constant OverLap Add (COLA) constraint
1502
+ is met
1503
+ check_NOLA: Check whether the Nonzero Overlap Add (NOLA) constraint is met
1504
+ welch: Power spectral density by Welch's method.
1505
+ spectrogram: Spectrogram by Welch's method.
1506
+ csd: Cross spectral density by Welch's method.
1507
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
1508
+
1509
+ Notes
1510
+ -----
1511
+ In order to enable inversion of an STFT via the inverse STFT in
1512
+ `istft`, the signal windowing must obey the constraint of "Nonzero
1513
+ OverLap Add" (NOLA), and the input signal must have complete
1514
+ windowing coverage (i.e. ``(x.shape[axis] - nperseg) %
1515
+ (nperseg-noverlap) == 0``). The `padded` argument may be used to
1516
+ accomplish this.
1517
+
1518
+ Given a time-domain signal :math:`x[n]`, a window :math:`w[n]`, and a hop
1519
+ size :math:`H` = `nperseg - noverlap`, the windowed frame at time index
1520
+ :math:`t` is given by
1521
+
1522
+ .. math:: x_{t}[n]=x[n]w[n-tH]
1523
+
1524
+ The overlap-add (OLA) reconstruction equation is given by
1525
+
1526
+ .. math:: x[n]=\frac{\sum_{t}x_{t}[n]w[n-tH]}{\sum_{t}w^{2}[n-tH]}
1527
+
1528
+ The NOLA constraint ensures that every normalization term that appears
1529
+ in the denominator of the OLA reconstruction equation is nonzero. Whether a
1530
+ choice of `window`, `nperseg`, and `noverlap` satisfy this constraint can
1531
+ be tested with `check_NOLA`.
1532
+
1533
+
1534
+ .. versionadded:: 0.19.0
1535
+
1536
+ References
1537
+ ----------
1538
+ .. [1] Oppenheim, Alan V., Ronald W. Schafer, John R. Buck
1539
+ "Discrete-Time Signal Processing", Prentice Hall, 1999.
1540
+ .. [2] Daniel W. Griffin, Jae S. Lim "Signal Estimation from
1541
+ Modified Short-Time Fourier Transform", IEEE 1984,
1542
+ 10.1109/TASSP.1984.1164317
1543
+
1544
+ Examples
1545
+ --------
1546
+ >>> import numpy as np
1547
+ >>> from scipy import signal
1548
+ >>> import matplotlib.pyplot as plt
1549
+ >>> rng = np.random.default_rng()
1550
+
1551
+ Generate a test signal, a 2 Vrms sine wave whose frequency is slowly
1552
+ modulated around 3kHz, corrupted by white noise of exponentially
1553
+ decreasing magnitude sampled at 10 kHz.
1554
+
1555
+ >>> fs = 10e3
1556
+ >>> N = 1e5
1557
+ >>> amp = 2 * np.sqrt(2)
1558
+ >>> noise_power = 0.01 * fs / 2
1559
+ >>> time = np.arange(N) / float(fs)
1560
+ >>> mod = 500*np.cos(2*np.pi*0.25*time)
1561
+ >>> carrier = amp * np.sin(2*np.pi*3e3*time + mod)
1562
+ >>> noise = rng.normal(scale=np.sqrt(noise_power),
1563
+ ... size=time.shape)
1564
+ >>> noise *= np.exp(-time/5)
1565
+ >>> x = carrier + noise
1566
+
1567
+ Compute and plot the STFT's magnitude.
1568
+
1569
+ >>> f, t, Zxx = signal.stft(x, fs, nperseg=1000)
1570
+ >>> plt.pcolormesh(t, f, np.abs(Zxx), vmin=0, vmax=amp, shading='gouraud')
1571
+ >>> plt.title('STFT Magnitude')
1572
+ >>> plt.ylabel('Frequency [Hz]')
1573
+ >>> plt.xlabel('Time [sec]')
1574
+ >>> plt.show()
1575
+
1576
+ Compare the energy of the signal `x` with the energy of its STFT:
1577
+
1578
+ >>> E_x = sum(x**2) / fs # Energy of x
1579
+ >>> # Calculate a two-sided STFT with PSD scaling:
1580
+ >>> f, t, Zxx = signal.stft(x, fs, nperseg=1000, return_onesided=False,
1581
+ ... scaling='psd')
1582
+ >>> # Integrate numerically over abs(Zxx)**2:
1583
+ >>> df, dt = f[1] - f[0], t[1] - t[0]
1584
+ >>> E_Zxx = sum(np.sum(Zxx.real**2 + Zxx.imag**2, axis=0) * df) * dt
1585
+ >>> # The energy is the same, but the numerical errors are quite large:
1586
+ >>> np.isclose(E_x, E_Zxx, rtol=1e-2)
1587
+ True
1588
+
1589
+ """
1590
+ if scaling == 'psd':
1591
+ scaling = 'density'
1592
+ elif scaling != 'spectrum':
1593
+ raise ValueError(f"Parameter {scaling=} not in ['spectrum', 'psd']!")
1594
+
1595
+ freqs, time, Zxx = _spectral_helper(x, x, fs, window, nperseg, noverlap,
1596
+ nfft, detrend, return_onesided,
1597
+ scaling=scaling, axis=axis,
1598
+ mode='stft', boundary=boundary,
1599
+ padded=padded)
1600
+
1601
+ return freqs, time, Zxx
1602
+
1603
+
1604
+ def istft(Zxx, fs=1.0, window='hann', nperseg=None, noverlap=None, nfft=None,
1605
+ input_onesided=True, boundary=True, time_axis=-1, freq_axis=-2,
1606
+ scaling='spectrum'):
1607
+ r"""Perform the inverse Short Time Fourier transform (legacy function).
1608
+
1609
+ .. legacy:: function
1610
+
1611
+ `ShortTimeFFT` is a newer STFT / ISTFT implementation with more
1612
+ features. A :ref:`comparison <tutorial_stft_legacy_stft>` between the
1613
+ implementations can be found in the :ref:`tutorial_stft` section of the
1614
+ :ref:`user_guide`.
1615
+
1616
+ Parameters
1617
+ ----------
1618
+ Zxx : array_like
1619
+ STFT of the signal to be reconstructed. If a purely real array
1620
+ is passed, it will be cast to a complex data type.
1621
+ fs : float, optional
1622
+ Sampling frequency of the time series. Defaults to 1.0.
1623
+ window : str or tuple or array_like, optional
1624
+ Desired window to use. If `window` is a string or tuple, it is
1625
+ passed to `get_window` to generate the window values, which are
1626
+ DFT-even by default. See `get_window` for a list of windows and
1627
+ required parameters. If `window` is array_like it will be used
1628
+ directly as the window and its length must be nperseg. Defaults
1629
+ to a Hann window. Must match the window used to generate the
1630
+ STFT for faithful inversion.
1631
+ nperseg : int, optional
1632
+ Number of data points corresponding to each STFT segment. This
1633
+ parameter must be specified if the number of data points per
1634
+ segment is odd, or if the STFT was padded via ``nfft >
1635
+ nperseg``. If `None`, the value depends on the shape of
1636
+ `Zxx` and `input_onesided`. If `input_onesided` is `True`,
1637
+ ``nperseg=2*(Zxx.shape[freq_axis] - 1)``. Otherwise,
1638
+ ``nperseg=Zxx.shape[freq_axis]``. Defaults to `None`.
1639
+ noverlap : int, optional
1640
+ Number of points to overlap between segments. If `None`, half
1641
+ of the segment length. Defaults to `None`. When specified, the
1642
+ COLA constraint must be met (see Notes below), and should match
1643
+ the parameter used to generate the STFT. Defaults to `None`.
1644
+ nfft : int, optional
1645
+ Number of FFT points corresponding to each STFT segment. This
1646
+ parameter must be specified if the STFT was padded via ``nfft >
1647
+ nperseg``. If `None`, the default values are the same as for
1648
+ `nperseg`, detailed above, with one exception: if
1649
+ `input_onesided` is True and
1650
+ ``nperseg==2*Zxx.shape[freq_axis] - 1``, `nfft` also takes on
1651
+ that value. This case allows the proper inversion of an
1652
+ odd-length unpadded STFT using ``nfft=None``. Defaults to
1653
+ `None`.
1654
+ input_onesided : bool, optional
1655
+ If `True`, interpret the input array as one-sided FFTs, such
1656
+ as is returned by `stft` with ``return_onesided=True`` and
1657
+ `numpy.fft.rfft`. If `False`, interpret the input as a a
1658
+ two-sided FFT. Defaults to `True`.
1659
+ boundary : bool, optional
1660
+ Specifies whether the input signal was extended at its
1661
+ boundaries by supplying a non-`None` ``boundary`` argument to
1662
+ `stft`. Defaults to `True`.
1663
+ time_axis : int, optional
1664
+ Where the time segments of the STFT is located; the default is
1665
+ the last axis (i.e. ``axis=-1``).
1666
+ freq_axis : int, optional
1667
+ Where the frequency axis of the STFT is located; the default is
1668
+ the penultimate axis (i.e. ``axis=-2``).
1669
+ scaling: {'spectrum', 'psd'}
1670
+ The default 'spectrum' scaling allows each frequency line of `Zxx` to
1671
+ be interpreted as a magnitude spectrum. The 'psd' option scales each
1672
+ line to a power spectral density - it allows to calculate the signal's
1673
+ energy by numerically integrating over ``abs(Zxx)**2``.
1674
+
1675
+ Returns
1676
+ -------
1677
+ t : ndarray
1678
+ Array of output data times.
1679
+ x : ndarray
1680
+ iSTFT of `Zxx`.
1681
+
1682
+ See Also
1683
+ --------
1684
+ stft: Short Time Fourier Transform
1685
+ ShortTimeFFT: Newer STFT/ISTFT implementation providing more features.
1686
+ check_COLA: Check whether the Constant OverLap Add (COLA) constraint
1687
+ is met
1688
+ check_NOLA: Check whether the Nonzero Overlap Add (NOLA) constraint is met
1689
+
1690
+ Notes
1691
+ -----
1692
+ In order to enable inversion of an STFT via the inverse STFT with
1693
+ `istft`, the signal windowing must obey the constraint of "nonzero
1694
+ overlap add" (NOLA):
1695
+
1696
+ .. math:: \sum_{t}w^{2}[n-tH] \ne 0
1697
+
1698
+ This ensures that the normalization factors that appear in the denominator
1699
+ of the overlap-add reconstruction equation
1700
+
1701
+ .. math:: x[n]=\frac{\sum_{t}x_{t}[n]w[n-tH]}{\sum_{t}w^{2}[n-tH]}
1702
+
1703
+ are not zero. The NOLA constraint can be checked with the `check_NOLA`
1704
+ function.
1705
+
1706
+ An STFT which has been modified (via masking or otherwise) is not
1707
+ guaranteed to correspond to a exactly realizible signal. This
1708
+ function implements the iSTFT via the least-squares estimation
1709
+ algorithm detailed in [2]_, which produces a signal that minimizes
1710
+ the mean squared error between the STFT of the returned signal and
1711
+ the modified STFT.
1712
+
1713
+
1714
+ .. versionadded:: 0.19.0
1715
+
1716
+ References
1717
+ ----------
1718
+ .. [1] Oppenheim, Alan V., Ronald W. Schafer, John R. Buck
1719
+ "Discrete-Time Signal Processing", Prentice Hall, 1999.
1720
+ .. [2] Daniel W. Griffin, Jae S. Lim "Signal Estimation from
1721
+ Modified Short-Time Fourier Transform", IEEE 1984,
1722
+ 10.1109/TASSP.1984.1164317
1723
+
1724
+ Examples
1725
+ --------
1726
+ >>> import numpy as np
1727
+ >>> from scipy import signal
1728
+ >>> import matplotlib.pyplot as plt
1729
+ >>> rng = np.random.default_rng()
1730
+
1731
+ Generate a test signal, a 2 Vrms sine wave at 50Hz corrupted by
1732
+ 0.001 V**2/Hz of white noise sampled at 1024 Hz.
1733
+
1734
+ >>> fs = 1024
1735
+ >>> N = 10*fs
1736
+ >>> nperseg = 512
1737
+ >>> amp = 2 * np.sqrt(2)
1738
+ >>> noise_power = 0.001 * fs / 2
1739
+ >>> time = np.arange(N) / float(fs)
1740
+ >>> carrier = amp * np.sin(2*np.pi*50*time)
1741
+ >>> noise = rng.normal(scale=np.sqrt(noise_power),
1742
+ ... size=time.shape)
1743
+ >>> x = carrier + noise
1744
+
1745
+ Compute the STFT, and plot its magnitude
1746
+
1747
+ >>> f, t, Zxx = signal.stft(x, fs=fs, nperseg=nperseg)
1748
+ >>> plt.figure()
1749
+ >>> plt.pcolormesh(t, f, np.abs(Zxx), vmin=0, vmax=amp, shading='gouraud')
1750
+ >>> plt.ylim([f[1], f[-1]])
1751
+ >>> plt.title('STFT Magnitude')
1752
+ >>> plt.ylabel('Frequency [Hz]')
1753
+ >>> plt.xlabel('Time [sec]')
1754
+ >>> plt.yscale('log')
1755
+ >>> plt.show()
1756
+
1757
+ Zero the components that are 10% or less of the carrier magnitude,
1758
+ then convert back to a time series via inverse STFT
1759
+
1760
+ >>> Zxx = np.where(np.abs(Zxx) >= amp/10, Zxx, 0)
1761
+ >>> _, xrec = signal.istft(Zxx, fs)
1762
+
1763
+ Compare the cleaned signal with the original and true carrier signals.
1764
+
1765
+ >>> plt.figure()
1766
+ >>> plt.plot(time, x, time, xrec, time, carrier)
1767
+ >>> plt.xlim([2, 2.1])
1768
+ >>> plt.xlabel('Time [sec]')
1769
+ >>> plt.ylabel('Signal')
1770
+ >>> plt.legend(['Carrier + Noise', 'Filtered via STFT', 'True Carrier'])
1771
+ >>> plt.show()
1772
+
1773
+ Note that the cleaned signal does not start as abruptly as the original,
1774
+ since some of the coefficients of the transient were also removed:
1775
+
1776
+ >>> plt.figure()
1777
+ >>> plt.plot(time, x, time, xrec, time, carrier)
1778
+ >>> plt.xlim([0, 0.1])
1779
+ >>> plt.xlabel('Time [sec]')
1780
+ >>> plt.ylabel('Signal')
1781
+ >>> plt.legend(['Carrier + Noise', 'Filtered via STFT', 'True Carrier'])
1782
+ >>> plt.show()
1783
+
1784
+ """
1785
+ # Make sure input is an ndarray of appropriate complex dtype
1786
+ Zxx = np.asarray(Zxx) + 0j
1787
+ freq_axis = int(freq_axis)
1788
+ time_axis = int(time_axis)
1789
+
1790
+ if Zxx.ndim < 2:
1791
+ raise ValueError('Input stft must be at least 2d!')
1792
+
1793
+ if freq_axis == time_axis:
1794
+ raise ValueError('Must specify differing time and frequency axes!')
1795
+
1796
+ nseg = Zxx.shape[time_axis]
1797
+
1798
+ if input_onesided:
1799
+ # Assume even segment length
1800
+ n_default = 2*(Zxx.shape[freq_axis] - 1)
1801
+ else:
1802
+ n_default = Zxx.shape[freq_axis]
1803
+
1804
+ # Check windowing parameters
1805
+ if nperseg is None:
1806
+ nperseg = n_default
1807
+ else:
1808
+ nperseg = int(nperseg)
1809
+ if nperseg < 1:
1810
+ raise ValueError('nperseg must be a positive integer')
1811
+
1812
+ if nfft is None:
1813
+ if (input_onesided) and (nperseg == n_default + 1):
1814
+ # Odd nperseg, no FFT padding
1815
+ nfft = nperseg
1816
+ else:
1817
+ nfft = n_default
1818
+ elif nfft < nperseg:
1819
+ raise ValueError('nfft must be greater than or equal to nperseg.')
1820
+ else:
1821
+ nfft = int(nfft)
1822
+
1823
+ if noverlap is None:
1824
+ noverlap = nperseg//2
1825
+ else:
1826
+ noverlap = int(noverlap)
1827
+ if noverlap >= nperseg:
1828
+ raise ValueError('noverlap must be less than nperseg.')
1829
+ nstep = nperseg - noverlap
1830
+
1831
+ # Rearrange axes if necessary
1832
+ if time_axis != Zxx.ndim-1 or freq_axis != Zxx.ndim-2:
1833
+ # Turn negative indices to positive for the call to transpose
1834
+ if freq_axis < 0:
1835
+ freq_axis = Zxx.ndim + freq_axis
1836
+ if time_axis < 0:
1837
+ time_axis = Zxx.ndim + time_axis
1838
+ zouter = list(range(Zxx.ndim))
1839
+ for ax in sorted([time_axis, freq_axis], reverse=True):
1840
+ zouter.pop(ax)
1841
+ Zxx = np.transpose(Zxx, zouter+[freq_axis, time_axis])
1842
+
1843
+ # Get window as array
1844
+ if isinstance(window, str) or type(window) is tuple:
1845
+ win = get_window(window, nperseg)
1846
+ else:
1847
+ win = np.asarray(window)
1848
+ if len(win.shape) != 1:
1849
+ raise ValueError('window must be 1-D')
1850
+ if win.shape[0] != nperseg:
1851
+ raise ValueError(f'window must have length of {nperseg}')
1852
+
1853
+ ifunc = sp_fft.irfft if input_onesided else sp_fft.ifft
1854
+ xsubs = ifunc(Zxx, axis=-2, n=nfft)[..., :nperseg, :]
1855
+
1856
+ # Initialize output and normalization arrays
1857
+ outputlength = nperseg + (nseg-1)*nstep
1858
+ x = np.zeros(list(Zxx.shape[:-2])+[outputlength], dtype=xsubs.dtype)
1859
+ norm = np.zeros(outputlength, dtype=xsubs.dtype)
1860
+
1861
+ if np.result_type(win, xsubs) != xsubs.dtype:
1862
+ win = win.astype(xsubs.dtype)
1863
+
1864
+ if scaling == 'spectrum':
1865
+ xsubs *= win.sum()
1866
+ elif scaling == 'psd':
1867
+ xsubs *= np.sqrt(fs * sum(win**2))
1868
+ else:
1869
+ raise ValueError(f"Parameter {scaling=} not in ['spectrum', 'psd']!")
1870
+
1871
+ # Construct the output from the ifft segments
1872
+ # This loop could perhaps be vectorized/strided somehow...
1873
+ for ii in range(nseg):
1874
+ # Window the ifft
1875
+ x[..., ii*nstep:ii*nstep+nperseg] += xsubs[..., ii] * win
1876
+ norm[..., ii*nstep:ii*nstep+nperseg] += win**2
1877
+
1878
+ # Remove extension points
1879
+ if boundary:
1880
+ x = x[..., nperseg//2:-(nperseg//2)]
1881
+ norm = norm[..., nperseg//2:-(nperseg//2)]
1882
+
1883
+ # Divide out normalization where non-tiny
1884
+ if np.sum(norm > 1e-10) != len(norm):
1885
+ warnings.warn(
1886
+ "NOLA condition failed, STFT may not be invertible."
1887
+ + (" Possibly due to missing boundary" if not boundary else ""),
1888
+ stacklevel=2
1889
+ )
1890
+ x /= np.where(norm > 1e-10, norm, 1.0)
1891
+
1892
+ if input_onesided:
1893
+ x = x.real
1894
+
1895
+ # Put axes back
1896
+ if x.ndim > 1:
1897
+ if time_axis != Zxx.ndim-1:
1898
+ if freq_axis < time_axis:
1899
+ time_axis -= 1
1900
+ x = np.moveaxis(x, -1, time_axis)
1901
+
1902
+ time = np.arange(x.shape[0])/float(fs)
1903
+ return time, x
1904
+
1905
+
1906
+ def coherence(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None,
1907
+ nfft=None, detrend='constant', axis=-1):
1908
+ r"""
1909
+ Estimate the magnitude squared coherence estimate, Cxy, of
1910
+ discrete-time signals X and Y using Welch's method.
1911
+
1912
+ ``Cxy = abs(Pxy)**2/(Pxx*Pyy)``, where `Pxx` and `Pyy` are power
1913
+ spectral density estimates of X and Y, and `Pxy` is the cross
1914
+ spectral density estimate of X and Y.
1915
+
1916
+ Parameters
1917
+ ----------
1918
+ x : array_like
1919
+ Time series of measurement values
1920
+ y : array_like
1921
+ Time series of measurement values
1922
+ fs : float, optional
1923
+ Sampling frequency of the `x` and `y` time series. Defaults
1924
+ to 1.0.
1925
+ window : str or tuple or array_like, optional
1926
+ Desired window to use. If `window` is a string or tuple, it is
1927
+ passed to `get_window` to generate the window values, which are
1928
+ DFT-even by default. See `get_window` for a list of windows and
1929
+ required parameters. If `window` is array_like it will be used
1930
+ directly as the window and its length must be nperseg. Defaults
1931
+ to a Hann window.
1932
+ nperseg : int, optional
1933
+ Length of each segment. Defaults to None, but if window is str or
1934
+ tuple, is set to 256, and if window is array_like, is set to the
1935
+ length of the window.
1936
+ noverlap: int, optional
1937
+ Number of points to overlap between segments. If `None`,
1938
+ ``noverlap = nperseg // 2``. Defaults to `None`.
1939
+ nfft : int, optional
1940
+ Length of the FFT used, if a zero padded FFT is desired. If
1941
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
1942
+ detrend : str or function or `False`, optional
1943
+ Specifies how to detrend each segment. If `detrend` is a
1944
+ string, it is passed as the `type` argument to the `detrend`
1945
+ function. If it is a function, it takes a segment and returns a
1946
+ detrended segment. If `detrend` is `False`, no detrending is
1947
+ done. Defaults to 'constant'.
1948
+ axis : int, optional
1949
+ Axis along which the coherence is computed for both inputs; the
1950
+ default is over the last axis (i.e. ``axis=-1``).
1951
+
1952
+ Returns
1953
+ -------
1954
+ f : ndarray
1955
+ Array of sample frequencies.
1956
+ Cxy : ndarray
1957
+ Magnitude squared coherence of x and y.
1958
+
1959
+ See Also
1960
+ --------
1961
+ periodogram: Simple, optionally modified periodogram
1962
+ lombscargle: Lomb-Scargle periodogram for unevenly sampled data
1963
+ welch: Power spectral density by Welch's method.
1964
+ csd: Cross spectral density by Welch's method.
1965
+
1966
+ Notes
1967
+ -----
1968
+ An appropriate amount of overlap will depend on the choice of window
1969
+ and on your requirements. For the default Hann window an overlap of
1970
+ 50% is a reasonable trade-off between accurately estimating the
1971
+ signal power, while not over counting any of the data. Narrower
1972
+ windows may require a larger overlap.
1973
+
1974
+ .. versionadded:: 0.16.0
1975
+
1976
+ References
1977
+ ----------
1978
+ .. [1] P. Welch, "The use of the fast Fourier transform for the
1979
+ estimation of power spectra: A method based on time averaging
1980
+ over short, modified periodograms", IEEE Trans. Audio
1981
+ Electroacoust. vol. 15, pp. 70-73, 1967.
1982
+ .. [2] Stoica, Petre, and Randolph Moses, "Spectral Analysis of
1983
+ Signals" Prentice Hall, 2005
1984
+
1985
+ Examples
1986
+ --------
1987
+ >>> import numpy as np
1988
+ >>> from scipy import signal
1989
+ >>> import matplotlib.pyplot as plt
1990
+ >>> rng = np.random.default_rng()
1991
+
1992
+ Generate two test signals with some common features.
1993
+
1994
+ >>> fs = 10e3
1995
+ >>> N = 1e5
1996
+ >>> amp = 20
1997
+ >>> freq = 1234.0
1998
+ >>> noise_power = 0.001 * fs / 2
1999
+ >>> time = np.arange(N) / fs
2000
+ >>> b, a = signal.butter(2, 0.25, 'low')
2001
+ >>> x = rng.normal(scale=np.sqrt(noise_power), size=time.shape)
2002
+ >>> y = signal.lfilter(b, a, x)
2003
+ >>> x += amp*np.sin(2*np.pi*freq*time)
2004
+ >>> y += rng.normal(scale=0.1*np.sqrt(noise_power), size=time.shape)
2005
+
2006
+ Compute and plot the coherence.
2007
+
2008
+ >>> f, Cxy = signal.coherence(x, y, fs, nperseg=1024)
2009
+ >>> plt.semilogy(f, Cxy)
2010
+ >>> plt.xlabel('frequency [Hz]')
2011
+ >>> plt.ylabel('Coherence')
2012
+ >>> plt.show()
2013
+
2014
+ """
2015
+ freqs, Pxx = welch(x, fs=fs, window=window, nperseg=nperseg,
2016
+ noverlap=noverlap, nfft=nfft, detrend=detrend,
2017
+ axis=axis)
2018
+ _, Pyy = welch(y, fs=fs, window=window, nperseg=nperseg, noverlap=noverlap,
2019
+ nfft=nfft, detrend=detrend, axis=axis)
2020
+ _, Pxy = csd(x, y, fs=fs, window=window, nperseg=nperseg,
2021
+ noverlap=noverlap, nfft=nfft, detrend=detrend, axis=axis)
2022
+
2023
+ Cxy = np.abs(Pxy)**2 / Pxx / Pyy
2024
+
2025
+ return freqs, Cxy
2026
+
2027
+
2028
+ def _spectral_helper(x, y, fs=1.0, window='hann', nperseg=None, noverlap=None,
2029
+ nfft=None, detrend='constant', return_onesided=True,
2030
+ scaling='density', axis=-1, mode='psd', boundary=None,
2031
+ padded=False):
2032
+ """Calculate various forms of windowed FFTs for PSD, CSD, etc.
2033
+
2034
+ .. legacy:: function
2035
+
2036
+ This function is soley used by the legacy functions `spectrogram` and `stft`
2037
+ (which are also in this same source file `scipy/signal/_spectral_py.py`).
2038
+
2039
+ This is a helper function that implements the commonality between
2040
+ the stft, psd, csd, and spectrogram functions. It is not designed to
2041
+ be called externally. The windows are not averaged over; the result
2042
+ from each window is returned.
2043
+
2044
+ Parameters
2045
+ ----------
2046
+ x : array_like
2047
+ Array or sequence containing the data to be analyzed.
2048
+ y : array_like
2049
+ Array or sequence containing the data to be analyzed. If this is
2050
+ the same object in memory as `x` (i.e. ``_spectral_helper(x,
2051
+ x, ...)``), the extra computations are spared.
2052
+ fs : float, optional
2053
+ Sampling frequency of the time series. Defaults to 1.0.
2054
+ window : str or tuple or array_like, optional
2055
+ Desired window to use. If `window` is a string or tuple, it is
2056
+ passed to `get_window` to generate the window values, which are
2057
+ DFT-even by default. See `get_window` for a list of windows and
2058
+ required parameters. If `window` is array_like it will be used
2059
+ directly as the window and its length must be nperseg. Defaults
2060
+ to a Hann window.
2061
+ nperseg : int, optional
2062
+ Length of each segment. Defaults to None, but if window is str or
2063
+ tuple, is set to 256, and if window is array_like, is set to the
2064
+ length of the window.
2065
+ noverlap : int, optional
2066
+ Number of points to overlap between segments. If `None`,
2067
+ ``noverlap = nperseg // 2``. Defaults to `None`.
2068
+ nfft : int, optional
2069
+ Length of the FFT used, if a zero padded FFT is desired. If
2070
+ `None`, the FFT length is `nperseg`. Defaults to `None`.
2071
+ detrend : str or function or `False`, optional
2072
+ Specifies how to detrend each segment. If `detrend` is a
2073
+ string, it is passed as the `type` argument to the `detrend`
2074
+ function. If it is a function, it takes a segment and returns a
2075
+ detrended segment. If `detrend` is `False`, no detrending is
2076
+ done. Defaults to 'constant'.
2077
+ return_onesided : bool, optional
2078
+ If `True`, return a one-sided spectrum for real data. If
2079
+ `False` return a two-sided spectrum. Defaults to `True`, but for
2080
+ complex data, a two-sided spectrum is always returned.
2081
+ scaling : { 'density', 'spectrum' }, optional
2082
+ Selects between computing the cross spectral density ('density')
2083
+ where `Pxy` has units of V²/Hz and computing the cross
2084
+ spectrum ('spectrum') where `Pxy` has units of V², if `x`
2085
+ and `y` are measured in V and `fs` is measured in Hz.
2086
+ Defaults to 'density'
2087
+ axis : int, optional
2088
+ Axis along which the FFTs are computed; the default is over the
2089
+ last axis (i.e. ``axis=-1``).
2090
+ mode: str {'psd', 'stft'}, optional
2091
+ Defines what kind of return values are expected. Defaults to
2092
+ 'psd'.
2093
+ boundary : str or None, optional
2094
+ Specifies whether the input signal is extended at both ends, and
2095
+ how to generate the new values, in order to center the first
2096
+ windowed segment on the first input point. This has the benefit
2097
+ of enabling reconstruction of the first input point when the
2098
+ employed window function starts at zero. Valid options are
2099
+ ``['even', 'odd', 'constant', 'zeros', None]``. Defaults to
2100
+ `None`.
2101
+ padded : bool, optional
2102
+ Specifies whether the input signal is zero-padded at the end to
2103
+ make the signal fit exactly into an integer number of window
2104
+ segments, so that all of the signal is included in the output.
2105
+ Defaults to `False`. Padding occurs after boundary extension, if
2106
+ `boundary` is not `None`, and `padded` is `True`.
2107
+
2108
+ Returns
2109
+ -------
2110
+ freqs : ndarray
2111
+ Array of sample frequencies.
2112
+ t : ndarray
2113
+ Array of times corresponding to each data segment
2114
+ result : ndarray
2115
+ Array of output data, contents dependent on *mode* kwarg.
2116
+
2117
+ Notes
2118
+ -----
2119
+ Adapted from matplotlib.mlab
2120
+
2121
+ .. versionadded:: 0.16.0
2122
+ """
2123
+ if mode not in ['psd', 'stft']:
2124
+ raise ValueError(f"Unknown value for mode {mode}, must be one of: "
2125
+ "{'psd', 'stft'}")
2126
+
2127
+ boundary_funcs = {'even': even_ext,
2128
+ 'odd': odd_ext,
2129
+ 'constant': const_ext,
2130
+ 'zeros': zero_ext,
2131
+ None: None}
2132
+
2133
+ if boundary not in boundary_funcs:
2134
+ raise ValueError(f"Unknown boundary option '{boundary}', "
2135
+ f"must be one of: {list(boundary_funcs.keys())}")
2136
+
2137
+ # If x and y are the same object we can save ourselves some computation.
2138
+ same_data = y is x
2139
+
2140
+ if not same_data and mode != 'psd':
2141
+ raise ValueError("x and y must be equal if mode is 'stft'")
2142
+
2143
+ axis = int(axis)
2144
+
2145
+ # Ensure we have np.arrays, get outdtype
2146
+ x = np.asarray(x)
2147
+ if not same_data:
2148
+ y = np.asarray(y)
2149
+ outdtype = np.result_type(x, y, np.complex64)
2150
+ else:
2151
+ outdtype = np.result_type(x, np.complex64)
2152
+
2153
+ if not same_data:
2154
+ # Check if we can broadcast the outer axes together
2155
+ xouter = list(x.shape)
2156
+ youter = list(y.shape)
2157
+ xouter.pop(axis)
2158
+ youter.pop(axis)
2159
+ try:
2160
+ outershape = np.broadcast(np.empty(xouter), np.empty(youter)).shape
2161
+ except ValueError as e:
2162
+ raise ValueError('x and y cannot be broadcast together.') from e
2163
+
2164
+ if same_data:
2165
+ if x.size == 0:
2166
+ return np.empty(x.shape), np.empty(x.shape), np.empty(x.shape)
2167
+ else:
2168
+ if x.size == 0 or y.size == 0:
2169
+ outshape = outershape + (min([x.shape[axis], y.shape[axis]]),)
2170
+ emptyout = np.moveaxis(np.empty(outshape), -1, axis)
2171
+ return emptyout, emptyout, emptyout
2172
+
2173
+ if x.ndim > 1:
2174
+ if axis != -1:
2175
+ x = np.moveaxis(x, axis, -1)
2176
+ if not same_data and y.ndim > 1:
2177
+ y = np.moveaxis(y, axis, -1)
2178
+
2179
+ # Check if x and y are the same length, zero-pad if necessary
2180
+ if not same_data:
2181
+ if x.shape[-1] != y.shape[-1]:
2182
+ if x.shape[-1] < y.shape[-1]:
2183
+ pad_shape = list(x.shape)
2184
+ pad_shape[-1] = y.shape[-1] - x.shape[-1]
2185
+ x = np.concatenate((x, np.zeros(pad_shape)), -1)
2186
+ else:
2187
+ pad_shape = list(y.shape)
2188
+ pad_shape[-1] = x.shape[-1] - y.shape[-1]
2189
+ y = np.concatenate((y, np.zeros(pad_shape)), -1)
2190
+
2191
+ if nperseg is not None: # if specified by user
2192
+ nperseg = int(nperseg)
2193
+ if nperseg < 1:
2194
+ raise ValueError('nperseg must be a positive integer')
2195
+
2196
+ # parse window; if array like, then set nperseg = win.shape
2197
+ win, nperseg = _triage_segments(window, nperseg, input_length=x.shape[-1])
2198
+
2199
+ if nfft is None:
2200
+ nfft = nperseg
2201
+ elif nfft < nperseg:
2202
+ raise ValueError('nfft must be greater than or equal to nperseg.')
2203
+ else:
2204
+ nfft = int(nfft)
2205
+
2206
+ if noverlap is None:
2207
+ noverlap = nperseg//2
2208
+ else:
2209
+ noverlap = int(noverlap)
2210
+ if noverlap >= nperseg:
2211
+ raise ValueError('noverlap must be less than nperseg.')
2212
+ nstep = nperseg - noverlap
2213
+
2214
+ # Padding occurs after boundary extension, so that the extended signal ends
2215
+ # in zeros, instead of introducing an impulse at the end.
2216
+ # I.e. if x = [..., 3, 2]
2217
+ # extend then pad -> [..., 3, 2, 2, 3, 0, 0, 0]
2218
+ # pad then extend -> [..., 3, 2, 0, 0, 0, 2, 3]
2219
+
2220
+ if boundary is not None:
2221
+ ext_func = boundary_funcs[boundary]
2222
+ x = ext_func(x, nperseg//2, axis=-1)
2223
+ if not same_data:
2224
+ y = ext_func(y, nperseg//2, axis=-1)
2225
+
2226
+ if padded:
2227
+ # Pad to integer number of windowed segments
2228
+ # I.e. make x.shape[-1] = nperseg + (nseg-1)*nstep, with integer nseg
2229
+ nadd = (-(x.shape[-1]-nperseg) % nstep) % nperseg
2230
+ zeros_shape = list(x.shape[:-1]) + [nadd]
2231
+ x = np.concatenate((x, np.zeros(zeros_shape)), axis=-1)
2232
+ if not same_data:
2233
+ zeros_shape = list(y.shape[:-1]) + [nadd]
2234
+ y = np.concatenate((y, np.zeros(zeros_shape)), axis=-1)
2235
+
2236
+ # Handle detrending and window functions
2237
+ if not detrend:
2238
+ def detrend_func(d):
2239
+ return d
2240
+ elif not hasattr(detrend, '__call__'):
2241
+ def detrend_func(d):
2242
+ return _signaltools.detrend(d, type=detrend, axis=-1)
2243
+ elif axis != -1:
2244
+ # Wrap this function so that it receives a shape that it could
2245
+ # reasonably expect to receive.
2246
+ def detrend_func(d):
2247
+ d = np.moveaxis(d, -1, axis)
2248
+ d = detrend(d)
2249
+ return np.moveaxis(d, axis, -1)
2250
+ else:
2251
+ detrend_func = detrend
2252
+
2253
+ if np.result_type(win, np.complex64) != outdtype:
2254
+ win = win.astype(outdtype)
2255
+
2256
+ if scaling == 'density':
2257
+ scale = 1.0 / (fs * (win*win).sum())
2258
+ elif scaling == 'spectrum':
2259
+ scale = 1.0 / win.sum()**2
2260
+ else:
2261
+ raise ValueError(f'Unknown scaling: {scaling!r}')
2262
+
2263
+ if mode == 'stft':
2264
+ scale = np.sqrt(scale)
2265
+
2266
+ if return_onesided:
2267
+ if np.iscomplexobj(x):
2268
+ sides = 'twosided'
2269
+ warnings.warn('Input data is complex, switching to return_onesided=False',
2270
+ stacklevel=3)
2271
+ else:
2272
+ sides = 'onesided'
2273
+ if not same_data:
2274
+ if np.iscomplexobj(y):
2275
+ sides = 'twosided'
2276
+ warnings.warn('Input data is complex, switching to '
2277
+ 'return_onesided=False',
2278
+ stacklevel=3)
2279
+ else:
2280
+ sides = 'twosided'
2281
+
2282
+ if sides == 'twosided':
2283
+ freqs = sp_fft.fftfreq(nfft, 1/fs)
2284
+ elif sides == 'onesided':
2285
+ freqs = sp_fft.rfftfreq(nfft, 1/fs)
2286
+
2287
+ # Perform the windowed FFTs
2288
+ result = _fft_helper(x, win, detrend_func, nperseg, noverlap, nfft, sides)
2289
+
2290
+ if not same_data:
2291
+ # All the same operations on the y data
2292
+ result_y = _fft_helper(y, win, detrend_func, nperseg, noverlap, nfft,
2293
+ sides)
2294
+ result = np.conjugate(result) * result_y
2295
+ elif mode == 'psd':
2296
+ result = np.conjugate(result) * result
2297
+
2298
+ result *= scale
2299
+ if sides == 'onesided' and mode == 'psd':
2300
+ if nfft % 2:
2301
+ result[..., 1:] *= 2
2302
+ else:
2303
+ # Last point is unpaired Nyquist freq point, don't double
2304
+ result[..., 1:-1] *= 2
2305
+
2306
+ time = np.arange(nperseg/2, x.shape[-1] - nperseg/2 + 1,
2307
+ nperseg - noverlap)/float(fs)
2308
+ if boundary is not None:
2309
+ time -= (nperseg/2) / fs
2310
+
2311
+ result = result.astype(outdtype)
2312
+
2313
+ # All imaginary parts are zero anyways
2314
+ if same_data and mode != 'stft':
2315
+ result = result.real
2316
+
2317
+ # Output is going to have new last axis for time/window index, so a
2318
+ # negative axis index shifts down one
2319
+ if axis < 0:
2320
+ axis -= 1
2321
+
2322
+ # Roll frequency axis back to axis where the data came from
2323
+ result = np.moveaxis(result, -1, axis)
2324
+
2325
+ return freqs, time, result
2326
+
2327
+
2328
+ def _fft_helper(x, win, detrend_func, nperseg, noverlap, nfft, sides):
2329
+ """
2330
+ Calculate windowed FFT, for internal use by
2331
+ `scipy.signal._spectral_helper`.
2332
+
2333
+ .. legacy:: function
2334
+
2335
+ This function is solely used by the legacy `_spectral_helper` function,
2336
+ which is located also in this file.
2337
+
2338
+ This is a helper function that does the main FFT calculation for
2339
+ `_spectral helper`. All input validation is performed there, and the
2340
+ data axis is assumed to be the last axis of x. It is not designed to
2341
+ be called externally. The windows are not averaged over; the result
2342
+ from each window is returned.
2343
+
2344
+ Returns
2345
+ -------
2346
+ result : ndarray
2347
+ Array of FFT data
2348
+
2349
+ Notes
2350
+ -----
2351
+ Adapted from matplotlib.mlab
2352
+
2353
+ .. versionadded:: 0.16.0
2354
+ """
2355
+ # Created sliding window view of array
2356
+ if nperseg == 1 and noverlap == 0:
2357
+ result = x[..., np.newaxis]
2358
+ else:
2359
+ step = nperseg - noverlap
2360
+ result = np.lib.stride_tricks.sliding_window_view(
2361
+ x, window_shape=nperseg, axis=-1, writeable=True
2362
+ )
2363
+ result = result[..., 0::step, :]
2364
+
2365
+ # Detrend each data segment individually
2366
+ result = detrend_func(result)
2367
+
2368
+ # Apply window by multiplication
2369
+ result = win * result
2370
+
2371
+ # Perform the fft. Acts on last axis by default. Zero-pads automatically
2372
+ if sides == 'twosided':
2373
+ func = sp_fft.fft
2374
+ else:
2375
+ result = result.real
2376
+ func = sp_fft.rfft
2377
+ result = func(result, n=nfft)
2378
+
2379
+ return result
2380
+
2381
+
2382
+ def _triage_segments(window, nperseg, input_length):
2383
+ """
2384
+ Parses window and nperseg arguments for spectrogram and _spectral_helper.
2385
+ This is a helper function, not meant to be called externally.
2386
+
2387
+ .. legacy:: function
2388
+
2389
+ This function is soley used by the legacy functions `spectrogram` and
2390
+ `_spectral_helper` (which are also in this file).
2391
+
2392
+ Parameters
2393
+ ----------
2394
+ window : string, tuple, or ndarray
2395
+ If window is specified by a string or tuple and nperseg is not
2396
+ specified, nperseg is set to the default of 256 and returns a window of
2397
+ that length.
2398
+ If instead the window is array_like and nperseg is not specified, then
2399
+ nperseg is set to the length of the window. A ValueError is raised if
2400
+ the user supplies both an array_like window and a value for nperseg but
2401
+ nperseg does not equal the length of the window.
2402
+
2403
+ nperseg : int
2404
+ Length of each segment
2405
+
2406
+ input_length: int
2407
+ Length of input signal, i.e. x.shape[-1]. Used to test for errors.
2408
+
2409
+ Returns
2410
+ -------
2411
+ win : ndarray
2412
+ window. If function was called with string or tuple than this will hold
2413
+ the actual array used as a window.
2414
+
2415
+ nperseg : int
2416
+ Length of each segment. If window is str or tuple, nperseg is set to
2417
+ 256. If window is array_like, nperseg is set to the length of the
2418
+ window.
2419
+ """
2420
+ # parse window; if array like, then set nperseg = win.shape
2421
+ if isinstance(window, str) or isinstance(window, tuple):
2422
+ # if nperseg not specified
2423
+ if nperseg is None:
2424
+ nperseg = 256 # then change to default
2425
+ if nperseg > input_length:
2426
+ warnings.warn(f'nperseg = {nperseg:d} is greater than input length '
2427
+ f' = {input_length:d}, using nperseg = {input_length:d}',
2428
+ stacklevel=3)
2429
+ nperseg = input_length
2430
+ win = get_window(window, nperseg)
2431
+ else:
2432
+ win = np.asarray(window)
2433
+ if len(win.shape) != 1:
2434
+ raise ValueError('window must be 1-D')
2435
+ if input_length < win.shape[-1]:
2436
+ raise ValueError('window is longer than input signal')
2437
+ if nperseg is None:
2438
+ nperseg = win.shape[0]
2439
+ elif nperseg is not None:
2440
+ if nperseg != win.shape[0]:
2441
+ raise ValueError("value specified for nperseg is different"
2442
+ " from length of window")
2443
+ return win, nperseg
2444
+
2445
+
2446
+ def _median_bias(n):
2447
+ """
2448
+ Returns the bias of the median of a set of periodograms relative to
2449
+ the mean.
2450
+
2451
+ See Appendix B from [1]_ for details.
2452
+
2453
+ Parameters
2454
+ ----------
2455
+ n : int
2456
+ Numbers of periodograms being averaged.
2457
+
2458
+ Returns
2459
+ -------
2460
+ bias : float
2461
+ Calculated bias.
2462
+
2463
+ References
2464
+ ----------
2465
+ .. [1] B. Allen, W.G. Anderson, P.R. Brady, D.A. Brown, J.D.E. Creighton.
2466
+ "FINDCHIRP: an algorithm for detection of gravitational waves from
2467
+ inspiraling compact binaries", Physical Review D 85, 2012,
2468
+ :arxiv:`gr-qc/0509116`
2469
+ """
2470
+ ii_2 = 2 * np.arange(1., (n-1) // 2 + 1)
2471
+ return 1 + np.sum(1. / (ii_2 + 1) - 1. / ii_2)