scientific-cal 0.1.2

scientific cal
Documentation

Crates.io Downloads Docs.rs

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)

使用说明

  1. 滤波算法示例
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:

cargo add scientific-cal