Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.

Commit ce09ce1

Browse files
committed
Added method to comput the Welch power spectrum in signals.tools.
1 parent 4ee85e4 commit ce09ce1

File tree

1 file changed

+103
-1
lines changed

1 file changed

+103
-1
lines changed

biosppy/signals/tools.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,8 @@ def power_spectrum(signal=None,
713713
sampling_rate : int, float, optional
714714
Sampling frequency (Hz).
715715
pad : int, optional
716-
Padding for the Fourier Transform (number of zeros added).
716+
Padding for the Fourier Transform (number of zeros added);
717+
defaults to no padding..
717718
pow2 : bool, optional
718719
If True, rounds the number of points `N = len(signal) + pad` to the
719720
nearest power of 2 greater than N.
@@ -762,6 +763,107 @@ def power_spectrum(signal=None,
762763
return utils.ReturnTuple((freqs, power), ('freqs', 'power'))
763764

764765

766+
def welch_spectrum(signal=None,
767+
sampling_rate=1000.,
768+
size=None,
769+
overlap=None,
770+
window='hanning',
771+
window_kwargs=None,
772+
pad=None,
773+
decibel=True):
774+
"""Compute the power spectrum of a signal using Welch's method (one-sided).
775+
776+
Parameters
777+
----------
778+
signal : array
779+
Input signal.
780+
sampling_rate : int, float, optional
781+
Sampling frequency (Hz).
782+
size : int, optional
783+
Number of points in each Welch segment;
784+
defaults to the equivalent of 1 second;
785+
ignored when 'window' is an array.
786+
overlap : int, optional
787+
Number of points to overlap between segments; defaults to `size / 2`.
788+
window : str, array, optional
789+
Type of window to use.
790+
window_kwargs : dict, optional
791+
Additional keyword arguments to pass on window creation; ignored if
792+
'window' is an array.
793+
pad : int, optional
794+
Padding for the Fourier Transform (number of zeros added);
795+
defaults to no padding.
796+
decibel : bool, optional
797+
If True, returns the power in decibels.
798+
799+
Returns
800+
-------
801+
freqs : array
802+
Array of frequencies (Hz) at which the power was computed.
803+
power : array
804+
Power spectrum.
805+
806+
Notes
807+
-----
808+
* Detrends each Welch segment by removing the mean.
809+
810+
"""
811+
812+
# check inputs
813+
if signal is None:
814+
raise TypeError("Please specify an input signal.")
815+
816+
length = len(signal)
817+
sampling_rate = float(sampling_rate)
818+
819+
if size is None:
820+
size = int(sampling_rate)
821+
822+
if window_kwargs is None:
823+
window_kwargs = {}
824+
825+
if isinstance(window, six.string_types):
826+
win = _get_window(window, size, **window_kwargs)
827+
elif isinstance(window, np.ndarray):
828+
win = window
829+
size = len(win)
830+
831+
if size > length:
832+
raise ValueError('Segment size must be smaller than signal length.')
833+
834+
if overlap is None:
835+
overlap = size // 2
836+
elif overlap > size:
837+
raise ValueError('Overlap must be smaller than segment size.')
838+
839+
nfft = size
840+
if pad is not None:
841+
if pad >= 0:
842+
nfft += pad
843+
else:
844+
raise ValueError("Padding must be a positive integer.")
845+
846+
freqs, power = ss.welch(
847+
signal,
848+
fs=sampling_rate,
849+
window=win,
850+
nperseg=size,
851+
noverlap=overlap,
852+
nfft=nfft,
853+
detrend='constant',
854+
return_onesided=True,
855+
scaling='spectrum',
856+
)
857+
858+
# compensate one-sided
859+
power *= 2
860+
861+
if decibel:
862+
power = 10. * np.log10(power)
863+
864+
return utils.ReturnTuple((freqs, power), ('freqs', 'power'))
865+
866+
765867
def band_power(freqs=None, power=None, frequency=None, decibel=True):
766868
"""Compute the avearge power in a frequency band.
767869

0 commit comments

Comments
 (0)