Add experimental Python bindings
This commit adds some experimental Python bindings. These likely need some further refinement in the building/deployment area, but should serve as a useful testbed for experimentation and interactive analysis of filters and the library's behaviour.
This commit is contained in:
parent
911b3eab3d
commit
5681c97b4e
|
@ -0,0 +1,5 @@
|
|||
.ipynb_checkpoints/
|
||||
__pycache__/
|
||||
build/
|
||||
iir.py
|
||||
pyiir_wrap.cxx
|
|
@ -0,0 +1,25 @@
|
|||
Experimental Python bindings
|
||||
============================
|
||||
|
||||
These bindings are currently experimental, as it is not yet clear how best
|
||||
to create and maintain them. They are built upon the C++ interface as the
|
||||
object oriented nature of it sits much better with Python.
|
||||
|
||||
At present, it is necessary to compile and install the C++ library before
|
||||
working with the bindings.
|
||||
|
||||
To generate the bindings, swig 3.0.2 has been used, but earlier versions
|
||||
may work too:
|
||||
|
||||
swig -c++ -python -py3 pyiir.i
|
||||
|
||||
To build the extension, distutils is used:
|
||||
|
||||
python3 setup.py build_ext
|
||||
|
||||
Note that the -L ${LIBDIR} option may be handy if libiir++ is not installed
|
||||
into the system library path.
|
||||
|
||||
To install the extension:
|
||||
|
||||
python3 setup.py install
|
|
@ -0,0 +1 @@
|
|||
../obj/iir++.h
|
|
@ -0,0 +1,130 @@
|
|||
%module iir
|
||||
%include <complex.i>
|
||||
|
||||
%{
|
||||
#include "iir++.h"
|
||||
%}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Add bounds checking
|
||||
*
|
||||
* The Python library is targetted at experimentation. It is therefore
|
||||
* reasonable to protect its object query and creation interfaces with code
|
||||
* that performs bounds checking on arguments.
|
||||
*/
|
||||
%exception IIR::Coeff::c {
|
||||
if(arg2 < 0 || arg2 >= arg1->nc()) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Index of c coefficient (%d) out of bounds "
|
||||
"(0,%d).", arg2, arg1->nc() - 1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::Coeff::d {
|
||||
if(arg2 < 0 || arg2 >= arg1->nd()) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Index of d coefficient (%d) out of bounds "
|
||||
"(0,%d).", arg2, arg1->nd() - 1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::Filter::getCoeffSet {
|
||||
if(arg2 < 0 || arg2 >= arg1->numCoeffSet()) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Index of coefficient set (%d) out of bounds "
|
||||
"(0,%d).", arg2, arg1->numCoeffSet() - 1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::ButterworthLowPass {
|
||||
if(arg1 < 1) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
|
||||
arg1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::ButterworthHighPass {
|
||||
if(arg1 < 1) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
|
||||
arg1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::ButterworthBandPass {
|
||||
if(arg1 < 1) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
|
||||
arg1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
if(arg3 > arg4) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Low corner frequency exceeds "
|
||||
"high corner frequency.");
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
%exception IIR::ButterworthBandStop {
|
||||
if(arg1 < 1) {
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
|
||||
arg1);
|
||||
PyErr_SetString(PyExc_RuntimeError, buf);
|
||||
return NULL;
|
||||
}
|
||||
if(arg3 > arg4) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Low corner frequency exceeds "
|
||||
"high corner frequency.");
|
||||
return NULL;
|
||||
}
|
||||
$action
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Invalid filter string handling
|
||||
*
|
||||
* The C++ library uses a "valid()" member in IIR::Filter to avoid throwing an
|
||||
* exception if the constructor is passed an invalid filter string. Python's
|
||||
* exceptions are a much nicer fit, however, so use those instead.
|
||||
*
|
||||
* Notes:
|
||||
* 1. Doesn't match if we prepend it with the namespace.
|
||||
* 2. Applies to all constructors.
|
||||
*/
|
||||
%exception Filter {
|
||||
$action
|
||||
if(!result->valid()) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Invalid filter description string.");
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
%include "iir++.h"
|
||||
|
||||
// vim: ts=4:sw=4
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
iir_module = Extension('_iir',
|
||||
sources=['pyiir_wrap.cxx'],
|
||||
libraries=['iir++'],
|
||||
)
|
||||
|
||||
setup(name = 'iir',
|
||||
version = '1.0.3',
|
||||
author = 'Laurence Withers',
|
||||
description = 'IIR filter',
|
||||
ext_modules = [iir_module],
|
||||
py_modules = ['iir'],
|
||||
)
|
Loading…
Reference in New Issue