A simple Python package providing a moving average, a first-order low-pass filter, FFT analysis, and STFT analysis. This project is brought to you by PinkWink from PinkLAB, aiming to help everyone easily integrate signal-processing functions in their applications or data-processing workflows.
- Moving Average: Compute the average of the most recent N samples (sliding window).
- First-Order Low-Pass Filter: Smooth out noisy data with an exponential moving average.
- FFT Analysis: Compute and visualize the frequency spectrum of time-domain signals.
- STFT Analysis: Compute and display the time–frequency representation of signals using Short-Time Fourier Transform (spectrogram).
All methods are simple to configure and use, reducing complexity for quick results in signal processing or time-series data smoothing.
pip install pw-signal-processor- Clone (or download) this repository.
- Navigate to the project root (where
setup.pyorpyproject.tomlis located). - Install locally with:
pip install -e .Once installed, import and create an instance of the SignalProcessor class. Configure the window_size and alpha parameters as needed:
from signal_processor import SignalProcessor
# Create a processor with a window size of 5 and alpha=0.2 for the low-pass filter
sp = SignalProcessor(window_size=5, alpha=0.2)data = [10, 12, 13, 20, 22, 21, 18, 15]
for val in data:
ma_val = sp.moving_average(val)
lp_val = sp.low_pass_filter(val)
print(f"Input: {val} | Moving Avg: {ma_val:.2f} | Low Pass: {lp_val:.2f}")Compute the FFT of a time-domain signal.
- Args:
signal(array-like): Time-domain signal.dt(float): Sampling interval in seconds.
- Returns:
freq(numpy array): Frequency bins (Hz).Y(numpy array): FFT result (complex spectrum).
import numpy as np
# Example signal: sinusoids combined
time = np.linspace(0, 1, 1000)
signal = np.sin(2*np.pi*5*time) + 0.5*np.sin(2*np.pi*12*time)
dt = time[1] - time[0]
freq, Y = sp.compute_fft(signal, dt)
print(freq[:5]) # first few frequency bins
print(np.abs(Y[:5])) # magnitude of FFTPlot the time-domain signal and its frequency spectrum side by side.
- Args:
time(array-like): Time axis data.signal(array-like): Time-domain signal.dt(float, optional): Sampling interval. IfNone, inferred fromtime.freq_limit(tuple, optional): Frequency axis limits for FFT plot.
# Using the same signal from above
dt = None # let the method infer from `time`
sp.plot_fft(time, signal, dt=dt, freq_limit=(0, 20))Plot the magnitude spectrogram from STFT results.
- Args:
f(array-like): Frequency bins (Hz).t(array-like): Time bins (sec).Zxx(2D array): STFT complex output.
# Assuming f, t, Zxx obtained from calc_stft
draw_stft(f, t, Zxx)Compute the STFT of a signal and plot its spectrogram.
- Args:
signal(array-like): Input time-domain signal.Fs(float): Sampling frequency in Hz.nperseg(int): Number of samples per STFT segment.
import numpy as np
# Generate a sample signal
Fs = 100.0 # Sampling frequency
time = np.linspace(0, 2, int(2*Fs), endpoint=False)
sin_concat = np.sin(2*np.pi*10*time) + 0.5*np.sin(2*np.pi*20*time)
# Compute and display STFT
sp.calc_stft(sin_concat, Fs, nperseg=128)import numpy as np
import matplotlib.pyplot as plt
from signal_processor import SignalProcessor
# Generate some noisy sinusoidal data
time = np.linspace(0, 10, 100)
noise = np.random.normal(0, 0.5, size=time.shape)
signal = np.sin(time) + noise
# Initialize the SignalProcessor
sp = SignalProcessor(window_size=5, alpha=0.1)
# Moving average and low-pass
ma_output = []
lp_output = []
for val in signal:
ma_output.append(sp.moving_average(val))
lp_output.append(sp.low_pass_filter(val))
# Plot time-domain filters
plt.figure(figsize=(10,6))
plt.plot(time, signal, label='Noisy Signal', alpha=0.5)
plt.plot(time, ma_output, label='Moving Average', linewidth=2)
plt.plot(time, lp_output, label='Low Pass Filter', linewidth=2)
plt.legend()
plt.title('My-Signal-Processor Demo')
plt.xlabel('Time')
plt.ylabel('Amplitude')
plt.show()
# FFT demonstration
dt = time[1] - time[0]
sp.plot_fft(time, signal, dt=dt, freq_limit=(0, 20))
# STFT demonstration
Fs = 100.0
sp.calc_stft(signal, Fs, nperseg=64)Contributions, bug reports, and feature requests are welcome!
- Fork the project.
- Create a new branch for your feature or bugfix.
- Commit your changes.
- Submit a Pull Request back to the main repository.
We'll review your PR as soon as possible.
This project is licensed under the MIT License - feel free to modify and use it as you see fit.
If you have any questions or feedback, feel free to reach out:
- PinkWink from PinkLAB
- GitHub: https://github.com/pinklab-art/signal_processor
- Email: pinkwink@pinklab.art
Happy filtering and analysis!