Skip to main content

CMSIS-DSP Python API

Project description

README

This is a Python wrapper for the Arm open source CMSIS-DSP and it is compatible with NumPy.

The CMSIS-DSP is available on our GitHub or as a CMSIS Pack.

The idea is to follow as closely as possible the C CMSIS-DSP API to ease the migration to the final implementation on a board.

The signal processing chain can thus be tested and developed in a Python environment and then easily converted to a C implementation running on a Cortex-M or Cortex-A board.

A tutorial is also available but with less details than this README: https://developer.arm.com/documentation/102463/latest/

An history of the changes to this wrapper is available at the end of the README.

How to build and install

Tested configurations

The building of this package has been tested on Windows with the Python install from python.org and Microsoft Visual Studio 2022 and on Ubuntu 22.04.

It has also been tested with cygwin. In that case, python-devel must be installed too. On Mac, it was tested with standard XCode installation.

To run the examples, scipy and matplotlib must also be installed.

Other configurations should work but the setup.py file would have to be improved.

Python 3 must be used.

Installing and Building

Installing

It is advised to do it in a Python virtual environment. Then, in the virtual environment you can just do:

pip install cmsisdsp

You must have a recent pip (to automatically install the dependencies like NumPy) and you should have a compiler which can be found by Python when building the package.

DSP examples are available in the CMSIS-DSP PythonWrapper examples folder.

You can also install and run it from Google colab:

This link will open a Jupyter notebook in Google colab for testing. This notebook is from the examples in the CMSIS-DSP GitHub repository.

Building

It it is not working (because it is not possible for us to test all configurations), you can then try to build and install the wrapper manually.

It is advised to do this it into a virtualenv

Since the CMSIS-DSP wrapper is using NumPy, you must first install it in the virtual environment.

> pip install numpy

Once NumPy is installed, you can build the CMSIS-DSP python wrapper. Go to folder CMSIS-DSP.

Now, you can install the cmsisdsp package in editable mode:

> pip install -e .

Before using this command, you need to rebuild the CMSIS-DSP library which is no more built by the setup.py script.

There is a CMakeLists.txt in the PythonWrapper folder for this. The build folders in PythonWrapper are giving some examples of the options to use with the cmake command to generate the Makefile and build the library.

This library is then used by the setup.py script to build the Python extension.

During development,you can rebuild only the object for the extension using : > python setup.py build_ext --inplace

It is faster than just using pip install

To build a wheel you can do: > pip wheel . -w dist

For Darwin with Neon, to force an arm64 build and not an universal build, use: > python setup.py bdist_wheel --plat-name macosx_11_0_arm64 -d dist

The wheel package may have to be installed.

Running the examples

Install some packages to be able to run the examples

> pip install numpy
> pip install scipy
> pip install matplotlib

Depending on the example, you may have to install more packages.

The examples are in the CMSIS-DSP PythonWrapper examples folder.

You can test the scripts testdsp.py and example.py and try to run them from this virtual environment. example.py is requiring a data file to be downloaded from the web. See below in this document for the link.

Note that due to the great number of possible configurations (OS, Compiler, Python), we can't give any support if you have problems compiling the PythonWrapper on your specific configuration. But, generally people manage to do it and solve all the problems.

Usage

The idea is to follow as closely as possible the CMSIS-DSP API to ease the migration to the final implementation on a board.

First you need to import the module

> import cmsisdsp as dsp

If you use numpy:

> import numpy as np

If you use scipy signal processing functions:

> from scipy import signal

Functions with no instance arguments

You can use a CMSIS-DSP function with numpy arrays:

> r = dsp.arm_add_f32(np.array([1.,2,3]),np.array([4.,5,7]))

The function can also be called more simply with

> r = dsp.arm_add_f32([1.,2,3],[4.,5,7])

The result of a CMSIS-DSP function will always be a numpy array whatever the arguments were (numpy array or list).

Functions with instance arguments

When the CMSIS-DSP function is requiring an instance data structure, it is just a bit more complex to use it:

First you need to create this instance:

> firf32 = dsp.arm_fir_instance_f32()

Then, you need to call an init function:

> dsp.arm_fir_init_f32(firf32,3,[1.,2,3],[0,0,0,0,0,0,0])

The third argument in this function is the state. Since all arguments (except the instance ones) are read-only in this Python API, this state will never be changed ! It is just used to communicate the length of the state array which must be allocated by the init function. This argument is required because it is present in the CMSIS-DSP API and in the final C implementation you'll need to allocate a state array with the right dimension.

Since the goal is to be as close as possible to the C API, the API is forcing the use of this argument.

The only change compared to the C API is that the size variables (like blockSize for filter) are computed automatically from the other arguments. This choice was made to make it a bit easier the use of numpy array with the API.

