Skip to content

Update to NumPy 2 C-API #1472

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject-tensorflow.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess

[tool.cibuildwheel.macos]

skip = ["pp*"]
skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"]

environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 }

Expand All @@ -45,7 +45,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess
[[tool.cibuildwheel.overrides]]
select = "*macosx_arm64*"

skip = ["pp*"]
skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"]

environment = { PROJECT_NAME="essentia-tensorflow", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1 }

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess

[tool.cibuildwheel.macos]

skip = ["pp*"]
skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"]

environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1 }

Expand All @@ -42,7 +42,7 @@ test-command = "python -c 'import essentia; import essentia.standard; import ess
[[tool.cibuildwheel.overrides]]
select = "*macosx_arm64*"

skip = ["pp*"]
skip = ["pp*", "*cp36*", "*cp37*", "*cp38*"]

environment = { PROJECT_NAME="essentia", ESSENTIA_PROJECT_NAME="${PROJECT_NAME}", ESSENTIA_WHEEL_SKIP_3RDPARTY=1, ESSENTIA_WHEEL_ONLY_PYTHON=1, ESSENTIA_MACOSX_ARM64=1 }

Expand Down
42 changes: 23 additions & 19 deletions src/python/globalfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,12 @@ derivative(PyObject* self, PyObject* arg) {
static double
internal_instant_power(PyObject* obj) {
double p = 0;
for (int i=0; i<PyArray_SIZE(obj); i++) {
double x = ((float*)PyArray_DATA(obj))[i];
PyArrayObject* array = (PyArrayObject*)obj;
for (int i=0; i<PyArray_SIZE(array); i++) {
double x = ((float*)PyArray_DATA(array))[i];
p += x * x;
}
p /= PyArray_SIZE(obj);
p /= PyArray_SIZE(array);
return p;
}

Expand Down Expand Up @@ -1034,29 +1035,32 @@ static PyObject* almostEqualArray(PyObject* notUsed, PyObject* args) {

if (argv.size() != 3 ||
!PyArray_Check(argv[0]) || !PyArray_Check(argv[1]) ||
PyArray_TYPE(argv[0]) != PyArray_TYPE(argv[1]) ||
PyArray_TYPE(argv[0]) != NPY_FLOAT ||
PyArray_TYPE((const PyArrayObject *) argv[0]) != PyArray_TYPE((const PyArrayObject *) argv[1]) ||
PyArray_TYPE((const PyArrayObject *) argv[0]) != NPY_FLOAT ||
!PyFloat_Check(argv[2])) {
PyErr_SetString(PyExc_TypeError, "expecting arguments (numpy.array(floats) m1, numpy.array(floats) m2, float precision)");
return NULL;
}

if (PyArray_NDIM(argv[0]) != PyArray_NDIM(argv[1])) Py_RETURN_FALSE;
PyArrayObject* array0 = (PyArrayObject*) argv[0];
PyArrayObject* array1 = (PyArrayObject*) argv[1];

if (PyArray_NDIM(argv[0]) > 2) {
if (PyArray_NDIM(array0) != PyArray_NDIM(array1)) Py_RETURN_FALSE;

if (PyArray_NDIM(array0) > 2) {
PyErr_SetString(PyExc_TypeError, "comparing numpy arrays of more than 2 dimensions not implemented");
return NULL;
}

float precision = PyFloat_AS_DOUBLE(argv[2]);

// 1-dimensional arrays
if (PyArray_NDIM(argv[0]) == 1) {
if (PyArray_DIM(argv[0], 0) != PyArray_DIM(argv[1], 0)) Py_RETURN_FALSE;
if (PyArray_NDIM(array0) == 1) {
if (PyArray_DIM(array0, 0) != PyArray_DIM(array1, 0)) Py_RETURN_FALSE;

for (int i=0; i<int(PyArray_DIM(argv[0], 0)); ++i) {
Real* x = (Real*)(PyArray_BYTES(argv[0]) + i*PyArray_STRIDE(argv[0], 0));
Real* y = (Real*)(PyArray_BYTES(argv[1]) + i*PyArray_STRIDE(argv[1], 0));
for (int i=0; i<int(PyArray_DIM(array0, 0)); ++i) {
Real* x = (Real*)(PyArray_BYTES(array0) + i*PyArray_STRIDE(array0, 0));
Real* y = (Real*)(PyArray_BYTES(array1) + i*PyArray_STRIDE(array1, 0));
Real diff = 0;
if (*y == 0) diff = abs(*x);
else if (*x == 0) diff = abs(*y);
Expand All @@ -1071,16 +1075,16 @@ static PyObject* almostEqualArray(PyObject* notUsed, PyObject* args) {
}

// 2-dimensional arrays
else if (PyArray_NDIM(argv[0]) == 2) {
if (PyArray_DIM(argv[0], 0) != PyArray_DIM(argv[1], 0) ||
PyArray_DIM(argv[0], 1) != PyArray_DIM(argv[1], 1)) {
else if (PyArray_NDIM(array0) == 2) {
if (PyArray_DIM(array0, 0) != PyArray_DIM(array1, 0) ||
PyArray_DIM(array0, 1) != PyArray_DIM(array1, 1)) {
Py_RETURN_FALSE;
}

for (int i=0; i<int(PyArray_DIM(argv[0], 0)); ++i) {
for (int j=0; j<int(PyArray_DIM(argv[0], 1)); ++j) {
Real* x = (Real*)(PyArray_BYTES(argv[0]) + i*PyArray_STRIDE(argv[0], 0) + j*PyArray_STRIDE(argv[0], 1));
Real* y = (Real*)(PyArray_BYTES(argv[1]) + i*PyArray_STRIDE(argv[1], 0) + j*PyArray_STRIDE(argv[1], 1));
for (int i=0; i<int(PyArray_DIM(array0, 0)); ++i) {
for (int j=0; j<int(PyArray_DIM(array0, 1)); ++j) {
Real* x = (Real*)(PyArray_BYTES(array0) + i*PyArray_STRIDE(array0, 0) + j*PyArray_STRIDE(array0, 1));
Real* y = (Real*)(PyArray_BYTES(array1) + i*PyArray_STRIDE(array1, 0) + j*PyArray_STRIDE(array1, 1));
Real diff = 0;
if (*y == 0) diff = abs(*x);
else if (*x == 0) diff = abs(*y);
Expand Down
13 changes: 8 additions & 5 deletions src/python/pytypes/matrixreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ PyObject* MatrixReal::toPythonRef(TNT::Array2D<Real>* mat) {

PyObject* result;
if (dims[0] == 0 || dims[1] == 0) {
result = PyArray_SimpleNew(2, dims, PyArray_FLOAT);
result = PyArray_SimpleNew(2, dims, NPY_FLOAT);
}
else {
result = PyArray_SimpleNewFromData(2, dims, PyArray_FLOAT, &((*mat)[0][0]));
result = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &((*mat)[0][0]));
}

if (result == NULL) {
throw EssentiaException("MatrixReal: dang null object");
}

PyArray_BASE(result) = TO_PYTHON_PROXY(MatrixReal, mat);
if (PyArray_SetBaseObject((PyArrayObject*)result, TO_PYTHON_PROXY(MatrixReal, mat)) < 0) {
Py_DECREF(result);
throw EssentiaException("MatrixReal: failed to set base object");
}

return result;
}
Expand All @@ -65,11 +68,11 @@ void* MatrixReal::fromPythonCopy(PyObject* obj) {
if (!PyArray_Check(obj)) {
throw EssentiaException("MatrixReal::fromPythonRef: argument not a PyArray");
}
if (PyArray_NDIM(obj) != 2) {
if (PyArray_NDIM((const PyArrayObject *) obj) != 2) {
throw EssentiaException("MatrixReal::fromPythonRef: argument is not a 2-dimensional PyArray");
}

TNT::Array2D<Real>* tntmat = new TNT::Array2D<Real>(PyArray_DIM(obj, 0), PyArray_DIM(obj, 1), 0.0);
TNT::Array2D<Real>* tntmat = new TNT::Array2D<Real>(PyArray_DIM((const PyArrayObject *) obj, 0), PyArray_DIM((const PyArrayObject *) obj, 1), 0.0);

// copy data from numpy array to matrix
PyArrayObject* numpyarr = (PyArrayObject*)obj;
Expand Down
14 changes: 7 additions & 7 deletions src/python/pytypes/tensorreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ PyObject* TensorReal::toPythonCopy(const essentia::Tensor<essentia::Real>* tenso
for (int i = 0; i < nd; i++)
dims[i] = tensor->dimension(i);

result = PyArray_SimpleNew(nd, dims, PyArray_FLOAT);
result = PyArray_SimpleNew(nd, dims, NPY_FLOAT);

Real* dest = (Real*)(((PyArrayObject*)result)->data);
const Real* src = tensor->data();
Expand All @@ -55,19 +55,19 @@ void* TensorReal::fromPythonCopy(PyObject* obj) {
if (!PyArray_Check(obj)) {
throw EssentiaException("TensorReal::fromPythonRef: expected PyArray, received: ", strtype(obj));
}
if (PyArray_NDIM(obj) != TENSORRANK) {
if (PyArray_NDIM((const PyArrayObject *) obj) != TENSORRANK) {
throw EssentiaException("TensorReal::fromPythonCopy: argument is not a 4-dimensional PyArray");
}

// // copy data from numpy array to matrix
PyArrayObject* numpyarr = (PyArrayObject*)obj;
if (numpyarr->descr->type_num != PyArray_FLOAT) {
if (numpyarr->descr->type_num != NPY_FLOAT) {
throw EssentiaException("TensorReal::fromPythonRef: this NumPy array doesn't contain Reals (maybe you forgot dtype='f4')");
}

return new Tensor<Real>(TensorMap<Real>((Real *)PyArray_DATA(numpyarr),
PyArray_DIM(obj, 0),
PyArray_DIM(obj, 1),
PyArray_DIM(obj, 2),
PyArray_DIM(obj, 3)));
PyArray_DIM(numpyarr, 0),
PyArray_DIM(numpyarr, 1),
PyArray_DIM(numpyarr, 2),
PyArray_DIM(numpyarr, 3)));
}
15 changes: 9 additions & 6 deletions src/python/pytypes/vectorcomplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,19 @@ PyObject* VectorComplex::toPythonRef(RogueVector<complex<Real> >* v) {
npy_intp dim = v->size();
PyObject* result;

if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, PyArray_COMPLEX64, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, PyArray_COMPLEX64);
if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, NPY_COMPLEX64, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, NPY_COMPLEX64);

if (result == NULL) {
throw EssentiaException("VectorComplex::toPythonRef: could not create PyArray of type PyArray_COMPLEX64");
throw EssentiaException("VectorComplex::toPythonRef: could not create PyArray of type NPY_COMPLEX64");
}

// set the PyArray pointer to our vector, so it can be released when the
// PyArray is released
PyArray_BASE(result) = TO_PYTHON_PROXY(VectorComplex, v);
if (PyArray_SetBaseObject((PyArrayObject*)result, TO_PYTHON_PROXY(VectorComplex, v)) < 0) {
Py_DECREF(result);
throw EssentiaException("VectorComplex: failed to set base object");
}

return result;
}
Expand All @@ -50,12 +53,12 @@ void* VectorComplex::fromPythonRef(PyObject* obj) {

PyArrayObject* array = (PyArrayObject*)obj;

if (array->descr->type_num != PyArray_CFLOAT) {
if (array->descr->type_num != NPY_CFLOAT) {
throw EssentiaException("VectorComplex::fromPythonRef: this NumPy array doesn't contain complex<Real> (maybe you forgot dtype='c8')");
}
if (array->nd != 1) {
throw EssentiaException("VectorComplex::fromPythonRef: this NumPy array has dimension ", array->nd, " (expected 1)");
}

return new RogueVector<complex<Real> >((complex<Real>*)PyArray_DATA(obj), PyArray_SIZE(obj));
return new RogueVector<complex<Real> >((complex<Real>*)PyArray_DATA(array), PyArray_SIZE(array));
}
15 changes: 9 additions & 6 deletions src/python/pytypes/vectorinteger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ PyObject* VectorInteger::toPythonRef(RogueVector<int>* v) {
npy_intp dim = v->size();
PyObject* result;

if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, PyArray_INT, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, PyArray_INT);
if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, NPY_INT, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, NPY_INT);

if (result == NULL) {
throw EssentiaException("VectorInteger::toPythonRef: could not create PyArray of type PyArray_INT");
throw EssentiaException("VectorInteger::toPythonRef: could not create PyArray of type NPY_INT");
}

PyArray_BASE(result) = TO_PYTHON_PROXY(VectorInteger, v);
if (PyArray_SetBaseObject((PyArrayObject*)result, TO_PYTHON_PROXY(VectorInteger, v)) < 0) {
Py_DECREF(result);
throw EssentiaException("VectorInteger: failed to set base object");
}

return result;
}
Expand All @@ -48,14 +51,14 @@ void* VectorInteger::fromPythonRef(PyObject* obj) {

PyArrayObject* array = (PyArrayObject*)obj;

if (array->descr->type_num != PyArray_INT32) {
if (array->descr->type_num != NPY_INT32) {
throw EssentiaException("VectorInteger::fromPythonRef: this NumPy array doesn't contain ints (maybe you forgot dtype='int'), type code: ", array->descr->type_num);
}
if (array->nd != 1) {
throw EssentiaException("VectorInteger::fromPythonRef: this NumPy array has dimension ", array->nd, " (expected 1)");
}

return new RogueVector<int>((int*)PyArray_DATA(obj), PyArray_SIZE(obj));
return new RogueVector<int>((int*)PyArray_DATA(array), PyArray_SIZE(array));
}

Parameter* VectorInteger::toParameter(PyObject* obj) {
Expand Down
2 changes: 1 addition & 1 deletion src/python/pytypes/vectormatrixreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ PyObject* VectorMatrixReal::toPythonCopy(const vector<TNT::Array2D<Real> >* matV
dims[0] = (*matVec)[i].dim1();
dims[1] = (*matVec)[i].dim2();

PyArrayObject* mat = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_FLOAT);
PyArrayObject* mat = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_FLOAT);

if (mat == NULL) {
throw EssentiaException("VectorMatrixReal::toPythonCopy: dang null object");
Expand Down
13 changes: 8 additions & 5 deletions src/python/pytypes/vectorreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ PyObject* VectorReal::toPythonRef(RogueVector<Real>* v) {
npy_intp dim = v->size();
PyObject* result;

if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, PyArray_FLOAT, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, PyArray_FLOAT);
if (dim > 0) result = PyArray_SimpleNewFromData(1, &dim, NPY_FLOAT, &((*v)[0]));
else result = PyArray_SimpleNew(1, &dim, NPY_FLOAT);

if (result == NULL) {
throw EssentiaException("VectorReal: dang null object");
}

PyArray_BASE(result) = TO_PYTHON_PROXY(VectorReal, v);
if (PyArray_SetBaseObject((PyArrayObject*)result, TO_PYTHON_PROXY(VectorReal, v)) < 0) {
Py_DECREF(result);
throw EssentiaException("VectorReal: failed to set base object");
}

return result;
}
Expand All @@ -48,14 +51,14 @@ void* VectorReal::fromPythonRef(PyObject* obj) {

PyArrayObject* array = (PyArrayObject*)obj;

if (array->descr->type_num != PyArray_FLOAT) {
if (array->descr->type_num != NPY_FLOAT) {
throw EssentiaException("VectorReal::fromPythonRef: this NumPy array doesn't contain Reals (maybe you forgot dtype='f4')");
}
if (array->nd != 1) {
throw EssentiaException("VectorReal::fromPythonRef: this NumPy array has dimension ", array->nd, " (expected 1)");
}

return new RogueVector<Real>((Real*)PyArray_DATA(obj), PyArray_SIZE(obj));
return new RogueVector<Real>((Real*)PyArray_DATA(array), PyArray_SIZE(array));
}

Parameter* VectorReal::toParameter(PyObject* obj) {
Expand Down
13 changes: 7 additions & 6 deletions src/python/pytypes/vectorstereosample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,19 @@ void* VectorStereoSample::fromPythonCopy(PyObject* obj) {
"is not a numpy array: ", strtype(obj));
}

if (PyArray_NDIM(obj) != 2) {
PyArrayObject* arr = (PyArrayObject*)obj;

if (PyArray_NDIM(arr) != 2) {
throw EssentiaException("VectorStereoSample::fromPythonCopy: given input "
"is not a 2-dimensional numpy array: ", PyArray_NDIM(obj));
"is not a 2-dimensional numpy array: ", PyArray_NDIM(arr));
}

if (PyArray_DIM(obj, 1) != 2) {
if (PyArray_DIM(arr, 1) != 2) {
throw EssentiaException("VectorStereoSample::fromPythonCopy: given input's "
"second dimension is not 2: ", PyArray_DIM(obj, 1));
"second dimension is not 2: ", PyArray_DIM(arr, 1));
}

Py_ssize_t total = PyArray_DIM(obj, 0);
PyArrayObject* arr = (PyArrayObject*)obj;
Py_ssize_t total = PyArray_DIM(arr, 0);
vector<StereoSample>* result = new vector<StereoSample>(total);

for (int i=0; i<int(total); ++i) {
Expand Down
2 changes: 1 addition & 1 deletion src/python/pytypes/vectortensorreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ PyObject* VectorTensorReal::toPythonCopy(const vector<Tensor<Real> >* tenVec) {
for (int j = 0; j< nd; j++)
dims[j] = tensor.dimension(j);

PyArrayObject* numpyarr = (PyArrayObject*)PyArray_SimpleNew(nd, dims, PyArray_FLOAT);
PyArrayObject* numpyarr = (PyArrayObject*)PyArray_SimpleNew(nd, dims, NPY_FLOAT);

if (numpyarr == NULL) {
throw EssentiaException("VectorTensorReal::toPythonCopy: dang null object");
Expand Down
2 changes: 1 addition & 1 deletion src/python/pytypes/vectorvectorcomplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ PyObject* VectorVectorComplex::toPythonCopy(const vector<vector<complex<Real> >
if (isRectangular && dims[0] > 0 && dims[1] > 0) {
PyArrayObject* result;

result = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_COMPLEX64);
result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_COMPLEX64);
assert(result->strides[1] == sizeof(complex<Real>));

if (result == NULL) {
Expand Down
13 changes: 7 additions & 6 deletions src/python/pytypes/vectorvectorreal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ PyObject* VectorVectorReal::toPythonCopy(const vector<vector<Real> >* v) {
if (isRectangular && dims[0] > 0 && dims[1] > 0) {
PyArrayObject* result;

result = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_FLOAT);
result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_FLOAT);
assert(result->strides[1] == sizeof(Real));

if (result == NULL) {
Expand All @@ -61,7 +61,7 @@ PyObject* VectorVectorReal::toPythonCopy(const vector<vector<Real> >* v) {

for (int i=0; i<(int)v->size(); ++i) {
npy_intp itemDims[1] = {(int)(*v)[i].size()};
PyArrayObject* item = (PyArrayObject*)PyArray_SimpleNew(1, itemDims, PyArray_FLOAT);
PyArrayObject* item = (PyArrayObject*)PyArray_SimpleNew(1, itemDims, NPY_FLOAT);
assert(item->strides[0] == sizeof(Real));
if (item == NULL) {
throw EssentiaException("VectorVectorReal: dang null object (list of numpy arrays)");
Expand Down Expand Up @@ -116,15 +116,16 @@ void* VectorVectorReal::fromPythonCopy(PyObject* obj) {

// Numpy array of floats
else if (PyArray_Check(row)) {
if (PyArray_NDIM(row) != 1) {
PyArrayObject* array = (PyArrayObject*)row;
if (PyArray_NDIM(array) != 1) {
throw EssentiaException("VectorVectorReal::fromPythonCopy: the element of input list "
"is not a 1-dimensional numpy array: ", PyArray_NDIM(row));
"is not a 1-dimensional numpy array: ", PyArray_NDIM(array));
}
PyArrayObject* array = (PyArrayObject*)row;

if (array == NULL) {
throw EssentiaException("VectorVectorReal::fromPythonCopy: dang null object (list of numpy arrays)");
}
if (array->descr->type_num != PyArray_FLOAT) {
if (array->descr->type_num != NPY_FLOAT) {
throw EssentiaException("VectorVectorReal::fromPythonCopy: this NumPy array doesn't contain Reals (maybe you forgot dtype='f4')");
}
assert(array->strides[0] == sizeof(Real));
Expand Down
Loading
Loading