Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
ConvoLab: A signal processing library for Dart
Dart
branch: master
Failed to load latest commit information.
example
lib change local variable name fix new obscure error
test Update to readme and maintenance status
.gitignore more on fsps and results for websocket
LICENSE.md changed to bsd license from apache
README.md Update to readme and maintenance status
pubspec.yaml added sequence class and functions

README.md

Convolab

A signal processing library for Dart

Note: This library is not currently being maintained.

Overview

The ability to create 2-dimensional, canvas based plots of signal waveforms is available through the simplot library.

The graph-centric algorithms (ie, scc, 2-sat, Prim's MST, Kruskal's MST, all pairs shortest path and the knapsack algorithm) have been moved to the graphlab library.

The library is currently moving its 1-dimensional data structure from List to Sequence, which extends the ListBase class and adds a number of methods and capabilities.

Some features of the library include:

  • Flexible data structures:
    Sequences: generate and easily manipulate impulse, step, position or arbitrary sequences
    Complex numbers: create complex numbers and handle complex calculations
  • Hyperbolic and logarithmic functions: sinh(), cosh(), log2(), log10() etc.
  • Simple waveform generator: square, pulse, triangular, etc.
  • Polynomial string construction in text, HTML or latex format
  • Common signal processing algorithms including (more are in development):
    fft(): fast and discrete Fourier transform
    ifft(): fast and discrete inverse Fourier transform
    fsps(): partial sums of Fourier series
    conv(): convolution
    deconv(): deconvolution
    corr(): cross and auto correlation
    filter(): a 1D transposed direct form II digital filter structure

Most library access is through top level function calls.

Library Usage:

Add the following to your pubspec.yaml:

convolab:
  git: git://github.com/scribeGriff/ConvoLab.git

Then import the library to your app:

import 'package:convolab/convolab.dart';

Sequences

The library is currently moving to using Sequences as the main data structure. A sequence extends from the ListBase class and therefore shares many of the same methods of the List data type. Some examples of using a Sequence data structure:

// Creates a List object.
var list = [1, 2, 3, 4];
// Converts the List into a Sequence.
var seq1 = sequence(list);
// Check if seq1 is a Sequence.
print(seq1 is Sequence);
// Print the sequence.
print(seq1);
// Prints:
// true
// [1, 2, 3, 4]

// Any Iterable, including another sequence, can be passed to the
// sequence function.
var seq2 = sequence(list.map((element) => element * 2));

// Sequences can be added, subtracted, multiplied, and divided element
// by element:
var seq3 = seq1 + seq2;
print(seq3);
// Prints:
// [3, 6, 9, 12]

// and element by number:
var seq4 = seq3 * 2;
print(seq4);
// Prints: 
// [6, 12, 18, 24]

// Sequences can be made periodic:
print(sequence(seq1, 4));
// Prints:
// [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]

Sequences allow us to perform a variety of tasks on sampled data. For example, suppose we had a sample sequence, x(n), and we wanted to know what x1(n) = 2x(n - 5) - 3x(n + 4) was.

// x(n)
Sequence x = sequence([1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1]);
// n, zeroth position at element 2.
Sequence n = x.position(2);
// n - 5
Sequence nm5 = shiftseq(n, 5);
// n + 4
Sequence np4 = shiftseq(n, -4);
// x1(n) = 2x(n - 5) - 3x(n + 4)
var x1 = addseqs(x * 2, x * -3, nm5, np4);
print(x1.x);
print(x1.n);
// Prints:
// [-3, -6, -9, -12, -15, -18, -21, -18, -15, -10, -5, 0, 5, 10, 12, 14, 12, 10, 8, 6, 4, 2]
// [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

The function, addseqs(), allows us to add sequences that have position information. In this example, the n = 0 sample point was the 3rd element in the sequence x(n). The function shiftseq() (as well as foldseq()), are also methods of the Sequence class. Therefore, we could do the following:

var x2 = position(11, 5);
print(x2);
print(x2.shiftseq(2).foldseq(negate:true));
// Prints:
// [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
// [-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3] 

The position() function creates a sample position sequence 11 samples long and places the 0 position at the 6th position in the sequence (sequences, like all Iterables in the Dart programming language, are based on the first element being element 0).

To convert a sequence to a list, simply use the toList() method of the ListBase class.

Sequence methods (other than those inherited from ListBase)

  • + operator - adds a sequence to another sequence of the same length or to a number
  • - operator - subtracts a sequence from another sequence of the same length or from a number
  • * operator - multiplies a sequence by another sequence of the same length or by a number
  • / operator - divides a sequence by another sequence of the same length or by a number
  • position() - creates a position sequence
  • shiftseq() - shifts a sequence
  • foldseq() - folds(ie, reverses) a sequence
  • toReal() - converts a complex sequence to a real valued sequence
  • toComplex() - converts a real sequence to a complex valued sequence
  • equals() - returns a boolean indicating element by element equivalence between two sequences
  • abs() - returns a sequence with the absolute value of each element
  • min() - returns the minimum of a sequence
  • max() - returns the maximum of a sequence
  • sum() - returns the sum of a sequence
  • prod() - returns the product of a sequence
  • energy() - returns the energy of a sequence
  • power() - returns the power of a sequence
  • iterator - returns an iterator to the sequence (allows for in and forEach)
  • middle - returns the index of the middle element of the sequence (truncates)

Sequence functions

  • sequence() - create a new sequence from an Iterable
  • position() - creates a position sequence
  • zeros() - creates a sequence of zeros
  • ones() - creates a sequence of ones
  • impseq() - creates an impulse sequence
  • stepseq() - creates a step sequence
  • shiftseq() - shifts a sequence
  • foldseq() - folds (ie, reverses) a sequence
  • addseqs() - adds sequences that are of differing lengths and/or have position information
  • multseqs() - multiplies sequences that are of differing lengths and/or have position information
  • evenodd() - decompose a sequence into its even and odd components.

Complex Numbers

The library contains support for complex numbers. A complex number can be defined as follows:

var c = complex(1, 2);
print(c.string);
// Prints:
// 1.00 + 2.00j

The complex class implements the following methods:

  • string - returns the complex number as a string
  • magnitude - returns the magnitude of a complex number
  • phase - returns the phase of a complex number
  • croud2 - rounds fractional part of complex number to two significant digits
  • conj - returns the complex conjugate of the complex number
  • recip - returns the reciprocal of the complex number
  • cexp - returns the complex exponential of the complex number
  • csin - returns the complex sine of the complex number
  • ccos - returns the complex cosine of the complex number
  • ctan - returns the complex tangent of the complex number
  • scale() - scales the complex number by a number of type int or double
  • + operator adds a complex number to another complex number
  • - operator subtracts a complex number from another complex number
  • * operator multiplies a complex number by another complex number
  • / operator divides a complex number by another complex number
  • == operator checks if two complex numbers are equal (hashCode is implemented)

Poly Strings

To convert a sequence to a readable polynomial string, the library contains a function called pstring(). The function can generate strings in text, HTML, or Latex format. In its simplest form, pstring() requires only a sequence of polynomial coefficients:

// Simple case - defaults
Sequence coefficients = sequence([2, 5, -3, 7]);
String polyString = pstring(coefficients);
print(polyString);
// prints:
// $$f(x) = 2 + 5x^{-1} - 3x^{-2} + 7x^{-3}$$

The Latex format, for use with MathJax in a browser, is the default. The pstring() function also accepts several named optional parameters:

  • index: for causal signals, this is the n = 0 position index (default = 0)
  • type: String representing desired format text, html, latex (default = 'latex')
  • variable: String representing the variable name (default = 'x')
  • name: String representing the function name (default = 'f')

Some additional examples:

// Setting options - html format.
polyString = pstring(coefficients, type: 'html', name: 'y', variable: 'n');
print(polyString);
// prints:
// y(n) = 2 + 5n<sup>-1</sup> - 3n<sup>-2</sup> + 7n<sup>-3</sup>

// Send the output to element on a webpage
query("#myDiv").appendHtml(pstring(test, type:'html'));

// Working with causal signals.
zeroIndex = 2;
polyString = pstring(coefficients, index: zeroIndex, type: 'html', name: 'y', variable: 'n');
print(polyString);
// prints:
// y(n) = 2n<sup>2</sup> + 5n - 3 + 7n<sup>-1</sup>

// Another example working with causal signals.
coefficients = sequence([1, 1, 1, 1, 1, 1]);
polyString = pstring(coefficients, index: zeroIndex, type: 'text');
print(polyString);
// prints:
// f(x) = x^2 + x + 1 + x^-1 + x^-2 + x^-3

The library functions conv() and deconv() both implement the PolyString class as a format() method to the function results. In the case of deconv(), the format() method handles remainders.


Something went wrong with that request. Please try again.