Now, you can check that the instance was initialized correctly.

> print(firf32.numTaps())

Then, you can filter with CMSIS-DSP:

> print(dsp.arm_fir_f32(firf32,[1,2,3,4,5]))

The size of this signal should be blockSize. blockSize was inferred from the size of the state array : numTaps + blockSize - 1 according to CMSIS-DSP. So here the signal must have 5 samples.

If you want to filter more than 5 samples, then you can just call the function again. The state variable inside firf32 will ensure that it works like in the CMSIS-DSP C code.

> print(dsp.arm_fir_f32(firf32,[6,7,8,9,10]))

If you want to compare with scipy it is easy but warning : coefficients for the filter are in opposite order in scipy :

> filtered_x = signal.lfilter([3,2,1.], 1.0, [1,2,3,4,5,6,7,8,9,10])
> print(filtered_x)

The principles are the same for all other APIs.

FFT

Here is an example for using FFT from the Python interface:

Let's define a signal you will use for the FFT.

> nb = 16
> signal = np.cos(2 * np.pi * np.arange(nb) / nb)

The CMSIS-DSP cfft is requiring complex signals with a specific layout in memory.

To remain as close as possible to the C API, we are not using complex numbers in the wrapper. So a complex signal must be converted into a real one. The function imToReal1D is defined in testdsp.py

> signalR = imToReal1D(signal)

Then, you create the FFT instance with:

> cfftf32=dsp.arm_cfft_instance_f32()

You initialize the instance with the init function provided by the wrapper:

> status=dsp.arm_cfft_init_f32(cfftf32, nb)
> print(status)

You compute the FFT of the signal with:

> resultR = dsp.arm_cfft_f32(cfftf32,signalR,0,1)

You convert back to a complex format to compare with scipy:

> resultI = realToIm1D(resultR)
> print(resultI)

Matrix

For matrix, the instance variables are masked by the Python API. We decided that for matrix only there was no use for having the CMSIS-DSP instance visible since they contain the same information as the numpy array (samples and dimension).

So to use a CMSIS-DSP matrix function, it is very simple:

> a=np.array([[1.,2,3,4],[5,6,7,8],[9,10,11,12]])
> b=np.array([[1.,2,3],[5.1,6,7],[9.1,10,11],[5,8,4]])

NumPy result as reference:

> print(np.dot(a , b))

CMSIS-DSP result:

> v=dsp.arm_mat_mult_f32(a,b)
> print(v)

In a real C code, a pointer to a data structure for the result v would have to be passed as argument of the function.

example.py

This example depends on a data file which can be downloaded here:

https://archive.physionet.org/pn3/ecgiddb/Person_87/rec_2.dat

This signal was created for a master thesis:

