Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

SciPy Signal (scipy.signal): Filtering, Peaks and Spectra

Use scipy.signal for research data: design a Butterworth filter, find peaks and compute a Welch spectrum, with the exact calls and how to read results.

Written and maintained by CASRAI Editorial Board

Last updated

SciPy signals work lives in one module, scipy.signal. It holds the functions researchers use to filter a recording, find peaks in it, and estimate its power spectrum. This guide maps each of those tasks to the function that does it, then walks through one complete example. If you searched “scipy signal” and “scipy signals”, this is the same module.

What scipy.signal is used for in research

The SciPy reference page for scipy.signal groups the module into these areas: convolution, B-splines, filtering, filter design (including Matlab-style IIR design), waveforms, window functions, peak finding, spectral analysis, and chirp Z-transform and zoom FFT. Most tutorials cover only filtering. The table maps a research task to the function and its signature as listed in the reference.

Task Function and signature
Design a Butterworth filter butter(N, Wn[, btype, analog, output, fs])
Apply a filter, one pass sosfilt(sos, x[, axis, zi]) or lfilter(b, a, x[, axis, zi])
Apply a filter forward and backward sosfiltfilt(sos, x[, axis, padtype, padlen]) or filtfilt(b, a, x[, axis, padtype, padlen, ...])
Smooth with a polynomial window savgol_filter(x, window_length, polyorder[, ...])
Median filter medfilt(volume[, kernel_size])
Remove a trend detrend(data[, axis, type, bp, overwrite_data])
Convolve or correlate two signals convolve(in1, in2[, mode, method]), correlate(in1, in2[, mode, method])
Analytic signal hilbert(x[, N, axis])
Resample to a new number of samples resample(x, num[, t, axis, window, domain])
Find peaks find_peaks(x[, height, threshold, distance, ...])
Power spectrum (Welch) welch(x[, fs, window, nperseg, noverlap, ...])

The conceptual background is in what is signal processing. For a plain FFT with NumPy, see NumPy Fourier transform.

Install or access

SciPy’s install page (scipy.org/install) gives these commands:

  1. python -m pip install scipy
  2. conda install scipy (or mamba install scipy)

The page says the recommended method depends on your workflow, and lists project-based tools (uv, pixi) as the recommended route for new users. Then import the module with from scipy import signal.

Step-by-step: design and apply a Butterworth filter, then find peaks and a Welch spectrum

The filter call follows the example in the scipy.signal.butter documentation: a 10th-order high-pass at 15 Hz on a signal sampled at 1000 Hz, which removes a 10 Hz tone. Here sig is your one-dimensional array of samples.

  1. Import the module: from scipy import signal
  2. Design the filter as second-order sections: sos = signal.butter(10, 15, 'hp', fs=1000, output='sos')
  3. Apply it forward and backward: y = signal.sosfiltfilt(sos, sig)
  4. Find peaks: peaks, props = signal.find_peaks(y, height=0, distance=50, prominence=0.5). The values 0, 50 and 0.5 are placeholders; set them for your data.
  5. Estimate the power spectrum: f, Pxx = signal.welch(y, fs=1000)

Passing fs to butter means the cutoff Wn is in the same units as fs (Hz here). Without fs, Wn is normalised so that 1 is the Nyquist frequency.

Output and how to read it

butter and the sos array

Wn is the -3 dB point. It is a scalar for lowpass and highpass and a length-2 sequence for bandpass and bandstop. With output='sos' the result is an array of shape (n_sections, 6), which sosfilt and sosfiltfilt take as their first argument.

sosfiltfilt versus sosfilt

sosfiltfilt filters forward and backward and returns an array of the same shape as x. In the SciPy docs example its output keeps the phase of the input, while single-pass sosfilt shows significant phase delay. If peak timing matters, that difference matters.

find_peaks

It returns (peaks, properties). peaks holds sample indices, not times: divide by the sampling rate to get seconds. A peak is a sample whose two direct neighbours are smaller; for a flat peak the middle index is returned (rounded down when the number of samples is even). distance is in samples (at least 1) and removes smaller peaks first. The conditions are evaluated in this order: plateau_size, height, threshold, distance, prominence, width. The properties dictionary can contain keys such as peak_heights, prominences, left_bases, right_bases, widths, width_heights, left_ips and right_ips, depending on which conditions you set.

welch

It returns f (frequencies) and Pxx (power). With the default scaling='density' the units are V2/Hz when the input is in V and fs in Hz; scaling='spectrum' gives V2. For a string or tuple window, nperseg defaults to 256 and noverlap defaults to nperseg//2. The default window is 'hann_periodic' and the default detrend is 'constant'.

Troubleshooting

Unstable or inaccurate filter

The butter default output is 'ba', but the documentation says: “Default is ‘ba’ for backwards compatibility, but ‘sos’ should be used for general-purpose filtering.” High-order or narrowband ba filters can be unstable or inaccurate because of floating-point precision. Pass output='sos' and use sosfilt or sosfiltfilt.

Wrong cutoff frequency

Check whether you passed fs. Without it, Wn is a fraction of the Nyquist frequency (the docs define it as 2 times the critical frequency divided by fs); with it, Wn is in Hz. The fs argument was added in SciPy 1.2.0.

Start and end of the output look odd

sosfiltfilt pads the signal at both ends (padtype='odd', with padlen set by default from the number of sections). You can change both arguments. sosfiltfilt was added in SciPy 0.18.0.

find_peaks returns too many peaks or odd results

On a noisy signal, smooth first or use find_peaks_cwt, as the documentation advises. NaNs in the input give unexpected results.

Legacy functions

The reference marks spectrogram as a legacy function, along with stft, istft, check_COLA and sosfreqz. Check the current reference before starting new code with them.

Free alternatives

Need Option Note
A frequency spectrum from the FFT only NumPy’s FFT routines Covered in NumPy Fourier transform.
Peaks in a noisy signal find_peaks_cwt in scipy.signal Named in the find_peaks documentation for noisy signals.

For other SciPy tasks, see SciPy interpolate, curve fitting with SciPy, and, for a related smoothing method in another tool, moving average in MATLAB.

FAQ

What is the difference between scipy signal and scipy.signal?

None. “SciPy signal” and “scipy signals” are informal names for the scipy.signal module, imported with from scipy import signal.

Should I use lfilter or sosfilt?

For general-purpose filtering the butter documentation recommends second-order sections (output='sos') with sosfilt, because ba coefficients can lose accuracy at high order or narrow bandwidth.

How do I filter without shifting peaks in time?

Use a forward-backward filter such as sosfiltfilt or filtfilt. The SciPy example shows its output matching the input phase, where sosfilt adds phase delay.

Are peak positions in seconds?

No. find_peaks returns sample indices; convert them using your sampling rate.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about SciPy Signal (scipy.signal): Filtering, Peaks and Spectra

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →