Flutter科学计算插件scidart的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter科学计算插件scidart的使用

Scidart简介

Scidart logo

SciDart 是一个实验性的跨平台科学库,适用于Dart。其主要目标是在任何可以运行Dart的地方运行,包括Flutter、Dart CLI、Dart web等。

目标 🎯

  • SciDart的主要目标是能够在所有Dart可以运行的地方运行,如Flutter、Dart CLI、Dart Web等。

动机 🏃

  • 该项目起源于作者尝试开发一个基于Flutter的吉他调音器(频率估计器),但发现Dart缺乏统一的科学计算库。为了解决这个问题,并帮助社区,作者创建了SciDart。

Pub链接 🧭

安装方法 🔌

示例代码 ⚒

项目里程碑 🛣

  • 所有项目状态将在GitHub的Projects部分共享和更新。

如何贡献 🙌

  • 建议查看GitHub的Projects部分选择任务或解决SciDart的问题,并实现缺失的部分。阅读CONTRIBUTING.md文件了解更多详情。
  • 所有贡献需要通过SciPy作为参考,并且必须包含测试、文档和示例,否则拉取请求将被阻止。

支持者 ☕

许可证 ⚠

  • SciDart由Angelo Polotto和贡献者提供,遵循Apache-2.0许可证。官方标志由Juliano Polotto创作并分发,遵循CC BY-SA 4.0国际许可。

使用SciDart进行科学计算的完整示例

下面是一个完整的示例,展示了如何使用SciDart来生成信号并估计其频率:

import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';

void main() {
  // 生成用于测试的信号
  // 1Hz正弦波
  var N = 50.0; // 信号长度(秒)
  var fs = 128.0; // 采样率(Hz)
  var n = linspace(0, N, num: (N * fs).toInt(), endpoint: false); // 时间轴
  var f1 = 1.0; // 1Hz
  var sg1 = arraySin(arrayMultiplyToScalar(n, 2 * pi * f1)); // 正弦波信号

  // 从FFT估计频率
  var fEstimated = freqFromFft(sg1, fs);

  print('原始频率和估计频率应该非常接近');
  print('原始频率: $f1 Hz');
  print('估计频率: $fEstimated Hz');
}

double freqFromFft(Array sig, double fs) {
  // 从FFT峰值估计频率

  // 计算加窗信号的傅里叶变换
  // 避免频谱泄漏:https://en.wikipedia.org/wiki/Spectral_leakage
  var windowed = sig * blackmanharris(sig.length);
  var f = rfft(windowed);

  var fAbs = arrayComplexAbs(f);

  // 查找峰值并进行插值以获得更准确的峰值
  var i = arrayArgMax(fAbs); // 仅用于不那么精确的简单版本

  // 抛物线逼近对于离散信号来说是必要的,因为频率可能位于样本之间的某个点上
  var true_i = parabolic(arrayLog(fAbs), i)[0];

  // 转换为等效频率
  return fs * true_i / windowed.length;
}

示例解释

  1. 生成信号

    • 创建了一个1Hz的正弦波信号,持续时间为50秒,采样率为128Hz。
  2. 估计频率

    • 使用快速傅里叶变换(FFT)从生成的信号中估计频率。
    • 为了避免频谱泄漏,使用了Blackman-Harris窗口对信号进行了加窗处理。
    • 通过查找FFT结果中的最大值,并使用抛物线逼近法来提高频率估计的精度。
  3. 输出结果

    • 打印出原始频率和估计频率,验证两者是否接近。

这个示例展示了如何在Flutter应用中使用SciDart进行基本的科学计算和信号处理。希望这对您有所帮助!如果有更多问题,欢迎继续讨论。


更多关于Flutter科学计算插件scidart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter科学计算插件scidart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用scidart插件进行科学计算的一个简单示例。scidart是一个Flutter插件,用于提供数值计算和科学计算功能,类似于Python中的SciPy和NumPy库。

首先,你需要在你的pubspec.yaml文件中添加scidart依赖:

dependencies:
  flutter:
    sdk: flutter
  scidart: ^最新版本号  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

下面是一个简单的Flutter应用示例,展示如何使用scidart进行基本的科学计算,例如生成一个正弦波并进行傅里叶变换:

import 'package:flutter/material.dart';
import 'package:scidart/scidart.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scidart Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ScidartDemo(),
    );
  }
}

class ScidartDemo extends StatefulWidget {
  @override
  _ScidartDemoState createState() => _ScidartDemoState();
}

class _ScidartDemoState extends State<ScidartDemo> {
  List<double> xValues;
  List<double> yValues;
  List<Complex> fftValues;

  @override
  void initState() {
    super.initState();
    generateSineWave();
    computeFFT();
  }

  void generateSineWave() {
    int numPoints = 1000;
    double frequency = 5.0;
    double sampleRate = 100.0;

    xValues = List.generate(numPoints, (i) => i / sampleRate);
    yValues = List.generate(numPoints, (i) => sin(2 * pi * frequency * xValues[i]));
  }

  void computeFFT() {
    fftValues = fft(yValues.map((e) => Complex(real: e, imaginary: 0.0)).toList());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scidart Demo'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Sine Wave Values:'),
          SizedBox(height: 20),
          Expanded(
            child: ListView.builder(
              itemCount: xValues.length,
              itemBuilder: (context, index) {
                return Text('x: ${xValues[index].toStringAsFixed(2)}, y: ${yValues[index].toStringAsFixed(2)}');
              },
            ),
          ),
          SizedBox(height: 20),
          Text('FFT Values:'),
          SizedBox(height: 20),
          Expanded(
            child: ListView.builder(
              itemCount: fftValues.length,
              itemBuilder: (context, index) {
                return Text('FFT[$index]: ${fftValues[index].toString()}');
              },
            ),
          ),
        ],
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 添加依赖:在pubspec.yaml中添加scidart依赖。
  2. 生成正弦波:在generateSineWave函数中,我们生成了一个频率为5Hz的正弦波,采样率为100Hz,生成1000个点。
  3. 计算FFT:在computeFFT函数中,我们使用scidartfft函数对正弦波进行傅里叶变换。
  4. 显示结果:在Flutter界面上显示生成的正弦波值和傅里叶变换结果。

请注意,scidart库中的函数和数据结构(例如Complex类)需要正确导入和使用。上述代码提供了一个基本的框架,你可以根据需要进行扩展和修改。

回到顶部