Lugovaya T.S. Biometric human identification based on electrocardiogram. [Master's thesis] Faculty of Computing Technologies and Informatics, Electrotechnical University "LETI", Saint-Petersburg, Russian Federation; June 2005.

and it is part of the PhysioNet database

Goldberger AL, Amaral LAN, Glass L, Hausdorff JM, Ivanov PCh, Mark RG, Mietus JE, Moody GB, Peng C-K, Stanley HE. PhysioBank, PhysioToolkit, and PhysioNet: Components of a New Research Resource for Complex Physiologic Signals. Circulation 101(23):e215-e220 [Circulation Electronic Pages; http://circ.ahajournals.org/cgi/content/full/101/23/e215]; 2000 (June 13).

Submodules

The Python wrapper is containing three submodules : fixedpoint , mfcc and datatype

fixedpoint is proving some tools to help generating the fixedpoint values expected by CMSIS-DSP.

mfcc is generating some tools to generate the MEL filters, DCT and window coefficients expected by the CMSIS-DSP MFCC implementation.

MEL filters are represented as 3 arrays to encode a sparse array.

datatype is an API on top of fixedpoint to provide more reuse when converting between data formats.

Change history

Version 1.10.2:

  • Release build of CMSIS-DSP for the Neon versions

Version 1.10.1:

  • Some Neon acceleration on Arm aarch64 (with small API differences for FFT)
  • Version 1.10 was removed because of issues in some buffer management

Version 1.9.9:

  • Supports Python 3.12
  • Works with Numpy 2.0
  • Corrections on Cholesky

Version 1.9.8:

  • Compute graph API has been removed
  • Dependency on numpy 1.22 has been lifted, tested through numpy 1.26
  • Inconsistencies in distance and window modules have been fixed.

Version 1.9.7:

  • Upgrade for compatibility with google colab
  • Change to compute graph API for structured datatype
  • Corrected distance issues when using wrapper on aarch64

Version 1.9.6:

  • Corrections to the RFFTs APIs
  • More flexibility in the compute graph to specify the additional arguments of the scheduler and nodes
  • Possibility to set the FIFO scaling factor at FIFO level (in asynchronous mode)

Version 1.9.5:

Same as 1.9.4 but will work in Google Colab.

Version 1.9.4:

  • Dynamic Time Warping API
  • Window functions for FFT
  • New asynchronous mode for the compute graph (see compute graph documentation for more details.

Version 1.9.3:

  • Corrected real FFTs in the wrapper
  • Corrected arm_fir_decimate and arm_fir_interpolate
  • Possibility to customize the FIFO class on a connection for the Python wrapper

Version 1.9.2:

  • New customization options for the compute graph:
    • CAPI
    • CMSISDSP
    • postCustomCName

Version 1.9.1:

  • Small fix to the compute graph generator. The #ifdef at beginning of the custom header should be different for different scheduler names
  • Improve addLiteralArg and addVariableArg in compute graph to use variable number of arguments

Version 1.9.0:

  • New scheduling mode, in the compute graph generator, giving priority to sinks in the scheduling. The idea is to try to decrease the latency between sinks and sources.
  • More customization options (Macros to be defined) in the C++ code generated by the compute graph generator

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

cmsisdsp-1.10.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

cmsisdsp-1.10.2-cp313-cp313-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

cmsisdsp-1.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

cmsisdsp-1.10.2-cp312-cp312-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

cmsisdsp-1.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

cmsisdsp-1.10.2-cp311-cp311-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

cmsisdsp-1.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

cmsisdsp-1.10.2-cp310-cp310-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

cmsisdsp-1.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

cmsisdsp-1.10.2-cp39-cp39-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file cmsisdsp-1.10.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e7a98d48be7a5a317ed5a58390f948c9480e0c648b7bf1452ba25b625eace3e4
MD5 334fa3e4f9e379f0ddd7366fc0e5cc69
BLAKE2b-256 3b3b058e9be32fe8d982b0caaa5001086a6a747a6ea9f54d5bb30374b03ffece

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 48f3b371233d1236aaf25dfdb7fb43e03fd46ef9ecbe919dbdbfd4c4fc2bbd9f
MD5 08d80c233f4d5b31282aa7ce9d86ffa9
BLAKE2b-256 b172f2f360cc712b435924792dad843edb92bccab3f3d858edb918098c917f7c

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 62cd7529ae110019e4616ec0a43b901374bb7a7c0eed4a68a359edb79bcdf50f
MD5 032998d70bfbd45ea1798d89d85ec060
BLAKE2b-256 d334a8be36d3e718dbc0570190cea7f58a84b9247b08188242f0a5ce2bcca27c

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fce7b4afd7fb809ea4d43d018e66b14724c5b35653f33acc9cdd5f5ac4e2bf09
MD5 b856a430d1251e7897e6831c4d97279c
BLAKE2b-256 d46af5d27c2264203f24eca4a3ce3b12cb9e7455c811ba8c893fac92ed336c61

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f93ac3ef8852cb958b1c3e491c07fcdab1541309794fe3a5cf9c373ed5bd0745
MD5 d2a231b46ae7713885e306c147d70883
BLAKE2b-256 88924168321e456cad15f999a3bcfb70e9c7ff2b44295dac6e1901b4baba84a2

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ac3ebbd5a81276f3a95a22bc170e971241d11d972b1043ae8cf6bd3b3a17eee3
MD5 236c778b810c62fa962abeb5695b8dbf
BLAKE2b-256 cd0577303c98e412c0e3fd7200f351f65f0278d67cf09b3262b0d78f456edadd

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0f4c187e96a3a17bbe8e066f3506c090df1d694b5a230d82c4de6613d389c9dc
MD5 396b87493ab86df875a3c988a03c4027
BLAKE2b-256 b1eb0b96ed0d1c802d28141fa956a9aa7e88d6053ad7d36c61d6ec773f2e0957

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b0695dfec2802e58309f52df97884b3d0eeaed793acb30035f7fd69188061960
MD5 4db9397b42da5cc9014b41ac641006e3
BLAKE2b-256 1707357c41706576a7175217a0cbba3e9d02d1610230dfb6ecea52542a5b8642

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6297190277cd0a9dcdf0b9cd3a0d4e575ffb238488e7a4e3c45693c68138843e
MD5 317e532f5839ab54fe04d8bd104579d9
BLAKE2b-256 7673d7a32802b0302a4692a752d0166f5db3323c37ec67da6a782dda4694b725

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.10.2-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.10.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 095be774a7f6c6524e1caa867b4076462f9bf86eb3ea989aec6813fe1f4816cd
MD5 0816c79939d129e45341782723d66d48
BLAKE2b-256 a56763df1770d53139c1a5f9f75d4b8b03c1fe0a09d7a43dd880b3a5e115b5df

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page