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.

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 visibles 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.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.9.9-cp312-cp312-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.12 Windows x86-64

cmsisdsp-1.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.7 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

cmsisdsp-1.9.9-cp312-cp312-macosx_10_9_universal2.whl (7.9 MB view details)

Uploaded CPython 3.12 macOS 10.9+ universal2 (ARM64, x86-64)

cmsisdsp-1.9.9-cp311-cp311-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.11 Windows x86-64

cmsisdsp-1.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

cmsisdsp-1.9.9-cp311-cp311-macosx_10_9_universal2.whl (7.9 MB view details)

Uploaded CPython 3.11 macOS 10.9+ universal2 (ARM64, x86-64)

cmsisdsp-1.9.9-cp310-cp310-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.10 Windows x86-64

cmsisdsp-1.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

cmsisdsp-1.9.9-cp310-cp310-macosx_10_9_universal2.whl (7.9 MB view details)

Uploaded CPython 3.10 macOS 10.9+ universal2 (ARM64, x86-64)

cmsisdsp-1.9.9-cp39-cp39-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.9 Windows x86-64

cmsisdsp-1.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

cmsisdsp-1.9.9-cp39-cp39-macosx_10_9_universal2.whl (7.9 MB view details)

Uploaded CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)

File details

Details for the file cmsisdsp-1.9.9-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 deee0ed5d34c95cebc83cc8ba06b6528614b9a73a4238133063a5b893f91a2c7
MD5 de8c2868629f31e9d0c942527db3c6b0
BLAKE2b-256 4362755824a7f37437af86bf27a7d9ee7400d695882b4e5a003fe3da1f6fa2a9

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b87ee1f128a593657a3d3cefcd3ebaf30b932a44d1e2c4a1b6714a9fd621a67e
MD5 5af85ad37d4bab98b5549c8eae9e1261
BLAKE2b-256 e3acef2b6b9d25b1a182d9e4385e18fb6b233b11388351ddce7163c0996848ea

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp312-cp312-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 dd8fdb4f4e27fe57d4d3e4f9790e5f0344d24e942b62f713c4c2febf586e6e25
MD5 711f3f149ffd9d2dbbdddd512947d9c5
BLAKE2b-256 76e79c812373e1c8d31d6d1378f96efeb59e7925bb3127d46be0c60e4706b1d4

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 21807cd731c737e3209f926dcf7204c80f677855de21d8ee03c85a3063e9aec4
MD5 dccc27b806015b26a2f746e622b3d4f2
BLAKE2b-256 4b7a7bb05abfa34a41b5adaf6c783c8309bbaef9cd4657652e4d64c536940e6a

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 70a92c7f6568d09f62d329d782671739973f133fd972b7a58eac0096e6c8dd16
MD5 27e79bc6d29e77f27a3410e129539416
BLAKE2b-256 7cb48bb20d58cb1238ed3bef9bd93c12ab9a83d73a0939e4d251012952b51e4c

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 f371c0394790824b835099f18d31a9340762f6856b965a927bc2743e9ae6e626
MD5 1f323a31ef17fecf2860eaac0d717b1b
BLAKE2b-256 a3bf216e2d234d9cae01eabfaa62daa7a082525d1ef5105026dc6e6b6a1aa77d

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 187729e1bbfcd4d5fa642dc535ff9870cee0fa76e559dd9870699ca85ae833db
MD5 ae8c6df42acb0e068b6f805e5c4535ef
BLAKE2b-256 0f9cabfa4797cfb33aae99abbfcb8fc97839bcd53d08eb32d3ed4292bec94c64

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d16430c0fbd60ca7f0473ce1c4597d101a8c7bc5ee1e15c89c8ee2e6c0536d4c
MD5 421338d973139368a0718d6d0f61e11d
BLAKE2b-256 804a3af2d76f14b60dbbde587fdb41576bdef3d229db40cf4055a7f5be6ea6e5

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 13a6d764e4f56fc4c5b70850c219406489258950642c4100dbed8e7e51f334c8
MD5 a23fe7f5372f225bf0adda6c7ed404b3
BLAKE2b-256 c46f3489fbf7032ea2178bb713fc401acdf71b9833a08986ecbda4124818d4eb

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: cmsisdsp-1.9.9-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.11

File hashes

Hashes for cmsisdsp-1.9.9-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 2c7e79b8dd8d7d84b86ef0ef2a06d72f19058b6d43da681f55667da215ebf6b7
MD5 795604bb645a22da4cb88192d52e15c8
BLAKE2b-256 37d39f0a2be706b7671b90fc996e1466ed4b5574ca864d1200c742d761118ce9

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7b56892409c1913e40229db086d50f400a87e3455a8f992ee56a613ddcbfa3be
MD5 2c427c63912d10e6e1663a2d878be5ea
BLAKE2b-256 c03cca688584c3320965f999c8eaccbbf3f6bb6cd8e5b0bdc1796a963c3e5cd2

See more details on using hashes here.

File details

Details for the file cmsisdsp-1.9.9-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for cmsisdsp-1.9.9-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 4a0ddc850cb8bb9f0a641260aac07fefa63fa9843f81d5e4b579978cc70bf9ec
MD5 618074c5a627ad1c3831f248447816a7
BLAKE2b-256 b65f1e2302f4b1d9262845b32729918bc0761873500b1502a4da165e41aa1aa5

See more details on using hashes here.

Supported by

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