SciDart

Signal processing

FIR filter design, filtering, peaks, window functions and convolution.

Like scipy.signal

FIR filters

firwin designs a linear phase FIR filter with the window method, like scipy.signal.firwin, and lfilter applies it. pass_zero accepts true, false, 'lowpass', 'highpass', 'bandpass' and 'bandstop'.

Low-pass FIR filterDesign a filter with firwin and apply it with lfilter to remove a high frequency.
import 'dart:math' as math;

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

void main() {
  var fs = 100.0;
  var t = linspace(0, 1, num: 100, endpoint: false);
  var slow = arraySin(arrayMultiplyToScalar(t, 2 * math.pi * 2));
  var fast = arraySin(arrayMultiplyToScalar(t, 2 * math.pi * 30));
  var x = slow + fast;

  // 31 taps, cutoff at 10 Hz
  Array b = firwin(31, Array([10]), fs: fs);
  var y = lfilter(b, Array([1]), x);

  // after the filter delay (15 samples), y follows the slow wave
  var error = 0.0;
  for (var i = 30; i < 100; i++) {
    error = math.max(error, (y[i] - slow[i - 15]).abs());
  }
  print('taps: ${b.length}, sum of taps: ${arraySum(b).toStringAsFixed(6)}');
  print('max difference to the 2 Hz wave: ${error.toStringAsFixed(4)}');
}
Output
taps: 31, sum of taps: 1.000000
max difference to the 2 Hz wave: 0.0017

Loading the interactive demo…

Peaks

Find peaksLocal maxima of a signal, optionally above a threshold.
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';

void main() {
  var a = Array([0, 2, 1, 3, 0, 1, 5, 2, 0]);
  var all = findPeaks(a);
  print(
      'indexes: ${(all[0] as Array).toList()}, values: ${(all[1] as Array).toList()}');

  var tall = findPeaks(a, threshold: 3);
  print(
      'above 3: indexes ${(tall[0] as Array).toList()}, values ${(tall[1] as Array).toList()}');
}
Output
indexes: [1.0, 3.0, 6.0], values: [2.0, 3.0, 5.0]
above 3: indexes [3.0, 6.0], values [3.0, 5.0]

Window functions

hann, hamming, blackman, blackmanharris, nuttall, flattop and kaiser, plus getWindow to pick one by name. With sym: false they return the periodic version used for spectral analysis.

Window functionsHann, Hamming, Blackman and Kaiser windows, like scipy.signal.windows.
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';

void main() {
  String show(Array w) => w.map((v) => v.toStringAsFixed(4)).join(', ');
  print('hann(5):     ${show(hann(5))}');
  print('hamming(5):  ${show(hamming(5))}');
  print('blackman(5): ${show(blackman(5))}');
  print('kaiser(5, 8): ${show(kaiser(5, 8))}');
}
Output
hann(5):     0.0000, 0.5000, 1.0000, 0.5000, 0.0000
hamming(5):  0.0800, 0.5400, 1.0000, 0.5400, 0.0800
blackman(5): -0.0000, 0.3400, 1.0000, 0.3400, -0.0000
kaiser(5, 8): 0.0023, 0.3690, 1.0000, 0.3690, 0.0023

Loading the interactive demo…

Convolution

Convolution and moving averageConvolve a signal with a kernel; a box kernel gives a moving average.
import 'package:scidart/numdart.dart';
import 'package:scidart/scidart.dart';

void main() {
  var x = Array([1, 2, 3, 4, 5]);
  print(convolution(x, Array([1, 1, 1])).toList());
  print(arrayDivisionToScalar(convolution(x, Array([1, 1, 1])), 3).toList());
  print(correlate(x, Array([0, 1, 0.5])).toList());
}
Output
[1.0, 3.0, 6.0, 9.0, 12.0, 9.0, 5.0]
[0.3333333333333333, 1.0, 2.0, 3.0, 4.0, 3.0, 1.6666666666666667]
[0.5, 2.0, 3.5, 5.0, 6.5, 5.0, 0.0]

convolution and correlate return the full result, like numpy.convolve(..., mode='full'). Pass fast: true to compute them through the FFT.

Edit this guide on GitHub