这是一个用 Rust 编写的高性能科学计算信号处理库,旨在逐步重现 Python 中广泛使用的 scipy.signal 模块功能。该库专注于滤波器设计、信号平滑、频域分析以及模态分解等,适用于嵌入式系统、实时处理、高性能计算等对性能和稳定性有较高要求的场景
📦 模块功能覆盖情况(Rust 替代 SciPy.signal)
| 模块类型 | 功能 | 状态 |
|---|---|---|
| 数字滤波器 | Butterworth(低通 / 高通) | ✅ 已完成 |
| Bessel(低通 / 高通) | ✅ 已完成 | |
| Chebyshev I(低通 / 高通) | ✅ 已完成 | |
| Chebyshev II(低通 / 高通) | ✅ 已完成 | |
| Gaussian(低通) | ✅ 已完成 | |
| 带通 / 带阻支持 | 🚧 规划中 | |
| 平滑算法 | 中值滤波(Median filter) | ✅ 已完成 |
| SMA(Simple Moving Average) | ✅ 已完成 | |
| EMA(Exponential Moving Average) | ✅ 已完成 | |
| RMA(Running Moving Average) | ✅ 已完成 | |
| 频域分析 | FFT / IFFT | ✅ 已完成 |
| RFFT / IRFFT | 🚧 待实现 | |
| Hilbert 变换 | 🚧 规划中 | |
| 模态分解 | EMD(经验模态分解) | 🚧 规划中 |
| EEMD(集合经验模态分解) | 🚧 规划中 | |
| CEEMD(完全集合 EMD) | 🚧 规划中 | |
| 实用函数 | 极值点检测(find_peaks) | 🚧 规划中 |
| 样条插值器(Spline interpolation) | 🚧 规划中 |
当前所有滤波器仅实现了低通 / 高通功能,带通与带阻支持将于后续版本添加。
📦 使用说明
- 数字滤波器示例
use std::{f32::consts::PI, time::Instant};
// use scientific_cal::{bessel, butter_worth, FilterBand, FilterSelect, Sosfit};
use scientific_cal::{filters::{filter_factory, BesselCriterion, FilterBand, FilterType}, ScientificError};
#[test]
fn bessel_filter_test() -> Result<(), ScientificError>{
// 参数输入
let order = 4;
let fs = 1000.0;
let cutoff = 5.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let mut raw_data: Vec<f32> = (0..fs as i32)
.map(|i| {
let t = i as f32 * dt;
(2.0 * PI * 2.0 * t).sin() + 0.5 * (2.0 * PI * 20.0 * t).sin()
})
.collect();
// 定义低通滤波器
let mut start = Instant::now();
let ftype = FilterType::Bessel {
order: order,
cutoff: vec![cutoff],
band: FilterBand::LowPass,
analog: false,
criterion: BesselCriterion::Delay,
fs: Some(fs),
};
let filter = filter_factory::<f32>().create(ftype)?;
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
println!("滤波前:{:?}", &raw_data[0..10]);
let _ = filter.apply_inplase(&mut raw_data)?;
println!("滤波运行耗时: {:?}", start.elapsed());
println!("滤波后:{:?}", &raw_data[0..10]);
Ok(())
}
- 平滑算法示例
use std::{f32::consts::PI, time::Instant};
use scientific_cal::{smooth::{sma, ema, rma, sma_inplase,}, ScientificError};
#[test]
fn move_ema_filter_test() -> Result<(), ScientificError>{
// 参数输入
let window_size = 5;
let fs = 100000;
// 仿真数据
let dt = 1.0 / fs as f32;
let mut raw_data: Vec<f32> = (0..fs as i32)
.map(|i| {
let t = i as f32 * dt;
(2.0 * PI * 2.0 * t).sin() + 0.5 * (2.0 * PI * 20.0 * t).sin()
})
.collect();
// 开始计算
let start = Instant::now();
let output = sma(&raw_data, window_size)?; // ema rma用法一样
// sma_inplase(&mut raw_data, window_size)?; // ema rma 没有实现 inplase
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
- 频谱分析示例
use std::{f32::consts::PI, time::Instant};
use scientific_cal::{spectrum::{fft, ifft}, ScientificError};
#[test]
fn fft_test() -> Result<(), ScientificError>{
// 参数输入
let n = 1024;
// 仿真数据
let raw_data: Vec<f32> = (0..n as i64)
.map(|i| {
(2.0 * PI * i as f32 / n as f32).sin()
})
.collect();
// 开始计算
let start = Instant::now();
let mut fft_result = fft(&raw_data)?;
println!("fft_result: {:?}", &fft_result[0..10]);
// 幅值需要除以 N
let n = raw_data.len();
for f in fft_result.iter_mut(){
*f = *f / (n as f32)
}
// 可以自定义滤波
// 略
// 反fft
let ifft_result = ifft(&mut fft_result)?;
println!("fft运行耗时: {:?}", start.elapsed());
println!("ifft_result: {:?}", &ifft_result[0..10]);
Ok(())
}
🚀 Quick Start
Add this to your Cargo.toml: