[![Crates.io](https://img.shields.io/crates/v/scientific-cal.svg)](https://crates.io/crates/scientific-cal)
[![Downloads](https://img.shields.io/crates/d/scientific-cal.svg)](https://crates.io/crates/scientific-cal)
[![Docs.rs](https://img.shields.io/badge/docs.rs-scientific--cal-blue)](https://docs.rs/scientific-cal)
---
## 简介
这是一个用 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） | 🚧 规划中 |

> 当前所有滤波器仅实现了低通 / 高通功能，带通与带阻支持将于后续版本添加。


## 📦 使用说明

1.  数字滤波器示例
```rs
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(())
}

```
2.  平滑算法示例
```rs
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(())
}

```
3.  频谱分析示例
```rs
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();
    println!("raw_data: {:?}", &raw_data[0..10]);
    // 开始计算
    let start = Instant::now();

    let mut fft_result = fft(&raw_data)?;
    println!("fft_result: {:?}", &fft_result[0..10]);
    
    // 可以自定义滤波
    // 略
    // ifft
    // 幅值需要取共轭除以 N 
    let n = raw_data.len();
    for f in fft_result.iter_mut(){
        *f = Complex::new(f.re, -f.im) / (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 安装 
```bash
cargo add scientific-cal
```
or
```bash
cargo add scientific-cal --no-default-features --features filters

```
##### Cargo.toml 配置
```toml
# In your Cargo.toml
[dependencies]
scientific-cal = "0.2.0"
```
or
```toml
[dependencies]
scientific-cal = { version = "0.2.0", default-features = false, features = ["filters"] }
```
