
简介
这是一个用 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::{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)?; 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]);
let n = raw_data.len();
for f in fft_result.iter_mut(){
*f = *f / (n as f32)
}
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:
shell 安装
cargo add scientific-cal
or
cargo add scientific-cal --no-default-features --features filters
Cargo.toml 配置
[dependencies]
scientific-cal = "0.2.0"
or
[dependencies]
scientific-cal = { version = "0.2.0", default-features = false, features = ["filters"] }