Skip to content

Commit

Permalink
Fixes to Python wrapper examples. Changes to work with Python 3.12
Browse files Browse the repository at this point in the history
  • Loading branch information
christophe0606 committed Jun 17, 2024
1 parent 60f22e0 commit b8db1e4
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 92 deletions.
2 changes: 1 addition & 1 deletion PythonWrapper/build/create.bat
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake -DHOST=YES ^
-DLOOPUNROLL=ON ^
-DWRAPPER=YES ^
-DCMSISDSP=".." ^
-DCMSISDSP="path to CMSIS-DSP folder" ^
-DCMAKE_C_FLAGS_RELEASE="-std=c11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra" ^
-DCMAKE_CXX_FLAGS_RELEASE="-fno-rtti -std=c++11 -Ofast -ffast-math -DNDEBUG -Wall -Wextra -Wno-unused-parameter" ^
-G "Unix Makefiles" ..
Expand Down
2 changes: 1 addition & 1 deletion PythonWrapper/cmsisdsp_pkg/src/cmsisdsp_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include <numpy/numpyconfig.h>

// API version used on google colab
// List in https://github.com/numpy/numpy numpyconfig.h
// https://github.com/numpy/numpy/blob/main/numpy/_core/include/numpy/numpyconfig.h
#if (NPY_API_VERSION != 0x0000000F )
//#error("Error building with wrong NumPy API version")
#endif
Expand Down
107 changes: 53 additions & 54 deletions PythonWrapper/examples/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import colorama
from colorama import init,Fore, Back, Style
from numpy.testing import assert_allclose
import scipy.spatial.distance as d

init()

Expand All @@ -19,63 +20,61 @@ def printSubTitle(s):
print("\n" + Style.BRIGHT + s + Style.RESET_ALL)


def chop(A, eps = 1e-6):
B = np.copy(A)
B[np.abs(A) < eps] = 0
return B
def packset(a):
b = np.packbits(a)
newSize = int(np.ceil(b.shape[0] / 4.0)) * 4
c = np.copy(b).astype(np.uint32)
c.resize(newSize)
#print(c)
vecSize = round(newSize/4)
c=c.reshape(vecSize,4)
#print(c)
r = np.zeros(vecSize)
result = []
for i in range(0,vecSize):
print(c[i,:])
#print("%X %X %X %X" % (c[i,0],c[i,1],c[i,2],c[i,3]))
d = (c[i,0] << 24) | (c[i,1] << 16) | (c[i,2] << 8) | c[i,3]
result.append(np.uint32(d))
return(result)

nb = 32
signal = np.cos(2 * np.pi * np.arange(nb) / nb)*np.cos(0.2*2 * np.pi * np.arange(nb) / nb)
nb = 34
#va = np.random.choice([0,1],nb)
# Array of word32 containing all of our bits
#pva = packset(va)

ref=scipy.fft.rfft(signal)
invref = scipy.fft.irfft(ref)

print(f"ref length = {len(ref)}")
print(ref)
#vb = np.random.choice([0,1],nb)
# Array of word32 containing all of our bits
#pvb = packset(vb)
#
va=[1, 0, 1, 0, 1, 1, 1, 0 ,0, 1, 1, 0, 1, 0, 0, 0, 0, 1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,1,1]
vb=[0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,1,0,0,0,1,0]

va = np.array(va)
vb = np.array(vb)

pva=packset(va)
pvb=packset(vb)

#pva = [np.uint32(167), np.uint32(0)]
#pvb = [np.uint32(152), np.uint32(0)]

#print(va,pva)
#print(vb,pvb)

ctt=1.0*np.count_nonzero((va==1) & (vb==1))
ctf=1.0*np.count_nonzero((va==1) & (vb==0))
cft=1.0*np.count_nonzero((va==0) & (vb==1))

res=(cft+ctf)/(2*ctt+cft+ctf)

# Convert ref to CMSIS-DSP format
referenceFloat=np.zeros(2*len(ref))
print(f"referenceFloat length = {len(referenceFloat)}")
# Replace complex datatype by real datatype
referenceFloat[0::2] = np.real(ref)
referenceFloat[1::2] = np.imag(ref)
# Copy Nyquist frequency value into first
# sample.This is just a storage trick so that the
# output of the RFFT has same length as input
# It is legacy behavior that we need to keep
# for backward compatibility but it is not
# very pretty
#referenceFloat[1] = np.real(ref[-1])

rifftQ31=dsp.arm_rfft_instance_q31()
status=dsp.arm_rfft_init_q31(rifftQ31,nb,1,1)
# Apply CMSIS-DSP scaling
referenceQ31 = f.toQ31(referenceFloat / nb)

resultQ31 = dsp.arm_rfft_q31(rifftQ31,referenceQ31)
resultF = f.Q31toF32(resultQ31)

print(f"resultF length = {len(resultF)}")
assert_allclose(invref/nb,resultF,atol=1e-6)

signalQ31 = f.toQ31(signal)
rfftQ31=dsp.arm_rfft_instance_q31()
status=dsp.arm_rfft_init_q31(rfftQ31,nb,0,1)
resultQ31 = dsp.arm_rfft_q31(rfftQ31,signalQ31)
print(len(resultQ31))
print(2*nb)
resultF = f.Q31toF32(resultQ31) * nb

def compareWithConjugatePart(r):
res = r[0::2] + 1j * r[1::2]
conjPart = res[nb:nb//2:-1].conj()
refPart = res[1:nb//2]
assert(np.equal(refPart , conjPart).all())

compareWithConjugatePart(resultF)

res = resultF[0::2] + 1j * resultF[1::2]
print(res)

print(res[0:nb//2+1])
print(res[0:nb//2+1].shape)

print("\nDice")
ref=d.dice(va,vb)
res=dsp.arm_dice_distance(pva,pvb,nb)
print(ref)
print(res)
assert_allclose(ref,res,1e-6)
34 changes: 18 additions & 16 deletions PythonWrapper/examples/example_1_11.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,26 +122,28 @@ def printSubTitle(s):

printSubTitle("With a window")

nan = np.nan

referenceDistance = 0.617099940776825
referenceCost=np.array([[9.1612804e-01, 9.9920368e-01, np.NAN, np.NAN,
np.NAN],
[1.2353053e+00, 1.6792301e+00, np.NAN, np.NAN,
np.NAN],
[1.3028694e+00, 2.3696373e+00, 4.4372001e+00, np.NAN,
np.NAN],
[np.NAN, 3.0795674e+00, 4.9687119e+00, np.NAN,
np.NAN],
[np.NAN, 3.5039051e+00, 4.9290380e+00, 5.3565612e+00,
np.NAN],
[np.NAN, np.NAN, 4.8520918e+00, 5.1756082e+00,
np.NAN],
[np.NAN, np.NAN, 5.0427418e+00, 5.8497019e+00,
referenceCost=np.array([[9.1612804e-01, 9.9920368e-01, nan, nan,
nan],
[1.2353053e+00, 1.6792301e+00, nan, nan,
nan],
[1.3028694e+00, 2.3696373e+00, 4.4372001e+00, nan,
nan],
[nan, 3.0795674e+00, 4.9687119e+00, nan,
nan],
[nan, 3.5039051e+00, 4.9290380e+00, 5.3565612e+00,
nan],
[nan, nan, 4.8520918e+00, 5.1756082e+00,
nan],
[nan, nan, 5.0427418e+00, 5.8497019e+00,
7.6590457e+00],
[np.NAN, np.NAN, np.NAN, 6.7571073e+00,
[nan, nan, nan, 6.7571073e+00,
8.6668968e+00],
[np.NAN, np.NAN, np.NAN, 7.3949833e+00,
[nan, nan, nan, 7.3949833e+00,
9.0352430e+00],
[np.NAN, np.NAN, np.NAN, np.NAN,
[nan, nan, nan, nan,
9.2564993e+00]], dtype=np.float32)


Expand Down
14 changes: 11 additions & 3 deletions PythonWrapper/examples/testdistance.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
a=[1,2,3]
b=[1,5,2]

def kulsinski(va,vb):
n = len(va)
ctt=1.0*np.count_nonzero((va==1) & (vb==1))
ctf=1.0*np.count_nonzero((va==1) & (vb==0))
cft=1.0*np.count_nonzero((va==0) & (vb==1))
return(1.0*(ctf + cft - ctt+n)/(cft + ctf + n))


print("\nBray-Curtis")
ref=d.braycurtis(a,b)
res=dsp.arm_braycurtis_distance_f32(a,b)
Expand Down Expand Up @@ -96,7 +104,7 @@
def packset(a):
b = np.packbits(a)
newSize = int(np.ceil(b.shape[0] / 4.0)) * 4
c = np.copy(b)
c = np.copy(b).astype(np.uint32)
c.resize(newSize)
#print(c)
vecSize = round(newSize/4)
Expand All @@ -105,7 +113,7 @@ def packset(a):
r = np.zeros(vecSize)
result = []
for i in range(0,vecSize):
#print(c[i,:])
print(c[i,:])
#print("%X %X %X %X" % (c[i,0],c[i,1],c[i,2],c[i,3]))
d = (c[i,0] << 24) | (c[i,1] << 16) | (c[i,2] << 8) | c[i,3]
result.append(np.uint32(d))
Expand Down Expand Up @@ -143,7 +151,7 @@ def packset(a):
assert_allclose(ref,res,1e-6)

print("\nKulsinski")
ref=d.kulsinski(va,vb)
ref=kulsinski(va,vb)
res=dsp.arm_kulsinski_distance(pva,pvb,nb)
print(ref)
print(res)
Expand Down
6 changes: 5 additions & 1 deletion PythonWrapper/examples/testdsp6.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,14 @@
supportVectors = supportVectors.reshape(nbSupportVectors * VECDIM)

svmInst=dsp.arm_svm_polynomial_instance_f32()


dsp.arm_svm_polynomial_init_f32(svmInst,nbSupportVectors,vectorDimensions,
intercept,dualCoefs,supportVectors,
intercept[0],dualCoefs,supportVectors,
[0,1],degree,coef0,gamma)

exit(0)

test1 = np.array([0.4,0.1])
predicted1 = dsp.arm_svm_polynomial_predict_f32(svmInst,test1)
print(predicted1)
Expand Down
2 changes: 1 addition & 1 deletion PythonWrapper/examples/testmfcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
freq_high = sample_rate / 2
numOfMelFilters = 20

window = sig.hamming(FFTSize, sym=False)
window = sig.windows.hamming(FFTSize, sym=False)

filtLen,filtPos,packedFilters = mfcc.melFilterMatrix(F32,freq_min, freq_high, numOfMelFilters,sample_rate,FFTSize)

Expand Down
2 changes: 1 addition & 1 deletion PythonWrapper/examples/testmfccq15.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
freq_high = sample_rate / 2
numOfMelFilters = 20

windowQ15 = dt.convert(sig.hamming(FFTSize, sym=False),Q15)
windowQ15 = dt.convert(sig.windows.hamming(FFTSize, sym=False),Q15)
filtLen,filtPos,packedFiltersQ15 = mfcc.melFilterMatrix(Q15,freq_min, freq_high, numOfMelFilters,sample_rate,FFTSize)
dctMatrixFiltersQ15 = mfcc.dctMatrix(Q15,numOfDctOutputs, numOfMelFilters)

Expand Down
2 changes: 1 addition & 1 deletion PythonWrapper/examples/testmfccq31.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
freq_high = sample_rate / 2
numOfMelFilters = 20

windowQ31 = dt.convert(sig.hamming(FFTSize, sym=False),Q31)
windowQ31 = dt.convert(sig.windows.hamming(FFTSize, sym=False),Q31)
filtLen,filtPos,packedFiltersQ31 = mfcc.melFilterMatrix(Q31,freq_min, freq_high, numOfMelFilters,sample_rate,FFTSize)
dctMatrixFiltersQ31 = mfcc.dctMatrix(Q31,numOfDctOutputs, numOfMelFilters)

Expand Down
3 changes: 3 additions & 0 deletions PythonWrapper_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ MEL filters are represented as 3 arrays to encode a sparse array.

# Change history

## Version 1.9.9:
* Supports Python 3.12

## Version 1.9.8:
* Compute graph API has been removed
* Dependency on numpy 1.22 has been lifted, tested through numpy 1.26
Expand Down
2 changes: 1 addition & 1 deletion cmsisdsp/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Python wrapper version
__version__ = "1.9.8"
__version__ = "1.9.9"
24 changes: 12 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#from distutils.core import setup, Extension
from setuptools import setup, Extension,find_packages
from distutils.util import convert_path
import io
import glob
import numpy
import sys
Expand All @@ -14,6 +14,15 @@
ROOT = here
ROOT=""

PYTHON_MOD = os.path.join(ROOT,"cmsisdsp")
version_path = os.path.join(PYTHON_MOD,"version.py")

__version__ = re.search(
r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', # It excludes inline comment too
io.open(version_path, encoding='utf_8_sig').read()
).group(1)


includes = [os.path.join(ROOT,"Include"),os.path.join(ROOT,"PrivateInclude"),os.path.join("PythonWrapper","cmsisdsp_pkg","src")]

if sys.platform == 'win32':
Expand Down Expand Up @@ -153,13 +162,8 @@ def build():
print('setup.py: Error: This package only supports Python 3.', file=sys.stderr)
sys.exit(1)

main_ns = {}
ver_path = convert_path(os.path.join("cmsisdsp","version.py"))
with open(ver_path) as ver_file:
exec(ver_file.read(), main_ns)

setup (name = 'cmsisdsp',
version = main_ns['__version__'],
version = __version__,
packages=["cmsisdsp"],
description = 'CMSIS-DSP Python API',
long_description=open("PythonWrapper_README.md").read(),
Expand All @@ -181,7 +185,7 @@ def build():
moduleWindow
],
include_package_data=True,
author = 'Copyright (C) 2010-2023 ARM Limited or its affiliates. All rights reserved.',
author = 'Copyright (C) 2010-2024 ARM Limited or its affiliates. All rights reserved.',
author_email = '[email protected]',
url="https://github.com/ARM-software/CMSIS-DSP",
python_requires='>=3.7',
Expand All @@ -202,10 +206,6 @@ def build():
keywords=['development','dsp','cmsis','cmsis-dsp','Arm','signal processing','maths','ml','cortex-m','cortex-a'],
install_requires=[
'numpy>=1.22',
'networkx>=3.0',
'jinja2>= 3.1.2, <4.0',
'sympy>=1.7.1',
'MarkupSafe>=2.1.2, <3.0'
],
project_urls={ # Optional
'Bug Reports': 'https://github.com/ARM-software/CMSIS-DSP/issues',
Expand Down

0 comments on commit b8db1e4

Please sign in to comment.