A Rust library for scientific and signal processing filters, including:
- Butterworth / Bessel / Chebyshev I & II filters
- SMA / EMA / EMS
- Gaussian & Median filters
- Frequency-domain utilities (in progress)
使用说明
- 滤波算法示例
use std::{f32::consts::PI, time::Instant};
use scientific_cal::{bessel, butter_worth, cheby1, cheby2, correlate1d, ema, gaussian1d, median_filter, rma, sma, sosfilt, BesselCriterion, FilterBand, FilterSelect};
#[test]
fn bessel_filter_test() -> Result<(), String>{
// 参数输入
let order = 4;
let fs = 1000.0;
let cutoff = 5.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 sos = if let Ok(s) = bessel(
order as usize, // 阶数
&mut vec![cutoff], // 截止频率为5hz
FilterBand::LowPass,
false,
FilterSelect::Bessel(BesselCriterion::Delay),
Some(fs) // 采样频率为1khz 可以为None 但是 截止频率 wn = cutoff / (fs / 2)
){
s
}else{
return Err("".to_string());
};
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
let output = sosfilt(&sos, &raw_data);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn butter_worth_filter_test() -> Result<(), String>{
// 参数输入
let order = 4;
let fs = 1000.0;
let cutoff = 5.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 sos = if let Ok(s) = butter_worth(
order as usize, // 阶数
&mut vec![cutoff], // 截止频率为5hz
FilterBand::LowPass,
false,
Some(fs) // 采样频率为1khz 可以为None 但是 截止频率 wn = cutoff / (fs / 2)
){
s
}else{
return Err("".to_string());
};
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
let output = sosfilt(&sos, &raw_data);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn cheby1_filter_test() -> Result<(), String>{
// 参数输入
let order = 4;
let fs = 1000.0;
let cutoff = 5.0;
let rp = 1.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 sos = if let Ok(s) = cheby1(
order as usize, // 阶数
&mut vec![cutoff], // 截止频率为5hz
FilterBand::LowPass,
false,
Some(fs), // 采样频率为1khz 可以为None 但是 截止频率 wn = cutoff / (fs / 2)
Some(rp),
None
){
s
}else{
return Err("".to_string());
};
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
let output = sosfilt(&sos, &raw_data);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn cheby2_filter_test() -> Result<(), String>{
// 参数输入
let order = 4;
let fs = 1000.0;
let cutoff = 5.0;
let rs = 20.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 sos = if let Ok(s) = cheby2(
order as usize, // 阶数
&mut vec![cutoff], // 截止频率为5hz
FilterBand::LowPass,
false,
Some(fs), // 采样频率为1khz 可以为None 但是 截止频率 wn = cutoff / (fs / 2)
None,
Some(rs)
){
s
}else{
return Err("".to_string());
};
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
let output = sosfilt(&sos, &raw_data);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn gauss_filter_test() -> Result<(), String>{
// 参数输入
let fs = 1000.0;
let cutoff = 5.0;
let truncate = 4.0;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 weights = if let Ok(s) = gaussian1d(
fs,
cutoff,
truncate,
None
){
s
}else{
return Err(String::from(""));
};
println!("滤波初始化参数耗时: {:?}", start.elapsed());
start = Instant::now();
// 开始计算
let output = if let Ok(result) = correlate1d(&raw_data, &weights, -1, "reflect", 0.0, 0) {
result
}else {
return Err(String::from(""));
};
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn move_median_filter_test() -> Result<(), String>{
// 参数输入
let window_size = 5;
let precision = 0.2;
let fs = 1000;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 = median_filter(&raw_data, window_size as usize, precision);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn move_ema_filter_test() -> Result<(), String>{
// 参数输入
let window_size = 5;
let fs = 1000;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 = ema(&raw_data, window_size as usize);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn move_rma_filter_test() -> Result<(), String>{
// 参数输入
let window_size = 5;
let fs = 1000;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 = rma(&raw_data, window_size as usize);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
#[test]
fn move_sma_filter_test() -> Result<(), String>{
// 参数输入
let window_size = 5;
let fs = 1000;
// 仿真数据
let dt = 1.0 / fs as f32;
let 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 as usize);
println!("滤波运行耗时: {:?}", start.elapsed());
println!("{:?}", &output[0..10]);
Ok(())
}
🚀 Quick Start
Add this to your Cargo.toml: