Mercurial > hg > vampy
diff PyTypeInterface.cpp @ 32:a8231788216c vampy2
Vampy2: accept numpy array return types.
author | fazekasgy |
---|---|
date | Mon, 21 Sep 2009 13:56:28 +0000 |
parents | 4f1894c7591b |
children | c4da8d559872 |
line wrap: on
line diff
--- a/PyTypeInterface.cpp Sun Sep 20 17:31:20 2009 +0000 +++ b/PyTypeInterface.cpp Mon Sep 21 13:56:28 2009 +0000 @@ -2,6 +2,9 @@ */ #include <Python.h> +#ifdef HAVE_NUMPY +#include "arrayobject.h" +#endif #include "PyTypeInterface.h" #include "PyRealTime.h" #include "PyExtensionModule.h" @@ -25,7 +28,7 @@ static bool isMapInitialised = false; /* Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS - (EXCEPT FOR TEMPORARY PYOBJECTS)! */ + (EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */ PyTypeInterface::PyTypeInterface() : m_strict(false), @@ -405,29 +408,51 @@ return Output; } -//convert Python list to C++ vector of floats +//convert PyFeature.value (typically a list or numpy array) to C++ vector of floats std::vector<float> -PyTypeInterface::PyValue_To_FloatVector (PyObject *inputList) const +PyTypeInterface::PyValue_To_FloatVector (PyObject *pyValue) const { - typedef std::vector<float> floatVector; std::vector<float> Output; + +#ifdef HAVE_NUMPY + /// Check for NumPy Array: this requires linking with numpy + /// but, we don't really need this macro + // if (PyArray_CheckExact(inputList)) cerr << "PyPyArray_CheckExact OK" << endl; - /// Check for NumPy Array - if (PyObject_HasAttrString(inputList,"__array_struct__")) { - int vectorLength; - float *dataptr = getNumPyObjectData(inputList,vectorLength); - if (dataptr != 0) cerr << "Numpy array found: " << vectorLength << endl; - // Output = *dataptr; + /// numpy array + if (PyObject_HasAttrString(pyValue,"__array_struct__")) { + return PyArray_To_FloatVector(pyValue); } +#endif + + /// python list + if (PyList_Check(pyValue)) { + return PyList_To_FloatVector(pyValue); + } + + /// assume a single number + /// this allows to write e.g. Feature.values = 5 instead of [5.00] + Output.push_back(PyValue_To_Float(pyValue)); + return Output; + + /// TODO : set error + +} + +//convert a list of python floats +std::vector<float> +PyTypeInterface::PyList_To_FloatVector (PyObject *inputList) const +{ + std::vector<float> Output; float ListElement; PyObject *pyFloat = NULL; if (!PyList_Check(inputList)) return Output; - for (Py_ssize_t k = 0; k < PyList_GET_SIZE(inputList); ++k) { + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) { //Get next list item (Borrowed Reference) - pyFloat = PyList_GET_ITEM(inputList,k); + pyFloat = PyList_GET_ITEM(inputList,i); ListElement = (float) PyFloat_AS_DOUBLE(pyFloat); #ifdef _DEBUG cerr << "value: " << ListElement << endl; @@ -438,6 +463,50 @@ return Output; } +#ifdef HAVE_NUMPY +std::vector<float> +PyTypeInterface::PyArray_To_FloatVector (PyObject *pyValue) const +{ + std::vector<float> Output; + + /// we don't verify the array here as it'd be duplicated mostly + // if (!PyObject_HasAttrString(pyValue,"__array_struct__")) { + // return Output; + // } + + PyArrayObject* pyArray = (PyArrayObject*) pyValue; + PyArray_Descr* descr = pyArray->descr; + + /// check raw data pointer + if (pyArray->data == 0) return Output; + + /// check dimensions + if (pyArray->nd != 1) { + cerr << "Error: array must be 1D" << endl; + return Output; + } + +#ifdef _DEBUG + cerr << "Numpy array verified." << endl; +#endif + + switch (descr->type_num) + { + case NPY_FLOAT : + return PyArray_Convert<float,float>(pyArray->data,pyArray->dimensions[0]); + case NPY_DOUBLE : + return PyArray_Convert<float,double>(pyArray->data,pyArray->dimensions[0]); + case NPY_INT : + return PyArray_Convert<float,int>(pyArray->data,pyArray->dimensions[0]); + case NPY_LONG : + return PyArray_Convert<float,long>(pyArray->data,pyArray->dimensions[0]); + + default : + cerr << "Error. Unsupported element type in NumPy array object." << endl; + return Output; + } +} +#endif /* Vamp API Specific Types @@ -580,7 +649,7 @@ Vamp::Plugin::FeatureSet PyTypeInterface::PyValue_To_FeatureSet(PyObject* pyValue) const { - Vamp::Plugin::FeatureSet rFeatureSet; /// PyFeatureSet is an int map + Vamp::Plugin::FeatureSet rFeatureSet; /// map<int> if (pyValue == NULL) { cerr << "NULL FeatureSet" << endl; return rFeatureSet; @@ -893,77 +962,6 @@ /* Utilities */ -//return a pointer to the data in the numPy array -float* -PyTypeInterface::getNumPyObjectData(PyObject *object, int &length) const -{ - - char attr_name[]="__array_struct__"; - - //check if we passed in a NumPy array object - if (!PyObject_HasAttrString(object,attr_name)) { - // PyErr_SetString(PyExc_TypeError, - // "Input object has no __array_struct__ attribute. NumPy array required."); - return NULL; - } - - //retrieve __array_struct__ interface - object = PyObject_GetAttrString(object,attr_name); - - //check whether we found CObjects - if (!PyCObject_Check(object)) { - PyErr_SetString(PyExc_TypeError, - "The passed __array_struct__ interface is not a valid C Object."); - return NULL; - } - - - //check if the pointers directed to the integer '2' - int *check = (int *) PyCObject_AsVoidPtr (object); - - if (*check != 2 ) { - PyErr_SetString(PyExc_TypeError, - "A C Object __array_struct__ required as inputs"); - return NULL; - } - - //convert CObjects to Array interfaces - PyArrayInterface *arrayInterface = - (PyArrayInterface *) PyCObject_AsVoidPtr (object); - - //check array dimension: should be 1 - int inputDim = arrayInterface->nd; - - if (inputDim > 1 ) { - PyErr_SetString(PyExc_TypeError, - "Array dimensions must not exceed one."); - return NULL; - } - - // check if vector size is sane - Py_intptr_t arrayLength = arrayInterface->shape[0]; - length = (int) arrayLength; - - // if (arrayLength < 8 || arrayLength > 65536 ) { - // PyErr_SetString(PyExc_TypeError, - // "Array length is out of bounds."); - // return NULL; - // } - - //check type; must be float32 - char arrayType = arrayInterface->typekind; - - if (arrayType != 'f' ) { - PyErr_SetString(PyExc_TypeError, - "Floating point arrays required."); - return NULL; - } - - //return data vector address - return (float*) arrayInterface->data; - -} - /// get the type name of an object std::string PyTypeInterface::PyValue_Get_TypeName(PyObject* pyValue) const