Algorithm Guide
WSDP includes a comprehensive algorithm library for CSI signal processing. This guide helps you choose and use the right algorithms for your use case.
Overview
WSDP algorithms are organized into six categories:
wsdp.algorithms
├── denoise() # Remove noise from CSI signals
├── calibrate() # Correct phase errors
├── normalize() # Normalize amplitude
├── interpolate() # Resample frequency grid
├── extract_features() # Extract signal features
└── detect() # Detect activity / change points
Choosing the Right Algorithm
Denoising
| Method | Speed | Quality | Best For |
|---|---|---|---|
| wavelet | Medium | High | General-purpose, preserves edges |
| butterworth | Fast | High | Smooth signals, configurable cutoff |
| savgol | Fastest | Medium | Real-time applications, minimal distortion |
Recommendation:
- For research/accuracy: Use butterworth (order=5, cutoff=0.3)
- For speed: Use savgol (window_length=7-11, polyorder=3)
- For noisy environments: Use wavelet (automatic thresholding)
Phase Calibration
| Method | Speed | Quality | Best For |
|---|---|---|---|
| linear | Fastest | Basic | Simple phase errors |
| polynomial | Medium | Good | Non-linear phase distortions |
| stc | Medium | High | CFO/SFO errors (IEEE TWC 2019) |
| robust | Slowest | Highest | Multipath-heavy environments |
Recommendation:
- Default choice: stc (most robust for commodity WiFi)
- Clean environments: linear (fast and sufficient)
- Complex environments: robust (handles outliers)
Normalization
| Method | Output Range | Best For |
|---|---|---|
| z-score | ~N(0,1) | Most DL models, standard choice |
| min-max | [0, 1] | Sigmoid/tanh activation functions |
Interpolation
| Method | Smoothness | Best For |
|---|---|---|
| cubic | Highest | Upsampling, localization |
| linear | Medium | General-purpose |
| nearest | None | Categorical data, downsampling |
Quick Examples
Basic Processing Pipeline
from wsdp.algorithms import denoise, calibrate, normalize
# Chain algorithms manually
denoised = denoise(csi, method='butterworth', order=5, cutoff=0.3)
calibrated = calibrate(denoised, method='stc')
normalized = normalize(calibrated, method='z-score')
Using Presets (Recommended)
from wsdp.algorithms import apply_preset, execute_pipeline
# Use a preset for common use cases
steps = apply_preset('high_quality')
processed = execute_pipeline(csi, steps)
# Available presets:
# 'high_quality' - Maximum accuracy
# 'fast' - Speed-optimized
# 'robust' - Noisy environments
# 'gesture_recognition' - Gesture tasks
# 'activity_detection' - HAR tasks
# 'localization' - Localization tasks
Configuration File
Create algorithms_config.yaml:
denoise:
method: butterworth
params:
order: 5
cutoff: 0.3
calibrate:
method: stc
normalize:
method: z-score
Use it:
from wsdp.algorithms import load_config, execute_pipeline
config = load_config('algorithms_config.yaml')
processed = execute_pipeline(csi, config)
Adding Custom Algorithms
WSDP's pluggable architecture makes it easy to add your own algorithms:
import numpy as np
from wsdp.algorithms import register_algorithm, denoise
# 1. Implement your algorithm
def my_median_denoise(csi, kernel_size=5, **kwargs):
"""Median filter denoising for CSI."""
from scipy.ndimage import median_filter
result = np.empty_like(csi)
for f in range(csi.shape[1]):
for a in range(csi.shape[2]):
real_part = median_filter(np.real(csi[:, f, a]), size=kernel_size)
imag_part = median_filter(np.imag(csi[:, f, a]), size=kernel_size)
result[:, f, a] = real_part + 1j * imag_part
return result
# 2. Register it
register_algorithm('denoise', 'median', my_median_denoise)
# 3. Use it like any built-in algorithm
result = denoise(csi, method='median', kernel_size=7)
Creating Custom Presets
from wsdp.algorithms import register_preset, execute_pipeline
register_preset('my_workflow', {
'denoise': {'method': 'median', 'kernel_size': 7},
'calibrate': {'method': 'stc'},
'normalize': {'method': 'z-score'},
})
steps = apply_preset('my_workflow')
result = execute_pipeline(csi, steps)
Feature Extraction
Extract signal features for downstream ML:
from wsdp.algorithms import extract_features
features = extract_features(csi, features=['doppler', 'entropy', 'ratio'])
# features['doppler'] — Doppler spectrogram (n_freq, n_time, F, A)
# features['entropy'] — Shannon entropy per subcarrier (F, A)
# features['ratio'] — Antenna pair ratios (T, F, n_pairs)
Activity Detection
Detect motion in CSI data:
from wsdp.algorithms import detect_activity, change_point_detection
# Detect activity via sliding window variance
activity = detect_activity(csi, window=32, threshold=0.1)
# Returns: boolean array (T,) — True = activity detected
# Find transition points
change_points = change_point_detection(csi, method='bayesian')
# Returns: array of time indices where transitions occur
Algorithm Performance Tips
- Pipeline order matters: Always denoise before calibrating
- Normalization last: Normalize after all other processing
- Match calibration to noise: STC for CFO-dominant, robust for multipath
- Feature extraction: Do after denoising and calibration for best results
Full API
See the Complete API Reference for all parameters, return values, and academic references.