Python Forum
Element misalignment passing numpy array with distutils
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Element misalignment passing numpy array with distutils
#1
I have a 4D numpy array, surfaceVectors, where the 4th dimension is the unnormalized vector (size and direction) at each voxel of a 3D volume. I make a corresponding 3D volume, magnitudes, where each element is the norm of the vector at the corresponding element in surfaceVectors. I make magnitudes as follows.

    dimensions=filteredVolumes[0].shape
    numVoxels = int(len(surfaceVectors.reshape(-1))/3)
    temp=surfaceVectors.reshape(numVoxels, 3)
    temp2=np.array([np.linalg.norm(temp[item],axis=0) for item in range(0,numVoxels)])
    magnitudes = temp2.reshape(dimensions)
I then load a module, surfaceModules, which is a CInterface module, using

import surfaceModules as sm

y=sm.squeezeSurfaces(surfaceVectors, magnitudes)
squeezeSurfaces is a C function with the following form

static PyObject *  squeezeSurfaces(PyObject* self, PyObject* args)
{
	PyArrayObject *matin, *magmat, *matout;
	double ****cin, ****cout, ***cmag;
	int h,i,j,k,n,m,l,index=0, dims[4];

	// Parse tuples separately since args will differ between C fcns
	if (!PyArg_ParseTuple(args, "O!O!",
		&PyArray_Type, &matin, &PyArray_Type, &magmat))  return NULL;
	if (NULL == matin)  return NULL;

	// Check that object input is 'double' type and a matrix
	//   Not needed if python wrapper function checks before call to this routine
	if (not_doublematrix(matin)) return NULL;

	// Get the dimensions of the input
	m=dims[0]=matin->dimensions[0];
	n=dims[1]=matin->dimensions[1];
	l=dims[2]=matin->dimensions[2];
	dims[3]=matin->dimensions[3];

	// Make a new double matrix of same dims
	matout=(PyArrayObject *) PyArray_FromDims(4,dims,NPY_DOUBLE);

	// Change contiguous arrays into C ** arrays (Memory is Allocated!)
	cin=pymatrix_to_Carrayptrs(matin);
	cout=pymatrix_to_Carrayptrs(matout);

	// Do the calculation.
	for ( i=0; i<m; i++)  {
		for ( j=0; j<n; j++)  {
            for (k=0; k<l; ++k){
                if (magmat->data[index]>1){
                    // printf("f(%d,%d,%d) = %d\n",k,j,i,(int)(magmat->data[index]+0.5));
                    printf("f(%d,%d,%d) = %d, v=(%d,%d,%d)\n",k,j,i,(int)(magmat->data[index]+0.5),
                        (int)(cin[i][j][k][0]+0.5),
                        (int)(cin[i][j][k][1]+0.5),(int)(cin[i][j][k][2]+0.5));
                }
                ++index;
            }
	}  }

	// Free memory, close file and return
	free_Carrayptrs(cin, m, n, l);
	free_Carrayptrs(cout, m, n, l);

	return PyArray_Return(matout);
}
The output I get from

sm.squeezeSurfaces(surfaceVectors, magnitudes)
includes the following.

f(89,75,84) = 64, v=(115,118,-63)
f(4,76,84) = 98, v=(-40,-123,-110)
f(5,76,84) = 101, v=(-63,85,61)
f(7,76,84) = 64, v=(115,118,-63)
f(12,76,84) = 98, v=(-40,-123,-110)
f(13,76,84) = 101, v=(-63,85,61)
f(15,76,84) = 64, v=(115,118,-63)
f(18,76,84) = 96, v=(0,0,0)
f(23,76,84) = 64, v=(-63,111,64)
f(26,76,84) = 96, v=(86,-63,85)
f(30,76,84) = 113, v=(0,0,0)
f(31,76,84) = 64, v=(-63,111,64)
However, I get the following in Python

surfaceVectors[84][76][31]
Out[20]: array([0., 0., 0.])

magnitudes[84][76][31]
Out[21]: 0.0
So the values in the PyArrayObject arrays, in the C code, are not the same as the corresponding values in the corresponding numpy arrays in Python. Additionally, the norm values are not what would be expected given the 3D vectors from which they are derived.
Reply
#2
I thought I should post the whole C code.

#include <stdio.h>
#include <stdlib.h>
#include "/home/peter/anaconda3/include/python3.7m/Python.h"
#include "numpy/arrayobject.h"

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

int  not_doublematrix(PyArrayObject *mat);
double ****pymatrix_to_Carrayptrs(PyArrayObject *arrayin);
double **ptrvector(long n, long l);
double ****pptrvector(long n, long m, long l);
void free_Carrayptrs(double ****v, int m, int n, int l);

PyArrayObject * CsqueezeSurfaces(PyArrayObject **surfaceVectors, PyArrayObject **dimensions)
{
    printf("This function squeezes the surfaces");

    return *surfaceVectors;
}

