static PyObject * QUATERNION_getitem(char *ip, PyArrayObject *ap) { quaternion q; PyObject *tuple; if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) { q = *((quaternion *)ip); } else { PyArray_Descr *descr; descr = PyArray_DescrFromType(NPY_DOUBLE); descr->f->copyswap(&q.w, ip, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.x, ip+8, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.y, ip+16, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.z, ip+24, !PyArray_ISNOTSWAPPED(ap), NULL); Py_DECREF(descr); } tuple = PyTuple_New(4); PyTuple_SET_ITEM(tuple, 0, PyFloat_FromDouble(q.w)); PyTuple_SET_ITEM(tuple, 1, PyFloat_FromDouble(q.x)); PyTuple_SET_ITEM(tuple, 2, PyFloat_FromDouble(q.y)); PyTuple_SET_ITEM(tuple, 3, PyFloat_FromDouble(q.z)); return tuple; }
/*NUMPY_API * For backward compatibility * * Cast an array using typecode structure. * steals reference to at --- cannot be NULL */ NPY_NO_EXPORT PyObject * PyArray_CastToType(PyArrayObject *mp, PyArray_Descr *at, int fortran) { PyObject *out; int ret; PyArray_Descr *mpd; mpd = mp->descr; if (((mpd == at) || ((mpd->type_num == at->type_num) && PyArray_EquivByteorders(mpd->byteorder, at->byteorder) && ((mpd->elsize == at->elsize) || (at->elsize==0)))) && PyArray_ISBEHAVED_RO(mp)) { Py_DECREF(at); Py_INCREF(mp); return (PyObject *)mp; } if (at->elsize == 0) { PyArray_DESCR_REPLACE(at); if (at == NULL) { return NULL; } if (mpd->type_num == PyArray_STRING && at->type_num == PyArray_UNICODE) { at->elsize = mpd->elsize << 2; } if (mpd->type_num == PyArray_UNICODE && at->type_num == PyArray_STRING) { at->elsize = mpd->elsize >> 2; }
static npy_bool HALF_nonzero (char *ip, PyArrayObject *ap) { if (ap == NULL || PyArray_ISBEHAVED_RO(ap)) { npy_half *ptmp = (npy_half *)ip; return (npy_bool) (((*ptmp)&0x7fff) != 0); } else { npy_half tmp; ap->descr->f->copyswap(&tmp, ip, !PyArray_ISNOTSWAPPED(ap), ap); return (npy_bool) ((tmp&0x7fff) != 0); } }
static PyObject * HALF_getitem(char *ip, PyArrayObject *ap) { npy_half t1; double t2; if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) { t1 = *((npy_half *)ip); } else { ap->descr->f->copyswap(&t1, ip, !PyArray_ISNOTSWAPPED(ap), ap); } t2 = half_to_double(t1); return PyFloat_FromDouble(t2); }
static npy_bool QUATERNION_nonzero (char *ip, PyArrayObject *ap) { quaternion q; if (ap == NULL || PyArray_ISBEHAVED_RO(ap)) { q = *(quaternion *)ip; } else { PyArray_Descr *descr; descr = PyArray_DescrFromType(NPY_DOUBLE); descr->f->copyswap(&q.w, ip, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.x, ip+8, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.y, ip+16, !PyArray_ISNOTSWAPPED(ap), NULL); descr->f->copyswap(&q.z, ip+24, !PyArray_ISNOTSWAPPED(ap), NULL); Py_DECREF(descr); } return (npy_bool) !quaternion_equal(q, (quaternion) {0,0,0,0}); }
static PyObject *cluster(PyObject *self, PyObject *args) { int debug; PyObject *py_centers, *py_item, *py_res; PyArrayObject *np_chunk, *np_item; Py_ssize_t N_centers, N_frames, dim; float *chunk; float **centers; char *metric; float mindist; float d; float *buffer_a, *buffer_b; int l; int *centers_counter; void *arr_data; float *new_centers; int i, j; int closest_center_index; npy_intp dims[2]; float (*distance)(float*, float*, size_t, float*, float*); PyObject* return_new_centers; debug = 0; if(debug) printf("KMEANS: \n----------- cluster called ----------\n"); if(debug) printf("KMEANS: declaring variables..."); if(debug) printf("done.\n"); if(debug) printf("KMEANS: initializing some of them..."); py_centers = NULL; py_item = NULL; py_res = NULL; np_chunk = NULL; np_item = NULL; centers = NULL; metric=""; chunk = NULL; centers_counter = NULL; new_centers = NULL; buffer_a = NULL; buffer_b = NULL; return_new_centers = Py_BuildValue(""); if(debug) printf("done\n"); if(debug) printf("KMEANS: attempting to parse args..."); if (!PyArg_ParseTuple(args, "O!O!s", &PyArray_Type, &np_chunk, &PyList_Type, &py_centers, &metric)) { goto error; } if(debug) printf("done\n"); /* import chunk */ if(debug) printf("KMEANS: importing chunk..."); if(PyArray_TYPE(np_chunk)!=NPY_FLOAT32) { PyErr_SetString(PyExc_ValueError, "dtype of \"chunk\" isn\'t float (32)."); goto error; }; if(!PyArray_ISCARRAY_RO(np_chunk) ) { PyErr_SetString(PyExc_ValueError, "\"chunk\" isn\'t C-style contiguous or isn\'t behaved."); goto error; }; if(PyArray_NDIM(np_chunk)!=2) { PyErr_SetString(PyExc_ValueError, "Number of dimensions of \"chunk\" isn\'t 2."); goto error; }; N_frames = np_chunk->dimensions[0]; dim = np_chunk->dimensions[1]; if(dim==0) { PyErr_SetString(PyExc_ValueError, "chunk dimension must be larger than zero."); goto error; } chunk = PyArray_DATA(np_chunk); if(debug) printf("done with N_frames=%zd, dim=%zd\n", N_frames, dim); if(debug) printf("KMEANS: creating metric function..."); if(strcmp(metric,"euclidean")==0) { distance = euclidean_distance; } /*else if(strcmp(metric,"minRMSD")==0) { distance = minRMSD_distance; buffer_a = malloc(dim*sizeof(float)); buffer_b = malloc(dim*sizeof(float)); if(!buffer_a || !buffer_b) { PyErr_NoMemory(); goto error; } } */ else { PyErr_SetString(PyExc_ValueError, "metric must be one of \"euclidean\" or \"minRMSD\"."); goto error; } if(debug) printf("done\n"); /* import list of cluster centers */ if(debug) printf("KMEANS: importing list of cluster centers..."); N_centers = PyList_Size(py_centers); if(!(centers = malloc(N_centers*sizeof(float*)))) { PyErr_NoMemory(); goto error; } for(i = 0; i < N_centers; ++i) { l = 0; if(debug) printf("%d", l++); /* 0 */ py_item = PyList_GetItem(py_centers,i); /* ref:borr. */ if(debug) printf("%d", l++); /* 1 */ if(!py_item) goto error; if(debug) printf("%d", l++); /* 2 */ if(!PyArray_Check(py_item)) { PyErr_SetString(PyExc_ValueError, "Elements of centers must be numpy arrays."); goto error; } if(debug) printf("%d", l++); /* 3 */ np_item = (PyArrayObject*)py_item; if(debug) printf("%d", l++); /* 4 */ if(PyArray_TYPE(np_item)!=NPY_FLOAT32) { PyErr_SetString(PyExc_ValueError, "dtype of cluster center isn\'t float (32)."); goto error; }; if(debug) printf("%d", l++); /* 5 */ if(!PyArray_ISBEHAVED_RO(np_item) ) { PyErr_SetString(PyExc_ValueError, "cluster center isn\'t behaved."); goto error; }; if(debug) printf("%d", l++); /* 6 */ if(PyArray_NDIM(np_item)!=1) { PyErr_SetString(PyExc_ValueError, "Number of dimensions of cluster centers must be 1."); goto error; }; if(debug) printf("%d", l++); /* 7 */ if(np_item->dimensions[0]!=dim) { PyErr_SetString(PyExc_ValueError, "Dimension of cluster centers doesn\'t match dimension of frames."); goto error; } if(debug) printf("%d", l++); /* 8 */ centers[i] = (float*)PyArray_DATA(np_item); if(debug) printf("%d", l++); /* 9 */ } if(debug) printf("done, k=%zd\n", N_centers); /* initialize centers_counter and new_centers with zeros */ if(debug) printf("KMEANS: initializing calloc centers counter and new_centers stuff..."); centers_counter = (int*) calloc(N_centers, sizeof(int)); new_centers = (float*) calloc(N_centers * dim, sizeof(float)); if(!centers_counter || !new_centers) { PyErr_NoMemory(); goto error; } if(debug) printf("done\n"); /* do the clustering */ if(debug) printf("KMEANS: performing the clustering..."); for (i = 0; i < N_frames; i++) { mindist = FLT_MAX; for(j = 0; j < N_centers; ++j) { d = distance(&chunk[i*dim], centers[j], dim, buffer_a, buffer_b); if(d<mindist) { mindist = d; closest_center_index = j; } } (*(centers_counter + closest_center_index))++; for (j = 0; j < dim; j++) { new_centers[closest_center_index*dim+j] += chunk[i*dim+j]; } } for (i = 0; i < N_centers; i++) { if (*(centers_counter + i) == 0) { for (j = 0; j < dim; j++) { (*(new_centers + i * dim + j)) = centers[i][j]; } } else { for (j=0; j < dim; j++) { (*(new_centers + i * dim + j)) /= (*(centers_counter + i)); } } } if(debug) printf("done\n"); if(debug) printf("KMEANS: creating return_new_centers..."); dims[0] = N_centers; dims[1] = dim; return_new_centers = PyArray_SimpleNew(2, dims, NPY_FLOAT32); if (return_new_centers == NULL){ PyErr_SetString(PyExc_MemoryError, "Error occurs when creating a new PyArray"); goto error; } arr_data = PyArray_DATA((PyArrayObject*)return_new_centers); if(debug) printf("done\n"); /* Need to copy the data of the malloced buffer to the PyObject since the malloced buffer will disappear after the C extension is called. */ if(debug) printf("KMEANS: attempting memcopy..."); memcpy(arr_data, new_centers, PyArray_ITEMSIZE((PyArrayObject*) return_new_centers) * N_centers * dim); if(debug) printf("done\n"); if(debug) printf("KMEANS: increasting ref to return_new_centers thingy..."); Py_INCREF(return_new_centers); /* The returned list should still exist after calling the C extension */ if(debug) printf("done\n"); /* fall through */ error: free(centers_counter); free(new_centers); free(centers); free(buffer_a); free(buffer_b); return return_new_centers; }