/* ==== Allocate a double *vector (vec of pointers) ======================
    Memory is Allocated!  See void free_Carray(double ** )                  */
double **ptrvector(long n, long l)  {
    int i;
	double **v;
	if (!(v=(double **)malloc((size_t) (n*sizeof(double *))))){
		printf("In **ptrvector. Allocation of memory for double array failed.");
		return NULL;  }
    for (i=0; i<n; ++i){
        if (!(v[i]=(double *)malloc((size_t) (l*sizeof(double))))){
            for (--i; i>=0; --i) free(v[i]);
        }
        printf("In **ptrvector. Allocation of memory for double array failed.");
        free(v);
        return NULL;
    }
	return v;
}
double ****pptrvector(long n, long m, long l)  {
    int i, j, k;
	double ****v;
	if (!(v=(double ****)malloc((size_t) (n*sizeof(double ***)))))   {
		printf("In ***pptrvector. Allocation of memory for double array failed.");
		return NULL;
    }
	for (i=0; i<n; ++i){
        if (!(v[i]=(double ***)malloc((size_t) (m*sizeof(double **))))){
                for (--i; i>=0; --i){
                free(v[i]);
                }

            free(v);
            printf("In ***pptrvector. Allocation of memory for double array failed.");
            return NULL;
            }
            for (j=0; j<m; ++j){
                if (!(v[i][j]=(double **)malloc((size_t) (l*sizeof(double *))))){
                    for (--j; j>=0; --j) {
                        for (k=0; k<l; ++k) free(v[i][j][k]);
                        free(v[i][j]);
                    }
                    free(v[i]);
                    for (--i; i>=0; --i){
                        for (j=0; j<m; ++j) {
                            for (k=0; k<l; ++k) free(v[i][j][k]);
                            free(v[i][j]);
                        }
                        free(v[i]);
                    }
                    free(v);
                    printf("In ***pptrvector. Allocation of memory for double array failed.");
                    return NULL;
                }
                for (k=0; k<l; ++k){
                    if (!(v[i][j][k]=(double *)malloc((size_t) (3*sizeof(double))))){
                        for (--k; k>=0; --k) free(v[i][j][k]);
                        free(v[i][j]);
                        for (--j;j>=0; --j){
                            for (k=0; k<l; ++k) free(v[i][j][k]);
                            free(v[i][j]);
                        }
                        free(v[i]);
                        for (--i; i>=0; --i) {
                            for (j=0; j<m; ++j){
                                for (k=0; k<l; ++k) free(v[i][j][k]);
                                free(v[i][j]);
                                }
                            free(v[i]);
                        }
                        free(v);
                        printf("In ***pptrvector. Allocation of memory for double array failed.");
                        return NULL;
                }
            }
        }
    }

	return v;
}

/* ==== Free a double *vector (vec of pointers) ========================== */
//void free_Carrayptrs(double **v) {
//free((char*) v);
//}
void free_Carrayptrs(double ****v, int m, int n, int l) {
    int i, j, k;
    for (i=0; i<m; ++i){
        for (j=0; j<n; ++j){
            for (k=0; k<l; ++k){
                free(v[i][j][k]);
            }
            free(v[i][j]);
        }
        free(v[i]);
    }
    free((char*) v);
}

/* ==== Create Carray from PyArray ======================
    Assumes PyArray is contiguous in memory.
    Memory is allocated!                                    */
double ****pymatrix_to_Carrayptrs(PyArrayObject *arrayin)  {
	double ****d;
	int h,i,j,k,n,m,l, inc=0;

	n=arrayin->dimensions[0];
	m=arrayin->dimensions[1];
	l=arrayin->dimensions[2];
	d=pptrvector(n,m,l);
	for ( i=0; i<n; i++)  {
        for (j=0; j<m; ++j){
            for (h=0; h<l; ++h){
                for (k=0; k<3; ++k)  d[i][j][h][k]=arrayin->data[inc++];
           }
        }
    }

	return d;
}

/* ==== Check that PyArrayObject is a double (Float) type and a matrix ==============
    return 1 if an error and raise exception */
int  not_doublematrix(PyArrayObject *mat)  {
	if (mat->descr->type_num != NPY_DOUBLE || mat->nd != 4)  {
		PyErr_SetString(PyExc_ValueError,
			"In not_doublematrix: array must be of type Float and 4 dimensional (n x m).");
		return 1;  }
	return 0;
}

static PyObject *  squeezeSurfaces(PyObject* self, PyObject* args)
{
	PyArrayObject *matin, *magmat, *matout;
	double ****cin, ****cout, ***cmag;
	int h,i,j,k,n,m,l,index=0, dims[4];

	// Parse tuples separately since args will differ between C fcns
	if (!PyArg_ParseTuple(args, "O!O!",
		&PyArray_Type, &matin, &PyArray_Type, &magmat))  return NULL;
	if (NULL == matin)  return NULL;

	// Check that object input is 'double' type and a matrix
	//   Not needed if python wrapper function checks before call to this routine
	if (not_doublematrix(matin)) return NULL;

	// Get the dimensions of the input
	m=dims[0]=matin->dimensions[0];
	n=dims[1]=matin->dimensions[1];
	l=dims[2]=matin->dimensions[2];
	dims[3]=matin->dimensions[3];

	// Make a new double matrix of same dims
	matout=(PyArrayObject *) PyArray_FromDims(4,dims,NPY_DOUBLE);

	// Change contiguous arrays into C ** arrays (Memory is Allocated!)
	cin=pymatrix_to_Carrayptrs(matin);
	cout=pymatrix_to_Carrayptrs(matout);

	// Do the calculation.
	for ( i=0; i<m; i++)  {
		for ( j=0; j<n; j++)  {
            for (k=0; k<l; ++k){
                if (magmat->data[index]>1){
                    // printf("f(%d,%d,%d) = %d\n",k,j,i,(int)(magmat->data[index]+0.5));
                    printf("f(%d,%d,%d) = %d, v=(%d,%d,%d)\n",k,j,i,(int)(magmat->data[index]+0.5),
                        (int)(cin[i][j][k][0]+0.5),
                        (int)(cin[i][j][k][1]+0.5),(int)(cin[i][j][k][2]+0.5));
                }
                ++index;
//                for (h=0; h<3; ++h)
//                    cout[i][j][k][h]= 1.0/h;
            }
	}  }

	// Free memory, close file and return
	free_Carrayptrs(cin, m, n, l);
	free_Carrayptrs(cout, m, n, l);

	return PyArray_Return(matout);

//	Py_INCREF(matin);
//	return PyArray_Return(matin);
}

int CmergeDirectionalVolumes(PyArrayObject *directions[3], int dimensions[3], PyArrayObject ***filteredVolumes,
    PyArrayObject ***strongest, PyArrayObject ***secondStrongest, PyArrayObject ****mergedMagnitudes, PyArrayObject ****mergedDirections)
{
    printf("This function merges 3D directional volumes");

    return 1;
}

static PyObject* mergeDirectionalVolumes(PyObject* self, PyObject* args)
{
    int dimensions[3];
    PyArrayObject *directions[3], ***filteredVolumes=NULL, ***strongest=NULL, ***secondStrongest=NULL;
    PyArrayObject   ****mergedMagnitudes=NULL, ****mergedDirections=NULL;

    if (!PyArg_ParseTuple(args, "i", directions, dimensions, filteredVolumes, strongest, secondStrongest,
            mergedMagnitudes, mergedDirections))
        return NULL;

        return Py_BuildValue("i", CmergeDirectionalVolumes(directions, dimensions, filteredVolumes, strongest,
            secondStrongest, mergedMagnitudes, mergedDirections));
}

static PyObject* version(PyObject* self){
    return Py_BuildValue("s", "Version 1.0");
}

static PyMethodDef surfaceMethods[] = {
    {"mergeDirectionalVolumes", mergeDirectionalVolumes, METH_VARARGS, "Merges directional volumes"},
    {"squeezeSurfaces", squeezeSurfaces, METH_VARARGS, "Squeezes surfaces along normal vectors"},
    {"version", (PyCFunction)version, METH_NOARGS, "Returns the version"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef surfaceModules = {
    PyModuleDef_HEAD_INIT,
    "surfaceModules",
    "Surface function Module",
    -1,
    surfaceMethods
};

PyMODINIT_FUNC PyInit_surfaceModules(void){
    import_array();
    return PyModule_Create(&surfaceModules);
}
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Elegant way to apply each element of an array to a dataframe? sawtooth500 7 387 Mar-29-2024, 05:51 PM
Last Post: deanhystad
  Convert numpy array to image without loading it into RAM. DreamingInsanity 7 5,867 Feb-08-2024, 09:38 AM
Last Post: paul18fr
  IPython errors for numpy array min/max methods muelaner 1 554 Nov-04-2023, 09:22 PM
Last Post: snippsat
  Expand the range of a NumPy array? PythonNPC 0 746 Jan-31-2023, 02:41 AM
Last Post: PythonNPC
  Change a numpy array to a dataframe Led_Zeppelin 3 1,106 Jan-26-2023, 09:01 PM
Last Post: deanhystad
  from numpy array to csv - rounding SchroedingersLion 6 2,160 Nov-14-2022, 09:09 PM
Last Post: deanhystad
  numpy.array has no attribute head Led_Zeppelin 1 1,228 Jul-13-2022, 12:56 AM
Last Post: Led_Zeppelin
  Seeing al the data in a dataframe or numpy.array Led_Zeppelin 1 1,139 Jul-11-2022, 08:54 PM
Last Post: Larz60+
  Passing parameters with arrays and array definitions michael_lwt 1 936 Jul-07-2022, 09:45 PM
Last Post: Larz60+
  go over and search in numpy array faster caro 7 1,739 Jun-20-2022, 04:54 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020