int NI_FindObjects(PyArrayObject* input, npy_intp max_label, npy_intp* regions) { int kk; npy_intp size, jj; NI_Iterator ii; char *pi; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; /* get input data, size and iterator: */ pi = (void *)PyArray_DATA(input); size = 1; for(kk = 0; kk < input->nd; kk++) size *= input->dimensions[kk]; if (!NI_InitPointIterator(input, &ii)) goto exit; if (input->nd > 0) { for(jj = 0; jj < 2 * input->nd * max_label; jj++) regions[jj] = -1; } else { for(jj = 0; jj < max_label; jj++) regions[jj] = -1; } /* iterate over all points: */ for(jj = 0 ; jj < size; jj++) { switch (NI_NormalizeType(input->descr->type_num)) { CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, Bool); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, UInt8); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, UInt16); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, UInt32); #if HAS_UINT64 CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, UInt64); #endif CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, Int8); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, Int16); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, Int32); CASE_FIND_OBJECT_POINT(pi, regions, input->nd, input->dimensions, max_label, ii, Int64); break; default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT(ii, pi); } exit: NPY_END_THREADS; return PyErr_Occurred() ? 0 : 1; }
/* Initialize a line buffer */ int NI_InitLineBuffer(PyArrayObject *array, int axis, maybelong size1, maybelong size2, maybelong buffer_lines, double *buffer_data, NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) { maybelong line_length = 0, array_lines = 0, size; int ii; size = 1; for(ii = 0; ii < array->nd; ii++) size *= array->dimensions[ii]; /* check if the buffer is big enough: */ if (size > 0 && buffer_lines < 1) { PyErr_SetString(PyExc_RuntimeError, "buffer too small"); return 0; } /* Initialize a line iterator to move over the array: */ if (!NI_InitPointIterator(array, &(buffer->iterator))) return 0; if (!NI_LineIterator(&(buffer->iterator), axis)) return 0; line_length = array->nd > 0 ? array->dimensions[axis] : 1; if (line_length > 0) array_lines = line_length > 0 ? size / line_length : 1; /* initialize the buffer structure: */ buffer->array_data = (void *)PyArray_DATA(array); buffer->buffer_data = buffer_data; buffer->buffer_lines = buffer_lines; buffer->array_type = array->descr->type_num; buffer->array_lines = array_lines; buffer->next_line = 0; buffer->size1 = size1; buffer->size2 = size2; buffer->line_length = line_length; buffer->line_stride = array->nd > 0 ? array->strides[axis] : 0; buffer->extend_mode = extend_mode; buffer->extend_value = extend_value; return 1; }
/* Initialize a line buffer */ int NI_InitLineBuffer(PyArrayObject *array, int axis, npy_intp size1, npy_intp size2, npy_intp buffer_lines, double *buffer_data, NI_ExtendMode extend_mode, double extend_value, NI_LineBuffer *buffer) { npy_intp line_length = 0, array_lines = 0, size; size = PyArray_SIZE(array); /* check if the buffer is big enough: */ if (size > 0 && buffer_lines < 1) { PyErr_SetString(PyExc_RuntimeError, "buffer too small"); return 0; } /* Initialize a line iterator to move over the array: */ if (!NI_InitPointIterator(array, &(buffer->iterator))) return 0; if (!NI_LineIterator(&(buffer->iterator), axis)) return 0; line_length = PyArray_NDIM(array) > 0 ? PyArray_DIM(array, axis) : 1; if (line_length > 0) { array_lines = line_length > 0 ? size / line_length : 1; } /* initialize the buffer structure: */ buffer->array_data = (void *)PyArray_DATA(array); buffer->buffer_data = buffer_data; buffer->buffer_lines = buffer_lines; buffer->array_type = NI_CanonicalType(PyArray_TYPE(array)); buffer->array_lines = array_lines; buffer->next_line = 0; buffer->size1 = size1; buffer->size2 = size2; buffer->line_length = line_length; buffer->line_stride = PyArray_NDIM(array) > 0 ? PyArray_STRIDE(array, axis) : 0; buffer->extend_mode = extend_mode; buffer->extend_value = extend_value; return 1; }
int NI_GenericFilter(PyArrayObject* input, int (*function)(double*, npy_intp, double*, void*), void *data, PyArrayObject* footprint, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins) { Bool *pf = NULL; npy_intp fsize, jj, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; double *buffer = NULL; int ll; /* get the the footprint: */ fsize = 1; for(ll = 0; ll < footprint->nd; ll++) fsize *= footprint->dimensions[ll]; pf = (Bool*)PyArray_DATA(footprint); for(jj = 0; jj < fsize; jj++) { if (pf[jj]) ++filter_size; } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, mode, &offsets, &border_flag_value, NULL)) goto exit; /* initialize filter iterator: */ if (!NI_InitFilterIterator(input->nd, footprint->dimensions, filter_size, input->dimensions, origins, &fi)) goto exit; /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = 1; for(ll = 0; ll < input->nd; ll++) size *= input->dimensions[ll]; /* buffer for filter calculation: */ buffer = (double*)malloc(filter_size * sizeof(double)); if (!buffer) { PyErr_NoMemory(); goto exit; } /* iterate over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (NI_NormalizeType(input->descr->type_num)) { CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Bool, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt8, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt16, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt32, tmp, border_flag_value, function, data, buffer); #if HAS_UINT64 CASE_FILTER_POINT(pi, oo, filter_size, cvalue, UInt64, tmp, border_flag_value, function, data, buffer); #endif CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int8, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int16, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int32, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Int64, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float32, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(pi, oo, filter_size, cvalue, Float64, tmp, border_flag_value, function, data, buffer); default: PyErr_SetString(PyExc_RuntimeError, "array type not supported"); goto exit; } switch (NI_NormalizeType(output->descr->type_num)) { CASE_FILTER_OUT(po, tmp, Bool); CASE_FILTER_OUT(po, tmp, UInt8); CASE_FILTER_OUT(po, tmp, UInt16); CASE_FILTER_OUT(po, tmp, UInt32); #if HAS_UINT64 CASE_FILTER_OUT(po, tmp, UInt64); #endif CASE_FILTER_OUT(po, tmp, Int8); CASE_FILTER_OUT(po, tmp, Int16); CASE_FILTER_OUT(po, tmp, Int32); CASE_FILTER_OUT(po, tmp, Int64); CASE_FILTER_OUT(po, tmp, Float32); CASE_FILTER_OUT(po, tmp, Float64); default: PyErr_SetString(PyExc_RuntimeError, "array type not supported"); goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: if (offsets) free(offsets); if (buffer) free(buffer); return PyErr_Occurred() ? 0 : 1; }
int NI_GeometricTransform(PyArrayObject *input, int (*map)(npy_intp*, double*, int, int, void*), void* map_data, PyArrayObject* matrix_ar, PyArrayObject* shift_ar, PyArrayObject *coordinates, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi, *pc = NULL; npy_intp **edge_offsets = NULL, **data_offsets = NULL, filter_size; npy_intp ftmp[NPY_MAXDIMS], *fcoordinates = NULL, *foffsets = NULL; npy_intp cstride = 0, kk, hh, ll, jj; npy_intp size; double **splvals = NULL, icoor[NPY_MAXDIMS]; npy_intp idimensions[NPY_MAXDIMS], istrides[NPY_MAXDIMS]; NI_Iterator io, ic; npy_double *matrix = matrix_ar ? (npy_double*)PyArray_DATA(matrix_ar) : NULL; npy_double *shift = shift_ar ? (npy_double*)PyArray_DATA(shift_ar) : NULL; int irank = 0, orank; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; for(kk = 0; kk < PyArray_NDIM(input); kk++) { idimensions[kk] = PyArray_DIM(input, kk); istrides[kk] = PyArray_STRIDE(input, kk); } irank = PyArray_NDIM(input); orank = PyArray_NDIM(output); /* if the mapping is from array coordinates: */ if (coordinates) { /* initialize a line iterator along the first axis: */ if (!NI_InitPointIterator(coordinates, &ic)) goto exit; cstride = ic.strides[0]; if (!NI_LineIterator(&ic, 0)) goto exit; pc = (void *)(PyArray_DATA(coordinates)); } /* offsets used at the borders: */ edge_offsets = malloc(irank * sizeof(npy_intp*)); data_offsets = malloc(irank * sizeof(npy_intp*)); if (NPY_UNLIKELY(!edge_offsets || !data_offsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) data_offsets[jj] = NULL; for(jj = 0; jj < irank; jj++) { data_offsets[jj] = malloc((order + 1) * sizeof(npy_intp)); if (NPY_UNLIKELY(!data_offsets[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } /* will hold the spline coefficients: */ splvals = malloc(irank * sizeof(double*)); if (NPY_UNLIKELY(!splvals)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) splvals[jj] = NULL; for(jj = 0; jj < irank; jj++) { splvals[jj] = malloc((order + 1) * sizeof(double)); if (NPY_UNLIKELY(!splvals[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } filter_size = 1; for(jj = 0; jj < irank; jj++) filter_size *= order + 1; /* initialize output iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; /* get data pointers: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* make a table of all possible coordinates within the spline filter: */ fcoordinates = malloc(irank * filter_size * sizeof(npy_intp)); /* make a table of all offsets within the spline filter: */ foffsets = malloc(filter_size * sizeof(npy_intp)); if (NPY_UNLIKELY(!fcoordinates || !foffsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < irank; jj++) fcoordinates[jj + hh * irank] = ftmp[jj]; foffsets[hh] = kk; for(jj = irank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = PyArray_SIZE(output); for(kk = 0; kk < size; kk++) { double t = 0.0; int constant = 0, edge = 0; npy_intp offset = 0; if (map) { NPY_END_THREADS; /* call mappint functions: */ if (!map(io.coordinates, icoor, orank, irank, map_data)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "unknown error in mapping function"); goto exit; } NPY_BEGIN_THREADS; } else if (matrix) { /* do an affine transformation: */ npy_double *p = matrix; for(hh = 0; hh < irank; hh++) { icoor[hh] = 0.0; for(ll = 0; ll < orank; ll++) icoor[hh] += io.coordinates[ll] * *p++; icoor[hh] += shift[hh]; } } else if (coordinates) { /* mapping is from an coordinates array: */ char *p = pc; switch (PyArray_TYPE(coordinates)) { CASE_MAP_COORDINATES(NPY_BOOL, npy_bool, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_UBYTE, npy_ubyte, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_USHORT, npy_ushort, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_UINT, npy_uint, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_ULONG, npy_ulong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_ULONGLONG, npy_ulonglong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_BYTE, npy_byte, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_SHORT, npy_short, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_INT, npy_int, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_LONG, npy_long, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_LONGLONG, npy_longlong, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_FLOAT, npy_float, p, icoor, irank, cstride); CASE_MAP_COORDINATES(NPY_DOUBLE, npy_double, p, icoor, irank, cstride); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "coordinate array data type not supported"); goto exit; } } /* iterate over axes: */ for(hh = 0; hh < irank; hh++) { /* if the input coordinate is outside the borders, map it: */ double cc = map_coordinate(icoor[hh], idimensions[hh], mode); if (cc > -1.0) { /* find the filter location along this axis: */ npy_intp start; if (order & 1) { start = (npy_intp)floor(cc) - order / 2; } else { start = (npy_intp)floor(cc + 0.5) - order / 2; } /* get the offset to the start of the filter: */ offset += istrides[hh] * start; if (start < 0 || start + order >= idimensions[hh]) { /* implement border mapping, if outside border: */ edge = 1; edge_offsets[hh] = data_offsets[hh]; for(ll = 0; ll <= order; ll++) { npy_intp idx = start + ll; npy_intp len = idimensions[hh]; if (len <= 1) { idx = 0; } else { npy_intp s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (int)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (int)(idx / s2); if (idx >= len) idx = s2 - idx; } } /* calculate and store the offests at this edge: */ edge_offsets[hh][ll] = istrides[hh] * (idx - start); } } else { /* we are not at the border, use precalculated offsets: */ edge_offsets[hh] = NULL; } spline_coefficients(cc, order, splvals[hh]); } else { /* we use the constant border condition: */ constant = 1; break; } } if (!constant) { npy_intp *ff = fcoordinates; const int type_num = PyArray_TYPE(input); t = 0.0; for(hh = 0; hh < filter_size; hh++) { double coeff = 0.0; npy_intp idx = 0; if (NPY_UNLIKELY(edge)) { for(ll = 0; ll < irank; ll++) { if (edge_offsets[ll]) idx += edge_offsets[ll][ff[ll]]; else idx += ff[ll] * istrides[ll]; } } else { idx = foffsets[hh]; } idx += offset; switch (type_num) { CASE_INTERP_COEFF(NPY_BOOL, npy_bool, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UBYTE, npy_ubyte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_USHORT, npy_ushort, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UINT, npy_uint, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONG, npy_ulong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONGLONG, npy_ulonglong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_BYTE, npy_byte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_SHORT, npy_short, coeff, pi, idx); CASE_INTERP_COEFF(NPY_INT, npy_int, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONG, npy_long, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONGLONG, npy_longlong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_FLOAT, npy_float, coeff, pi, idx); CASE_INTERP_COEFF(NPY_DOUBLE, npy_double, coeff, pi, idx); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate the interpolated value: */ for(ll = 0; ll < irank; ll++) if (order > 0) coeff *= splvals[ll][ff[ll]]; t += coeff; ff += irank; } } else { t = cval; } /* store output value: */ switch (PyArray_TYPE(output)) { CASE_INTERP_OUT(NPY_BOOL, npy_bool, po, t); CASE_INTERP_OUT_UINT(UBYTE, npy_ubyte, po, t); CASE_INTERP_OUT_UINT(USHORT, npy_ushort, po, t); CASE_INTERP_OUT_UINT(UINT, npy_uint, po, t); CASE_INTERP_OUT_UINT(ULONG, npy_ulong, po, t); CASE_INTERP_OUT_UINT(ULONGLONG, npy_ulonglong, po, t); CASE_INTERP_OUT_INT(BYTE, npy_byte, po, t); CASE_INTERP_OUT_INT(SHORT, npy_short, po, t); CASE_INTERP_OUT_INT(INT, npy_int, po, t); CASE_INTERP_OUT_INT(LONG, npy_long, po, t); CASE_INTERP_OUT_INT(LONGLONG, npy_longlong, po, t); CASE_INTERP_OUT(NPY_FLOAT, npy_float, po, t); CASE_INTERP_OUT(NPY_DOUBLE, npy_double, po, t); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } if (coordinates) { NI_ITERATOR_NEXT2(io, ic, po, pc); } else { NI_ITERATOR_NEXT(io, po); } } exit: NPY_END_THREADS; free(edge_offsets); if (data_offsets) { for(jj = 0; jj < irank; jj++) free(data_offsets[jj]); free(data_offsets); } if (splvals) { for(jj = 0; jj < irank; jj++) free(splvals[jj]); free(splvals); } free(foffsets); free(fcoordinates); return PyErr_Occurred() ? 0 : 1; }
int NI_Correlate(PyArrayObject* input, PyArrayObject* weights, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins) { Bool *pf = NULL; npy_intp fsize, jj, kk, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; Float64 *pw; Float64 *ww = NULL; int ll, err = 0; NPY_BEGIN_THREADS_DEF; /* get the the footprint: */ fsize = 1; for(ll = 0; ll < weights->nd; ll++) fsize *= weights->dimensions[ll]; pw = (Float64*)PyArray_DATA(weights); pf = (Bool*)malloc(fsize * sizeof(Bool)); if (!pf) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < fsize; jj++) { if (fabs(pw[jj]) > DBL_EPSILON) { pf[jj] = 1; ++filter_size; } else { pf[jj] = 0; } } /* copy the weights to contiguous memory: */ ww = (Float64*)malloc(filter_size * sizeof(Float64)); if (!ww) { PyErr_NoMemory(); goto exit; } jj = 0; for(kk = 0; kk < fsize; kk++) { if (pf[kk]) { ww[jj++] = pw[kk]; } } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, weights->dimensions, origins, mode, &offsets, &border_flag_value, NULL)) goto exit; /* initialize filter iterator: */ if (!NI_InitFilterIterator(input->nd, weights->dimensions, filter_size, input->dimensions, origins, &fi)) goto exit; /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; NPY_BEGIN_THREADS; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = 1; for(ll = 0; ll < input->nd; ll++) size *= input->dimensions[ll]; /* iterator over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (NI_NormalizeType(input->descr->type_num)) { CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Bool, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt8, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt16, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt32, tmp, border_flag_value); #if HAS_UINT64 CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, UInt64, tmp, border_flag_value); #endif CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int8, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int16, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int32, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Int64, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float32, tmp, border_flag_value); CASE_CORRELATE_POINT(pi, ww, oo, filter_size, cvalue, Float64, tmp, border_flag_value); default: err = 1; goto exit; } switch (NI_NormalizeType(output->descr->type_num)) { CASE_FILTER_OUT(po, tmp, Bool); CASE_FILTER_OUT(po, tmp, UInt8); CASE_FILTER_OUT(po, tmp, UInt16); CASE_FILTER_OUT(po, tmp, UInt32); #if HAS_UINT64 CASE_FILTER_OUT(po, tmp, UInt64); #endif CASE_FILTER_OUT(po, tmp, Int8); CASE_FILTER_OUT(po, tmp, Int16); CASE_FILTER_OUT(po, tmp, Int32); CASE_FILTER_OUT(po, tmp, Int64); CASE_FILTER_OUT(po, tmp, Float32); CASE_FILTER_OUT(po, tmp, Float64); default: err = 1; goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: NPY_END_THREADS; if (err == 1) { PyErr_SetString(PyExc_RuntimeError, "array type not supported"); } if (offsets) free(offsets); if (ww) free(ww); if (pf) free(pf); return PyErr_Occurred() ? 0 : 1; }
int NI_MinOrMaxFilter(PyArrayObject* input, PyArrayObject* footprint, PyArrayObject* structure, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins, int minimum) { Bool *pf = NULL; npy_intp fsize, jj, kk, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; int ll, err = 0; double *ss = NULL; Float64 *ps; NPY_BEGIN_THREADS_DEF; /* get the the footprint: */ fsize = 1; for(ll = 0; ll < footprint->nd; ll++) fsize *= footprint->dimensions[ll]; pf = (Bool*)PyArray_DATA(footprint); for(jj = 0; jj < fsize; jj++) { if (pf[jj]) { ++filter_size; } } /* get the structure: */ if (structure) { ss = (double*)malloc(filter_size * sizeof(double)); if (!ss) { PyErr_NoMemory(); goto exit; } /* copy the weights to contiguous memory: */ ps = (Float64*)PyArray_DATA(structure); jj = 0; for(kk = 0; kk < fsize; kk++) if (pf[kk]) ss[jj++] = minimum ? -ps[kk] : ps[kk]; } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, footprint->dimensions, origins, mode, &offsets, &border_flag_value, NULL)) goto exit; /* initialize filter iterator: */ if (!NI_InitFilterIterator(input->nd, footprint->dimensions, filter_size, input->dimensions, origins, &fi)) goto exit; /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; NPY_BEGIN_THREADS; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = 1; for(ll = 0; ll < input->nd; ll++) size *= input->dimensions[ll]; /* iterator over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (NI_NormalizeType(input->descr->type_num)) { CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Bool, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt8, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt16, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt32, minimum, tmp, border_flag_value, ss); #if HAS_UINT64 CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, UInt64, minimum, tmp, border_flag_value, ss); #endif CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int8, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int16, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int32, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Int64, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float32, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(pi, oo, filter_size, cvalue, Float64, minimum, tmp, border_flag_value, ss); default: err = 1; goto exit; } switch (NI_NormalizeType(output->descr->type_num)) { CASE_FILTER_OUT(po, tmp, Bool); CASE_FILTER_OUT(po, tmp, UInt8); CASE_FILTER_OUT(po, tmp, UInt16); CASE_FILTER_OUT(po, tmp, UInt32); #if HAS_UINT64 CASE_FILTER_OUT(po, tmp, UInt64); #endif CASE_FILTER_OUT(po, tmp, Int8); CASE_FILTER_OUT(po, tmp, Int16); CASE_FILTER_OUT(po, tmp, Int32); CASE_FILTER_OUT(po, tmp, Int64); CASE_FILTER_OUT(po, tmp, Float32); CASE_FILTER_OUT(po, tmp, Float64); default: err = 1; goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: NPY_END_THREADS; if (err == 1) { PyErr_SetString(PyExc_RuntimeError, "array type not supported"); } if (offsets) free(offsets); if (ss) free(ss); return PyErr_Occurred() ? 0 : 1; }
int NI_GeometricTransform(PyArrayObject *input, int (*map)(npy_intp*, double*, int, int, void*), void* map_data, PyArrayObject* matrix_ar, PyArrayObject* shift_ar, PyArrayObject *coordinates, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi, *pc = NULL; npy_intp **edge_offsets = NULL, **data_offsets = NULL, filter_size; npy_intp ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; npy_intp cstride = 0, kk, hh, ll, jj, *idxs = NULL; npy_intp size; double **splvals = NULL, icoor[MAXDIM]; npy_intp idimensions[MAXDIM], istrides[MAXDIM]; NI_Iterator io, ic; Float64 *matrix = matrix_ar ? (Float64*)PyArray_DATA(matrix_ar) : NULL; Float64 *shift = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; int irank = 0, orank, qq; for(kk = 0; kk < input->nd; kk++) { idimensions[kk] = input->dimensions[kk]; istrides[kk] = input->strides[kk]; } irank = input->nd; orank = output->nd; /* if the mapping is from array coordinates: */ if (coordinates) { /* initialze a line iterator along the first axis: */ if (!NI_InitPointIterator(coordinates, &ic)) goto exit; cstride = ic.strides[0]; if (!NI_LineIterator(&ic, 0)) goto exit; pc = (void *)(PyArray_DATA(coordinates)); } /* offsets used at the borders: */ edge_offsets = (npy_intp**)malloc(irank * sizeof(npy_intp*)); data_offsets = (npy_intp**)malloc(irank * sizeof(npy_intp*)); if (!edge_offsets || !data_offsets) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) data_offsets[jj] = NULL; for(jj = 0; jj < irank; jj++) { data_offsets[jj] = (npy_intp*)malloc((order + 1) * sizeof(npy_intp)); if (!data_offsets[jj]) { PyErr_NoMemory(); goto exit; } } /* will hold the spline coefficients: */ splvals = (double**)malloc(irank * sizeof(double*)); if (!splvals) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) splvals[jj] = NULL; for(jj = 0; jj < irank; jj++) { splvals[jj] = (double*)malloc((order + 1) * sizeof(double)); if (!splvals[jj]) { PyErr_NoMemory(); goto exit; } } filter_size = 1; for(jj = 0; jj < irank; jj++) filter_size *= order + 1; idxs = (npy_intp*)malloc(filter_size * sizeof(idxs)); if (!idxs) { PyErr_NoMemory(); goto exit; } /* initialize output iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; /* get data pointers: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* make a table of all possible coordinates within the spline filter: */ fcoordinates = (npy_intp*)malloc(irank * filter_size * sizeof(npy_intp)); /* make a table of all offsets within the spline filter: */ foffsets = (npy_intp*)malloc(filter_size * sizeof(npy_intp)); if (!fcoordinates || !foffsets) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < irank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < irank; jj++) fcoordinates[jj + hh * irank] = ftmp[jj]; foffsets[hh] = kk; for(jj = irank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = 1; for(qq = 0; qq < output->nd; qq++) size *= output->dimensions[qq]; for(kk = 0; kk < size; kk++) { double t = 0.0; int constant = 0, edge = 0, offset = 0; if (map) { /* call mappint functions: */ if (!map(io.coordinates, icoor, orank, irank, map_data)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "unknown error in mapping function"); goto exit; } } else if (matrix) { /* do an affine transformation: */ Float64 *p = matrix; for(hh = 0; hh < irank; hh++) { icoor[hh] = 0.0; for(ll = 0; ll < orank; ll++) icoor[hh] += io.coordinates[ll] * *p++; icoor[hh] += shift[hh]; } } else if (coordinates) { /* mapping is from an coordinates array: */ char *p = pc; switch(coordinates->descr->type_num) { CASE_MAP_COORDINATES(p, icoor, irank, cstride, Bool); CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt8); CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt16); CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt32); #if HAS_UINT64 CASE_MAP_COORDINATES(p, icoor, irank, cstride, UInt64); #endif CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int8); CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int16); CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int32); CASE_MAP_COORDINATES(p, icoor, irank, cstride, Int64); CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float32); CASE_MAP_COORDINATES(p, icoor, irank, cstride, Float64); default: PyErr_SetString(PyExc_RuntimeError, "coordinate array data type not supported"); goto exit; } } /* iterate over axes: */ for(hh = 0; hh < irank; hh++) { /* if the input coordinate is outside the borders, map it: */ double cc = map_coordinate(icoor[hh], idimensions[hh], mode); if (cc > -1.0) { /* find the filter location along this axis: */ int start; if (order & 1) { start = (int)floor(cc) - order / 2; } else { start = (int)floor(cc + 0.5) - order / 2; } /* get the offset to the start of the filter: */ offset += istrides[hh] * start; if (start < 0 || start + order >= idimensions[hh]) { /* implement border mapping, if outside border: */ edge = 1; edge_offsets[hh] = data_offsets[hh]; for(ll = 0; ll <= order; ll++) { int idx = start + ll; int len = idimensions[hh]; if (len <= 1) { idx = 0; } else { int s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (int)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (int)(idx / s2); if (idx >= len) idx = s2 - idx; } } /* calculate and store the offests at this edge: */ edge_offsets[hh][ll] = istrides[hh] * (idx - start); } } else { /* we are not at the border, use precalculated offsets: */ edge_offsets[hh] = NULL; } spline_coefficients(cc, order, splvals[hh]); } else { /* we use the constant border condition: */ constant = 1; break; } } if (!constant) { npy_intp *ff = fcoordinates; for(hh = 0; hh < filter_size; hh++) { int idx = 0; if (edge) { for(ll = 0; ll < irank; ll++) { if (edge_offsets[ll]) idx += edge_offsets[ll][ff[ll]]; else idx += ff[ll] * istrides[ll]; } } else { idx = foffsets[hh]; } idx += offset; idxs[hh] = idx; ff += irank; } } if (!constant) { npy_intp *ff = fcoordinates; t = 0.0; for(hh = 0; hh < filter_size; hh++) { double coeff = 0.0; switch(input->descr->type_num) { CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); #if HAS_UINT64 CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); #endif CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); default: PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate the interpolated value: */ for(ll = 0; ll < irank; ll++) if (order > 0) coeff *= splvals[ll][ff[ll]]; t += coeff; ff += irank; } } else { t = cval; } /* store output value: */ switch (output->descr->type_num) { CASE_INTERP_OUT(po, t, Bool); CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); #if HAS_UINT64 /* FIXME */ CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); #endif CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); CASE_INTERP_OUT(po, t, Float32); CASE_INTERP_OUT(po, t, Float64); default: PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } if (coordinates) { NI_ITERATOR_NEXT2(io, ic, po, pc); } else { NI_ITERATOR_NEXT(io, po); } } exit: if (edge_offsets) free(edge_offsets); if (data_offsets) { for(jj = 0; jj < irank; jj++) free(data_offsets[jj]); free(data_offsets); } if (splvals) { for(jj = 0; jj < irank; jj++) free(splvals[jj]); free(splvals); } if (foffsets) free(foffsets); if (fcoordinates) free(fcoordinates); if (idxs) free(idxs); return PyErr_Occurred() ? 0 : 1; }
int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, PyArrayObject* shift_ar, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi; npy_intp **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; npy_intp ftmp[MAXDIM], *fcoordinates = NULL, *foffsets = NULL; npy_intp jj, hh, kk, filter_size, odimensions[MAXDIM]; npy_intp idimensions[MAXDIM], istrides[MAXDIM], *idxs = NULL; npy_intp size; double ***splvals = NULL; NI_Iterator io; Float64 *zooms = zoom_ar ? (Float64*)PyArray_DATA(zoom_ar) : NULL; Float64 *shifts = shift_ar ? (Float64*)PyArray_DATA(shift_ar) : NULL; int rank = 0, qq; for(kk = 0; kk < input->nd; kk++) { idimensions[kk] = input->dimensions[kk]; istrides[kk] = input->strides[kk]; odimensions[kk] = output->dimensions[kk]; } rank = input->nd; /* if the mode is 'constant' we need some temps later: */ if (mode == NI_EXTEND_CONSTANT) { zeros = (npy_intp**)malloc(rank * sizeof(npy_intp*)); if (!zeros) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) zeros[jj] = NULL; for(jj = 0; jj < rank; jj++) { zeros[jj] = (npy_intp*)malloc(odimensions[jj] * sizeof(npy_intp)); if(!zeros[jj]) { PyErr_NoMemory(); goto exit; } } } /* store offsets, along each axis: */ offsets = (npy_intp**)malloc(rank * sizeof(npy_intp*)); /* store spline coefficients, along each axis: */ splvals = (double***)malloc(rank * sizeof(double**)); /* store offsets at all edges: */ edge_offsets = (npy_intp***)malloc(rank * sizeof(npy_intp**)); if (!offsets || !splvals || !edge_offsets) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) { offsets[jj] = NULL; splvals[jj] = NULL; edge_offsets[jj] = NULL; } for(jj = 0; jj < rank; jj++) { offsets[jj] = (npy_intp*)malloc(odimensions[jj] * sizeof(npy_intp)); splvals[jj] = (double**)malloc(odimensions[jj] * sizeof(double*)); edge_offsets[jj] = (npy_intp**)malloc(odimensions[jj] * sizeof(npy_intp*)); if (!offsets[jj] || !splvals[jj] || !edge_offsets[jj]) { PyErr_NoMemory(); goto exit; } for(hh = 0; hh < odimensions[jj]; hh++) { splvals[jj][hh] = NULL; edge_offsets[jj][hh] = NULL; } } /* precalculate offsets, and offsets at the edge: */ for(jj = 0; jj < rank; jj++) { double shift = 0.0, zoom = 0.0; if (shifts) shift = shifts[jj]; if (zooms) zoom = zooms[jj]; for(kk = 0; kk < odimensions[jj]; kk++) { double cc = (double)kk; if (shifts) cc += shift; if (zooms) cc *= zoom; cc = map_coordinate(cc, idimensions[jj], mode); if (cc > -1.0) { int start; if (zeros && zeros[jj]) zeros[jj][kk] = 0; if (order & 1) { start = (int)floor(cc) - order / 2; } else { start = (int)floor(cc + 0.5) - order / 2; } offsets[jj][kk] = istrides[jj] * start; if (start < 0 || start + order >= idimensions[jj]) { edge_offsets[jj][kk] = (npy_intp*)malloc((order + 1) * sizeof(npy_intp)); if (!edge_offsets[jj][kk]) { PyErr_NoMemory(); goto exit; } for(hh = 0; hh <= order; hh++) { int idx = start + hh; int len = idimensions[jj]; if (len <= 1) { idx = 0; } else { int s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (int)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (int)(idx / s2); if (idx >= len) idx = s2 - idx; } } edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); } } if (order > 0) { splvals[jj][kk] = (double*)malloc((order + 1) * sizeof(double)); if (!splvals[jj][kk]) { PyErr_NoMemory(); goto exit; } spline_coefficients(cc, order, splvals[jj][kk]); } } else { zeros[jj][kk] = 1; } } } filter_size = 1; for(jj = 0; jj < rank; jj++) filter_size *= order + 1; idxs = (npy_intp*)malloc(filter_size * sizeof(idxs)); if (!idxs) { PyErr_NoMemory(); goto exit; } if (!NI_InitPointIterator(output, &io)) goto exit; pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* store all coordinates and offsets with filter: */ fcoordinates = (npy_intp*)malloc(rank * filter_size * sizeof(npy_intp)); foffsets = (npy_intp*)malloc(filter_size * sizeof(npy_intp)); if (!fcoordinates || !foffsets) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < rank; jj++) fcoordinates[jj + hh * rank] = ftmp[jj]; foffsets[hh] = kk; for(jj = rank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = 1; for(qq = 0; qq < output->nd; qq++) size *= output->dimensions[qq]; for(kk = 0; kk < size; kk++) { double t = 0.0; int edge = 0, oo = 0, zero = 0; for(hh = 0; hh < rank; hh++) { if (zeros && zeros[hh][io.coordinates[hh]]) { /* we use constant border condition */ zero = 1; break; } oo += offsets[hh][io.coordinates[hh]]; if (edge_offsets[hh][io.coordinates[hh]]) edge = 1; } if (!zero) { npy_intp *ff = fcoordinates; for(hh = 0; hh < filter_size; hh++) { int idx = 0; if (edge) { /* use precalculated edge offsets: */ for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj][io.coordinates[jj]]) idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; else idx += ff[jj] * istrides[jj]; } idx += oo; } else { /* use normal offsets: */ idx += oo + foffsets[hh]; } idxs[hh] = idx; ff += rank; } } if (!zero) { npy_intp *ff = fcoordinates; t = 0.0; for(hh = 0; hh < filter_size; hh++) { double coeff = 0.0; switch(input->descr->type_num) { CASE_INTERP_COEFF(coeff, pi, idxs[hh], Bool); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt8); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt16); CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt32); #if HAS_UINT64 CASE_INTERP_COEFF(coeff, pi, idxs[hh], UInt64); #endif CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int8); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int16); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int32); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Int64); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float32); CASE_INTERP_COEFF(coeff, pi, idxs[hh], Float64); default: PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate interpolated value: */ for(jj = 0; jj < rank; jj++) if (order > 0) coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; t += coeff; ff += rank; } } else { t = cval; } /* store output: */ switch (output->descr->type_num) { CASE_INTERP_OUT(po, t, Bool); CASE_INTERP_OUT_UINT(po, t, UInt8, 0, MAX_UINT8); CASE_INTERP_OUT_UINT(po, t, UInt16, 0, MAX_UINT16); CASE_INTERP_OUT_UINT(po, t, UInt32, 0, MAX_UINT32); #if HAS_UINT64 /* FIXME */ CASE_INTERP_OUT_UINT(po, t, UInt64, 0, MAX_UINT32); #endif CASE_INTERP_OUT_INT(po, t, Int8, MIN_INT8, MAX_INT8); CASE_INTERP_OUT_INT(po, t, Int16, MIN_INT16, MAX_INT16); CASE_INTERP_OUT_INT(po, t, Int32, MIN_INT32, MAX_INT32); CASE_INTERP_OUT_INT(po, t, Int64, MIN_INT64, MAX_INT64); CASE_INTERP_OUT(po, t, Float32); CASE_INTERP_OUT(po, t, Float64); default: PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT(io, po); } exit: if (zeros) { for(jj = 0; jj < rank; jj++) if (zeros[jj]) free(zeros[jj]); free(zeros); } if (offsets) { for(jj = 0; jj < rank; jj++) if (offsets[jj]) free(offsets[jj]); free(offsets); } if (splvals) { for(jj = 0; jj < rank; jj++) { if (splvals[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) if (splvals[jj][hh]) free(splvals[jj][hh]); free(splvals[jj]); } } free(splvals); } if (edge_offsets) { for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) if (edge_offsets[jj][hh]) free(edge_offsets[jj][hh]); free(edge_offsets[jj]); } } free(edge_offsets); } if (foffsets) free(foffsets); if (fcoordinates) free(fcoordinates); if (idxs) free(idxs); return PyErr_Occurred() ? 0 : 1; }
int NI_Statistics(PyArrayObject *input, PyArrayObject *labels, npy_intp min_label, npy_intp max_label, npy_intp *indices, npy_intp n_results, double *sum, npy_intp *total, double *variance, double *minimum, double *maximum, npy_intp* min_pos, npy_intp* max_pos) { char *pi = NULL, *pm = NULL; NI_Iterator ii, mi; npy_intp jj, size, idx = 0, label = 1, doit = 1; int qq; NPY_BEGIN_THREADS_DEF; /* input iterator: */ if (!NI_InitPointIterator(input, &ii)) return 0; /* input data: */ pi = (void *)PyArray_DATA(input); if (labels) { if (!NI_InitPointIterator(labels, &mi)) return 0; pm = (void *)PyArray_DATA(labels); } NPY_BEGIN_THREADS; /* input size: */ size = 1; for(qq = 0; qq < input->nd; qq++) size *= input->dimensions[qq]; for(jj = 0; jj < n_results; jj++) { if (sum) sum[jj] = 0.0; if (total) total[jj] = 0; if (variance) variance[jj] = 0; if (minimum) minimum[jj] = DBL_MAX; if (maximum) maximum[jj] = -DBL_MAX; if (min_pos) min_pos[jj] = 0; if (max_pos) max_pos[jj] = 0; } /* iterate over array: */ for(jj = 0; jj < size; jj++) { NI_GET_LABEL(pm, label, NI_NormalizeType(labels->descr->type_num)); if (min_label >= 0) { if (label >= min_label && label <= max_label) { idx = indices[label - min_label]; doit = idx >= 0; } else { doit = 0; } } else { doit = label != 0; } if (doit) { double val; NI_GET_VALUE(pi, val, NI_NormalizeType(input->descr->type_num)); if (sum) sum[idx] += val; if (total) total[idx]++; if (minimum && val < minimum[idx]) { minimum[idx] = val; if (min_pos) min_pos[idx] = jj; } if (maximum && (val > maximum[idx])) { maximum[idx] = val; if (max_pos) max_pos[idx] = jj; } } if (labels) { NI_ITERATOR_NEXT2(ii, mi, pi, pm); } else { NI_ITERATOR_NEXT(ii, pi); } } if (minimum) { for(jj = 0; jj < n_results; jj++) { if (!(minimum[jj] < DBL_MAX)) minimum[jj] = 0.0; } } if (maximum) { for(jj = 0; jj < n_results; jj++) { if (!(maximum[jj] > -DBL_MAX)) maximum[jj] = 0.0; } } if (variance) { int do_var = 0; for(jj = 0; jj < n_results; jj++) if (total[jj] > 1) { do_var = 1; break; } if (do_var) { /* reset input iterator: */ NI_ITERATOR_RESET(ii); pi = (void *)PyArray_DATA(input); if (labels) { /* reset label iterator: */ NI_ITERATOR_RESET(mi); pm = (void *)PyArray_DATA(labels); } for(jj = 0; jj < size; jj++) { NI_GET_LABEL(pm, label, NI_NormalizeType(labels->descr->type_num)); if (min_label >= 0) { if (label >= min_label && label <= max_label) { idx = indices[label - min_label]; doit = idx >= 0; } else { doit = 0; } } else { doit = label != 0; } if (doit) { double val; NI_GET_VALUE(pi, val, NI_NormalizeType(input->descr->type_num)); val = val - sum[idx] / total[idx]; variance[idx] += val * val; } if (labels) { NI_ITERATOR_NEXT2(ii, mi, pi, pm); } else { NI_ITERATOR_NEXT(ii, pi); } } for(jj = 0; jj < n_results; jj++) variance[jj] = (total[jj] > 1 ? variance[jj] / (total[jj] - 1) : 0.0); } } NPY_END_THREADS; return 1; }
int NI_CenterOfMass(PyArrayObject *input, PyArrayObject *labels, npy_intp min_label, npy_intp max_label, npy_intp *indices, npy_intp n_results, double *center_of_mass) { char *pi = NULL, *pm = NULL; NI_Iterator ii, mi; npy_intp jj, kk, size, idx = 0, label = 1, doit = 1; double *sum = NULL; int qq; NPY_BEGIN_THREADS_DEF; /* input iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* input data: */ pi = (void *)PyArray_DATA(input); if (labels) { if (!NI_InitPointIterator(labels, &mi)) goto exit; pm = (void *)PyArray_DATA(labels); } /* input size: */ size = 1; for(qq = 0; qq < input->nd; qq++) size *= input->dimensions[qq]; sum = (double*)malloc(n_results * sizeof(double)); if (!sum) { PyErr_NoMemory(); goto exit; } NPY_BEGIN_THREADS; for(jj = 0; jj < n_results; jj++) { sum[jj] = 0.0; for(kk = 0; kk < input->nd; kk++) center_of_mass[jj * input->nd + kk] = 0.0; } /* iterate over array: */ for(jj = 0; jj < size; jj++) { NI_GET_LABEL(pm, label, NI_NormalizeType(labels->descr->type_num)); if (min_label >= 0) { if (label >= min_label && label <= max_label) { idx = indices[label - min_label]; doit = idx >= 0; } else { doit = 0; } } else { doit = label != 0; } if (doit) { double val; NI_GET_VALUE(pi, val, NI_NormalizeType(input->descr->type_num)); sum[idx] += val; for(kk = 0; kk < input->nd; kk++) center_of_mass[idx * input->nd + kk] += val * ii.coordinates[kk]; } if (labels) { NI_ITERATOR_NEXT2(ii, mi, pi, pm); } else { NI_ITERATOR_NEXT(ii, pi); } } for(jj = 0; jj < n_results; jj++) for(kk = 0; kk < input->nd; kk++) center_of_mass[jj * input->nd + kk] /= sum[jj]; exit: NPY_END_THREADS; free(sum); return PyErr_Occurred() == NULL; }
int NI_MinOrMaxFilter(PyArrayObject* input, PyArrayObject* footprint, PyArrayObject* structure, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins, int minimum) { npy_bool *pf = NULL; npy_intp fsize, jj, kk, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; int err = 0; double *ss = NULL; npy_double *ps; NPY_BEGIN_THREADS_DEF; /* get the the footprint: */ fsize = PyArray_SIZE(footprint); pf = (npy_bool*)PyArray_DATA(footprint); for(jj = 0; jj < fsize; jj++) { if (pf[jj]) { ++filter_size; } } /* get the structure: */ if (structure) { ss = malloc(filter_size * sizeof(double)); if (!ss) { PyErr_NoMemory(); goto exit; } /* copy the weights to contiguous memory: */ ps = (npy_double*)PyArray_DATA(structure); jj = 0; for(kk = 0; kk < fsize; kk++) if (pf[kk]) ss[jj++] = minimum ? -ps[kk] : ps[kk]; } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, PyArray_DIMS(footprint), origins, mode, &offsets, &border_flag_value, NULL)) { goto exit; } /* initialize filter iterator: */ if (!NI_InitFilterIterator(PyArray_NDIM(input), PyArray_DIMS(footprint), filter_size, PyArray_DIMS(input), origins, &fi)) { goto exit; } /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; NPY_BEGIN_THREADS; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = PyArray_SIZE(input); /* iterator over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (PyArray_TYPE(input)) { CASE_MIN_OR_MAX_POINT(NPY_BOOL, npy_bool, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_UBYTE, npy_ubyte, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_USHORT, npy_ushort, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_UINT, npy_uint, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_ULONG, npy_ulong, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_ULONGLONG, npy_ulonglong, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_BYTE, npy_byte, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_SHORT, npy_short, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_INT, npy_int, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_LONG, npy_long, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_LONGLONG, npy_longlong, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_FLOAT, npy_float, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); CASE_MIN_OR_MAX_POINT(NPY_DOUBLE, npy_double, pi, oo, filter_size, cvalue, minimum, tmp, border_flag_value, ss); default: err = 1; goto exit; } switch (PyArray_TYPE(output)) { CASE_FILTER_OUT(NPY_BOOL, npy_bool, po, tmp); CASE_FILTER_OUT(NPY_UBYTE, npy_ubyte, po, tmp); CASE_FILTER_OUT(NPY_USHORT, npy_ushort, po, tmp); CASE_FILTER_OUT(NPY_UINT, npy_uint, po, tmp); CASE_FILTER_OUT(NPY_ULONG, npy_ulong, po, tmp); CASE_FILTER_OUT(NPY_ULONGLONG, npy_ulonglong, po, tmp); CASE_FILTER_OUT(NPY_BYTE, npy_byte, po, tmp); CASE_FILTER_OUT(NPY_SHORT, npy_short, po, tmp); CASE_FILTER_OUT(NPY_INT, npy_int, po, tmp); CASE_FILTER_OUT(NPY_LONG, npy_long, po, tmp); CASE_FILTER_OUT(NPY_LONGLONG, npy_longlong, po, tmp); CASE_FILTER_OUT(NPY_FLOAT, npy_float, po, tmp); CASE_FILTER_OUT(NPY_DOUBLE, npy_double, po, tmp); default: err = 1; goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: NPY_END_THREADS; if (err == 1) { PyErr_SetString(PyExc_RuntimeError, "array type not supported"); } free(offsets); free(ss); return PyErr_Occurred() ? 0 : 1; }
int NI_GenericFilter(PyArrayObject* input, int (*function)(double*, npy_intp, double*, void*), void *data, PyArrayObject* footprint, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins) { npy_bool *pf = NULL; npy_intp fsize, jj, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; double *buffer = NULL; /* get the the footprint: */ fsize = PyArray_SIZE(footprint); pf = (npy_bool*)PyArray_DATA(footprint); for(jj = 0; jj < fsize; jj++) { if (pf[jj]) ++filter_size; } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, PyArray_DIMS(footprint), origins, mode, &offsets, &border_flag_value, NULL)) { goto exit; } /* initialize filter iterator: */ if (!NI_InitFilterIterator(PyArray_NDIM(input), PyArray_DIMS(footprint), filter_size, PyArray_DIMS(input), origins, &fi)) { goto exit; } /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = PyArray_SIZE(input); /* buffer for filter calculation: */ buffer = malloc(filter_size * sizeof(double)); if (!buffer) { PyErr_NoMemory(); goto exit; } /* iterate over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (PyArray_TYPE(input)) { CASE_FILTER_POINT(NPY_BOOL, npy_bool, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_UBYTE, npy_ubyte, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_USHORT, npy_ushort, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_UINT, npy_uint, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_ULONG, npy_ulong, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_ULONGLONG, npy_ulonglong, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_BYTE, npy_byte, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_SHORT, npy_short, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_INT, npy_int, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_LONG, npy_long, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_LONGLONG, npy_longlong, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_FLOAT, npy_float, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); CASE_FILTER_POINT(NPY_DOUBLE, npy_double, pi, oo, filter_size, cvalue, tmp, border_flag_value, function, data, buffer); default: PyErr_SetString(PyExc_RuntimeError, "array type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_FILTER_OUT(NPY_BOOL, npy_bool, po, tmp); CASE_FILTER_OUT(NPY_UBYTE, npy_ubyte, po, tmp); CASE_FILTER_OUT(NPY_USHORT, npy_ushort, po, tmp); CASE_FILTER_OUT(NPY_UINT, npy_uint, po, tmp); CASE_FILTER_OUT(NPY_ULONG, npy_ulong, po, tmp); CASE_FILTER_OUT(NPY_ULONGLONG, npy_ulonglong, po, tmp); CASE_FILTER_OUT(NPY_BYTE, npy_byte, po, tmp); CASE_FILTER_OUT(NPY_SHORT, npy_short, po, tmp); CASE_FILTER_OUT(NPY_INT, npy_int, po, tmp); CASE_FILTER_OUT(NPY_LONG, npy_long, po, tmp); CASE_FILTER_OUT(NPY_LONGLONG, npy_longlong, po, tmp); CASE_FILTER_OUT(NPY_FLOAT, npy_float, po, tmp); CASE_FILTER_OUT(NPY_DOUBLE, npy_double, po, tmp); default: PyErr_SetString(PyExc_RuntimeError, "array type not supported"); goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: free(offsets); free(buffer); return PyErr_Occurred() ? 0 : 1; }
int NI_Correlate(PyArrayObject* input, PyArrayObject* weights, PyArrayObject* output, NI_ExtendMode mode, double cvalue, npy_intp *origins) { npy_bool *pf = NULL; npy_intp fsize, jj, kk, filter_size = 0, border_flag_value; npy_intp *offsets = NULL, *oo, size; NI_FilterIterator fi; NI_Iterator ii, io; char *pi, *po; npy_double *pw; npy_double *ww = NULL; int err = 0; NPY_BEGIN_THREADS_DEF; /* get the the footprint: */ fsize = PyArray_SIZE(weights); pw = (npy_double*)PyArray_DATA(weights); pf = malloc(fsize * sizeof(npy_bool)); if (!pf) { PyErr_NoMemory(); goto exit; } for(jj = 0; jj < fsize; jj++) { if (fabs(pw[jj]) > DBL_EPSILON) { pf[jj] = 1; ++filter_size; } else { pf[jj] = 0; } } /* copy the weights to contiguous memory: */ ww = malloc(filter_size * sizeof(npy_double)); if (!ww) { PyErr_NoMemory(); goto exit; } jj = 0; for(kk = 0; kk < fsize; kk++) { if (pf[kk]) { ww[jj++] = pw[kk]; } } /* initialize filter offsets: */ if (!NI_InitFilterOffsets(input, pf, PyArray_DIMS(weights), origins, mode, &offsets, &border_flag_value, NULL)) { goto exit; } /* initialize filter iterator: */ if (!NI_InitFilterIterator(PyArray_NDIM(input), PyArray_DIMS(weights), filter_size, PyArray_DIMS(input), origins, &fi)) { goto exit; } /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; NPY_BEGIN_THREADS; /* get data pointers an array size: */ pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = PyArray_SIZE(input); /* iterator over the elements: */ oo = offsets; for(jj = 0; jj < size; jj++) { double tmp = 0.0; switch (PyArray_TYPE(input)) { CASE_CORRELATE_POINT(NPY_BOOL, npy_bool, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_UBYTE, npy_ubyte, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_USHORT, npy_ushort, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_UINT, npy_uint, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_ULONG, npy_ulong, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_ULONGLONG, npy_ulonglong, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_BYTE, npy_byte, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_SHORT, npy_short, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_INT, npy_int, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_LONG, npy_long, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_LONGLONG, npy_longlong, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_FLOAT, npy_float, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); CASE_CORRELATE_POINT(NPY_DOUBLE, npy_double, pi, ww, oo, filter_size, cvalue, tmp, border_flag_value); default: err = 1; goto exit; } switch (PyArray_TYPE(output)) { CASE_FILTER_OUT(NPY_BOOL, npy_bool, po, tmp); CASE_FILTER_OUT(NPY_UBYTE, npy_ubyte, po, tmp); CASE_FILTER_OUT(NPY_USHORT, npy_ushort, po, tmp); CASE_FILTER_OUT(NPY_UINT, npy_uint, po, tmp); CASE_FILTER_OUT(NPY_ULONG, npy_ulong, po, tmp); CASE_FILTER_OUT(NPY_ULONGLONG, npy_ulonglong, po, tmp); CASE_FILTER_OUT(NPY_BYTE, npy_byte, po, tmp); CASE_FILTER_OUT(NPY_SHORT, npy_short, po, tmp); CASE_FILTER_OUT(NPY_INT, npy_int, po, tmp); CASE_FILTER_OUT(NPY_LONG, npy_long, po, tmp); CASE_FILTER_OUT(NPY_LONGLONG, npy_longlong, po, tmp); CASE_FILTER_OUT(NPY_FLOAT, npy_float, po, tmp); CASE_FILTER_OUT(NPY_DOUBLE, npy_double, po, tmp); default: err = 1; goto exit; } NI_FILTER_NEXT2(fi, ii, io, oo, pi, po); } exit: NPY_END_THREADS; if (err == 1) { PyErr_SetString(PyExc_RuntimeError, "array type not supported"); } free(offsets); free(ww); free(pf); return PyErr_Occurred() ? 0 : 1; }
int NI_FindObjects(PyArrayObject* input, npy_intp max_label, npy_intp* regions) { npy_intp size, jj; NI_Iterator ii; char *pi; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; /* get input data, size and iterator: */ pi = (void *)PyArray_DATA(input); size = PyArray_SIZE(input); if (!NI_InitPointIterator(input, &ii)) goto exit; if (PyArray_NDIM(input) > 0) { for (jj = 0; jj < 2 * PyArray_NDIM(input) * max_label; jj++) { regions[jj] = -1; } } else { for(jj = 0; jj < max_label; jj++) regions[jj] = -1; } /* iterate over all points: */ for(jj = 0 ; jj < size; jj++) { switch (PyArray_TYPE(input)) { CASE_FIND_OBJECT_POINT(NPY_BOOL, npy_bool, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_UBYTE, npy_ubyte, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_USHORT, npy_ushort, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_UINT, npy_uint, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_ULONG, npy_ulong, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_ULONGLONG, npy_ulonglong, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_BYTE, npy_byte, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_SHORT, npy_short, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_INT, npy_int, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_LONG, npy_long, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_LONGLONG, npy_longlong, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_FLOAT, npy_float, pi, regions, input, max_label, ii); CASE_FIND_OBJECT_POINT(NPY_DOUBLE, npy_double, pi, regions, input, max_label, ii); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT(ii, pi); } exit: NPY_END_THREADS; return PyErr_Occurred() ? 0 : 1; }
int NI_WatershedIFT(PyArrayObject* input, PyArrayObject* markers, PyArrayObject* strct, PyArrayObject* output) { char *pl, *pm, *pi; int ll; npy_intp size, jj, hh, kk, maxval; npy_intp strides[WS_MAXDIM], coordinates[WS_MAXDIM]; npy_intp *nstrides = NULL, nneigh, ssize; int i_contiguous, o_contiguous; NI_WatershedElement *temp = NULL, **first = NULL, **last = NULL; npy_bool *ps = NULL; NI_Iterator mi, ii, li; NPY_BEGIN_THREADS_DEF; i_contiguous = PyArray_ISCONTIGUOUS(input); o_contiguous = PyArray_ISCONTIGUOUS(output); ssize = PyArray_SIZE(strct); if (PyArray_NDIM(input) > WS_MAXDIM) { PyErr_SetString(PyExc_RuntimeError, "too many dimensions"); goto exit; } size = PyArray_SIZE(input); /* Storage for the temporary queue data. */ temp = malloc(size * sizeof(NI_WatershedElement)); if (!temp) { PyErr_NoMemory(); goto exit; } NPY_BEGIN_THREADS; pi = (void *)PyArray_DATA(input); if (!NI_InitPointIterator(input, &ii)) goto exit; /* Initialization and find the maximum of the input. */ maxval = 0; for(jj = 0; jj < size; jj++) { npy_intp ival = 0; switch (PyArray_TYPE(input)) { CASE_GET_INPUT(NPY_UINT8, npy_uint8, ival, pi); CASE_GET_INPUT(NPY_UINT16, npy_uint16, ival, pi); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } temp[jj].index = jj; temp[jj].done = 0; if (ival > maxval) maxval = ival; NI_ITERATOR_NEXT(ii, pi); } pi = (void *)PyArray_DATA(input); /* Allocate and initialize the storage for the queue. */ first = malloc((maxval + 1) * sizeof(NI_WatershedElement*)); last = malloc((maxval + 1) * sizeof(NI_WatershedElement*)); if (NPY_UNLIKELY(!first || !last)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(hh = 0; hh <= maxval; hh++) { first[hh] = NULL; last[hh] = NULL; } if (!NI_InitPointIterator(markers, &mi)) goto exit; if (!NI_InitPointIterator(output, &li)) goto exit; pm = (void *)PyArray_DATA(markers); pl = (void *)PyArray_DATA(output); /* initialize all nodes */ for (ll = 0; ll < PyArray_NDIM(input); ll++) { coordinates[ll] = 0; } for(jj = 0; jj < size; jj++) { /* get marker */ int label = 0; switch (PyArray_TYPE(markers)) { CASE_GET_LABEL(NPY_UBYTE, npy_ubyte, label, pm); CASE_GET_LABEL(NPY_USHORT, npy_ushort, label, pm); CASE_GET_LABEL(NPY_UINT, npy_uint, label, pm); CASE_GET_LABEL(NPY_ULONG, npy_ulong, label, pm); CASE_GET_LABEL(NPY_ULONGLONG, npy_ulonglong, label, pm); CASE_GET_LABEL(NPY_BYTE, npy_byte, label, pm); CASE_GET_LABEL(NPY_SHORT, npy_short, label, pm); CASE_GET_LABEL(NPY_INT, npy_int, label, pm); CASE_GET_LABEL(NPY_LONG, npy_long, label, pm); CASE_GET_LABEL(NPY_LONGLONG, npy_longlong, label, pm); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_PUT_LABEL(NPY_UBYTE, npy_ubyte, label, pl); CASE_PUT_LABEL(NPY_USHORT, npy_ushort, label, pl); CASE_PUT_LABEL(NPY_UINT, npy_uint, label, pl); CASE_PUT_LABEL(NPY_ULONG, npy_ulong, label, pl); CASE_PUT_LABEL(NPY_ULONGLONG, npy_ulonglong, label, pl); CASE_PUT_LABEL(NPY_BYTE, npy_byte, label, pl); CASE_PUT_LABEL(NPY_SHORT, npy_short, label, pl); CASE_PUT_LABEL(NPY_INT, npy_int, label, pl); CASE_PUT_LABEL(NPY_LONG, npy_long, label, pl); CASE_PUT_LABEL(NPY_LONGLONG, npy_longlong, label, pl); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT2(mi, li, pm, pl); if (label != 0) { /* This node is a marker */ temp[jj].cost = 0; if (!first[0]) { first[0] = &(temp[jj]); first[0]->next = NULL; first[0]->prev = NULL; last[0] = first[0]; } else { if (label > 0) { /* object markers are enqueued at the beginning, so they are processed first. */ temp[jj].next = first[0]; temp[jj].prev = NULL; first[0]->prev = &(temp[jj]); first[0] = &(temp[jj]); } else { /* background markers are enqueued at the end, so they are processed after the object markers. */ temp[jj].next = NULL; temp[jj].prev = last[0]; last[0]->next = &(temp[jj]); last[0] = &(temp[jj]); } } } else { /* This node is not a marker */ temp[jj].cost = maxval + 1; temp[jj].next = NULL; temp[jj].prev = NULL; } for (ll = PyArray_NDIM(input) - 1; ll >= 0; ll--) { if (coordinates[ll] < PyArray_DIMS(input)[ll] - 1) { coordinates[ll]++; break; } else { coordinates[ll] = 0; } } } pl = (void *)PyArray_DATA(output); ps = (npy_bool*)PyArray_DATA(strct); nneigh = 0; for (kk = 0; kk < ssize; kk++) if (ps[kk] && kk != (ssize / 2)) ++nneigh; nstrides = malloc(nneigh * sizeof(npy_intp)); if (NPY_UNLIKELY(!nstrides)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } strides[PyArray_NDIM(input) - 1] = 1; for (ll = PyArray_NDIM(input) - 2; ll >= 0; ll--) { strides[ll] = PyArray_DIM(input, ll + 1) * strides[ll + 1]; } for (ll = 0; ll < PyArray_NDIM(input); ll++) { coordinates[ll] = -1; } for(kk = 0; kk < nneigh; kk++) nstrides[kk] = 0; jj = 0; for(kk = 0; kk < ssize; kk++) { if (ps[kk]) { int offset = 0; for (ll = 0; ll < PyArray_NDIM(input); ll++) { offset += coordinates[ll] * strides[ll]; } if (offset != 0) nstrides[jj++] += offset; } for (ll = PyArray_NDIM(input) - 1; ll >= 0; ll--) { if (coordinates[ll] < 1) { coordinates[ll]++; break; } else { coordinates[ll] = -1; } } } /* Propagation phase: */ for(jj = 0; jj <= maxval; jj++) { while (first[jj]) { /* dequeue first element: */ NI_WatershedElement *v = first[jj]; first[jj] = first[jj]->next; if (first[jj]) first[jj]->prev = NULL; v->prev = NULL; v->next = NULL; /* Mark element as done: */ v->done = 1; /* Iterate over the neighbors of the element: */ for(hh = 0; hh < nneigh; hh++) { npy_intp v_index = v->index, p_index = v->index, idx, cc; int qq, outside = 0; p_index += nstrides[hh]; /* check if the neighbor is within the extent of the array: */ idx = p_index; for (qq = 0; qq < PyArray_NDIM(input); qq++) { cc = idx / strides[qq]; if (cc < 0 || cc >= PyArray_DIM(input, qq)) { outside = 1; break; } idx -= cc * strides[qq]; } if (!outside) { NI_WatershedElement *p = &(temp[p_index]); if (!(p->done)) { /* If the neighbor was not processed yet: */ int max, pval, vval, wvp, pcost, label, p_idx, v_idx; switch (PyArray_TYPE(input)) { CASE_WINDEX1(NPY_UBYTE, npy_ubyte, v_index, p_index, strides, PyArray_STRIDES(input), PyArray_NDIM(input), i_contiguous, p_idx, v_idx, pi, vval, pval); CASE_WINDEX1(NPY_USHORT, npy_ushort, v_index, p_index, strides, PyArray_STRIDES(input), PyArray_NDIM(input), i_contiguous, p_idx, v_idx, pi, vval, pval); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* Calculate cost: */ wvp = pval - vval; if (wvp < 0) wvp = -wvp; /* Find the maximum of this cost and the current element cost: */ pcost = p->cost; max = v->cost > wvp ? v->cost : wvp; if (max < pcost) { /* If this maximum is less than the neighbors cost, adapt the cost and the label of the neighbor: */ int idx; p->cost = max; switch (PyArray_TYPE(output)) { CASE_WINDEX2(NPY_UBYTE, npy_ubyte, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_USHORT, npy_ushort, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_UINT, npy_uint, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_ULONG, npy_ulong, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_ULONGLONG, npy_ulonglong, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_BYTE, npy_byte, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_SHORT, npy_short, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_INT, npy_int, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_LONG, npy_long, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX2(NPY_LONGLONG, npy_longlong, v_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_WINDEX3(NPY_UBYTE, npy_ubyte, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_USHORT, npy_ushort, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_UINT, npy_uint, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_ULONG, npy_ulong, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_ULONGLONG, npy_ulonglong, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_BYTE, npy_byte, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_SHORT, npy_short, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_INT, npy_int, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_LONG, npy_long, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); CASE_WINDEX3(NPY_LONGLONG, npy_longlong, p_index, strides, PyArray_STRIDES(output), PyArray_NDIM(input), idx, o_contiguous, label, pl); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* If the neighbor is in a queue, remove it: */ if (p->next || p->prev) { NI_WatershedElement *prev = p->prev, *next = p->next; if (first[pcost] == p) first[pcost] = next; if (last[pcost] == p) last[pcost] = prev; if (prev) prev->next = next; if (next) next->prev = prev; } /* Insert the neighbor in the appropriate queue: */ if (label < 0) { p->prev = last[max]; p->next = NULL; if (last[max]) last[max]->next = p; last[max] = p; if (!first[max]) first[max] = p; } else { p->next = first[max]; p->prev = NULL; if (first[max]) first[max]->prev = p; first[max] = p; if (!last[max]) last[max] = p; } } } } } } } exit: NPY_END_THREADS; free(temp); free(first); free(last); free(nstrides); return PyErr_Occurred() ? 0 : 1; }
int NI_ZoomShift(PyArrayObject *input, PyArrayObject* zoom_ar, PyArrayObject* shift_ar, PyArrayObject *output, int order, int mode, double cval) { char *po, *pi; npy_intp **zeros = NULL, **offsets = NULL, ***edge_offsets = NULL; npy_intp ftmp[NPY_MAXDIMS], *fcoordinates = NULL, *foffsets = NULL; npy_intp jj, hh, kk, filter_size, odimensions[NPY_MAXDIMS]; npy_intp idimensions[NPY_MAXDIMS], istrides[NPY_MAXDIMS]; npy_intp size; double ***splvals = NULL; NI_Iterator io; npy_double *zooms = zoom_ar ? (npy_double*)PyArray_DATA(zoom_ar) : NULL; npy_double *shifts = shift_ar ? (npy_double*)PyArray_DATA(shift_ar) : NULL; int rank = 0; NPY_BEGIN_THREADS_DEF; NPY_BEGIN_THREADS; for (kk = 0; kk < PyArray_NDIM(input); kk++) { idimensions[kk] = PyArray_DIM(input, kk); istrides[kk] = PyArray_STRIDE(input, kk); odimensions[kk] = PyArray_DIM(output, kk); } rank = PyArray_NDIM(input); /* if the mode is 'constant' we need some temps later: */ if (mode == NI_EXTEND_CONSTANT) { zeros = malloc(rank * sizeof(npy_intp*)); if (NPY_UNLIKELY(!zeros)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) zeros[jj] = NULL; for(jj = 0; jj < rank; jj++) { zeros[jj] = malloc(odimensions[jj] * sizeof(npy_intp)); if (NPY_UNLIKELY(!zeros[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } } } /* store offsets, along each axis: */ offsets = malloc(rank * sizeof(npy_intp*)); /* store spline coefficients, along each axis: */ splvals = malloc(rank * sizeof(double**)); /* store offsets at all edges: */ edge_offsets = malloc(rank * sizeof(npy_intp**)); if (NPY_UNLIKELY(!offsets || !splvals || !edge_offsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) { offsets[jj] = NULL; splvals[jj] = NULL; edge_offsets[jj] = NULL; } for(jj = 0; jj < rank; jj++) { offsets[jj] = malloc(odimensions[jj] * sizeof(npy_intp)); splvals[jj] = malloc(odimensions[jj] * sizeof(double*)); edge_offsets[jj] = malloc(odimensions[jj] * sizeof(npy_intp*)); if (NPY_UNLIKELY(!offsets[jj] || !splvals[jj] || !edge_offsets[jj])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(hh = 0; hh < odimensions[jj]; hh++) { splvals[jj][hh] = NULL; edge_offsets[jj][hh] = NULL; } } /* precalculate offsets, and offsets at the edge: */ for(jj = 0; jj < rank; jj++) { double shift = 0.0, zoom = 0.0; if (shifts) shift = shifts[jj]; if (zooms) zoom = zooms[jj]; for(kk = 0; kk < odimensions[jj]; kk++) { double cc = (double)kk; if (shifts) cc += shift; if (zooms) cc *= zoom; cc = map_coordinate(cc, idimensions[jj], mode); if (cc > -1.0) { npy_intp start; if (zeros && zeros[jj]) zeros[jj][kk] = 0; if (order & 1) { start = (npy_intp)floor(cc) - order / 2; } else { start = (npy_intp)floor(cc + 0.5) - order / 2; } offsets[jj][kk] = istrides[jj] * start; if (start < 0 || start + order >= idimensions[jj]) { edge_offsets[jj][kk] = malloc((order + 1) * sizeof(npy_intp)); if (NPY_UNLIKELY(!edge_offsets[jj][kk])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(hh = 0; hh <= order; hh++) { npy_intp idx = start + hh; npy_intp len = idimensions[jj]; if (len <= 1) { idx = 0; } else { npy_intp s2 = 2 * len - 2; if (idx < 0) { idx = s2 * (npy_intp)(-idx / s2) + idx; idx = idx <= 1 - len ? idx + s2 : -idx; } else if (idx >= len) { idx -= s2 * (npy_intp)(idx / s2); if (idx >= len) idx = s2 - idx; } } edge_offsets[jj][kk][hh] = istrides[jj] * (idx - start); } } if (order > 0) { splvals[jj][kk] = malloc((order + 1) * sizeof(double)); if (NPY_UNLIKELY(!splvals[jj][kk])) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } spline_coefficients(cc, order, splvals[jj][kk]); } } else { zeros[jj][kk] = 1; } } } filter_size = 1; for(jj = 0; jj < rank; jj++) filter_size *= order + 1; if (!NI_InitPointIterator(output, &io)) goto exit; pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); /* store all coordinates and offsets with filter: */ fcoordinates = malloc(rank * filter_size * sizeof(npy_intp)); foffsets = malloc(filter_size * sizeof(npy_intp)); if (NPY_UNLIKELY(!fcoordinates || !foffsets)) { NPY_END_THREADS; PyErr_NoMemory(); goto exit; } for(jj = 0; jj < rank; jj++) ftmp[jj] = 0; kk = 0; for(hh = 0; hh < filter_size; hh++) { for(jj = 0; jj < rank; jj++) fcoordinates[jj + hh * rank] = ftmp[jj]; foffsets[hh] = kk; for(jj = rank - 1; jj >= 0; jj--) { if (ftmp[jj] < order) { ftmp[jj]++; kk += istrides[jj]; break; } else { ftmp[jj] = 0; kk -= istrides[jj] * order; } } } size = PyArray_SIZE(output); for(kk = 0; kk < size; kk++) { double t = 0.0; npy_intp edge = 0, oo = 0, zero = 0; for(hh = 0; hh < rank; hh++) { if (zeros && zeros[hh][io.coordinates[hh]]) { /* we use constant border condition */ zero = 1; break; } oo += offsets[hh][io.coordinates[hh]]; if (edge_offsets[hh][io.coordinates[hh]]) edge = 1; } if (!zero) { npy_intp *ff = fcoordinates; const int type_num = PyArray_TYPE(input); t = 0.0; for(hh = 0; hh < filter_size; hh++) { npy_intp idx = 0; double coeff = 0.0; if (NPY_UNLIKELY(edge)) { /* use precalculated edge offsets: */ for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj][io.coordinates[jj]]) idx += edge_offsets[jj][io.coordinates[jj]][ff[jj]]; else idx += ff[jj] * istrides[jj]; } idx += oo; } else { /* use normal offsets: */ idx += oo + foffsets[hh]; } switch (type_num) { CASE_INTERP_COEFF(NPY_BOOL, npy_bool, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UBYTE, npy_ubyte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_USHORT, npy_ushort, coeff, pi, idx); CASE_INTERP_COEFF(NPY_UINT, npy_uint, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONG, npy_ulong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_ULONGLONG, npy_ulonglong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_BYTE, npy_byte, coeff, pi, idx); CASE_INTERP_COEFF(NPY_SHORT, npy_short, coeff, pi, idx); CASE_INTERP_COEFF(NPY_INT, npy_int, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONG, npy_long, coeff, pi, idx); CASE_INTERP_COEFF(NPY_LONGLONG, npy_longlong, coeff, pi, idx); CASE_INTERP_COEFF(NPY_FLOAT, npy_float, coeff, pi, idx); CASE_INTERP_COEFF(NPY_DOUBLE, npy_double, coeff, pi, idx); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } /* calculate interpolated value: */ for(jj = 0; jj < rank; jj++) if (order > 0) coeff *= splvals[jj][io.coordinates[jj]][ff[jj]]; t += coeff; ff += rank; } } else { t = cval; } /* store output: */ switch (PyArray_TYPE(output)) { CASE_INTERP_OUT(NPY_BOOL, npy_bool, po, t); CASE_INTERP_OUT_UINT(UBYTE, npy_ubyte, po, t); CASE_INTERP_OUT_UINT(USHORT, npy_ushort, po, t); CASE_INTERP_OUT_UINT(UINT, npy_uint, po, t); CASE_INTERP_OUT_UINT(ULONG, npy_ulong, po, t); CASE_INTERP_OUT_UINT(ULONGLONG, npy_ulonglong, po, t); CASE_INTERP_OUT_INT(BYTE, npy_byte, po, t); CASE_INTERP_OUT_INT(SHORT, npy_short, po, t); CASE_INTERP_OUT_INT(INT, npy_int, po, t); CASE_INTERP_OUT_INT(LONG, npy_long, po, t); CASE_INTERP_OUT_INT(LONGLONG, npy_longlong, po, t); CASE_INTERP_OUT(NPY_FLOAT, npy_float, po, t); CASE_INTERP_OUT(NPY_DOUBLE, npy_double, po, t); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT(io, po); } exit: NPY_END_THREADS; if (zeros) { for(jj = 0; jj < rank; jj++) free(zeros[jj]); free(zeros); } if (offsets) { for(jj = 0; jj < rank; jj++) free(offsets[jj]); free(offsets); } if (splvals) { for(jj = 0; jj < rank; jj++) { if (splvals[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) free(splvals[jj][hh]); free(splvals[jj]); } } free(splvals); } if (edge_offsets) { for(jj = 0; jj < rank; jj++) { if (edge_offsets[jj]) { for(hh = 0; hh < odimensions[jj]; hh++) free(edge_offsets[jj][hh]); free(edge_offsets[jj]); } } free(edge_offsets); } free(foffsets); free(fcoordinates); return PyErr_Occurred() ? 0 : 1; }
int NI_FourierShift(PyArrayObject *input, PyArrayObject* shift_array, npy_intp n, int axis, PyArrayObject* output) { NI_Iterator ii, io; char *pi, *po; double *shifts = NULL, **params = NULL; npy_intp kk, hh, size; npy_double *ishifts = (void *)PyArray_DATA(shift_array); NPY_BEGIN_THREADS_DEF; /* precalculate the shifts: */ shifts = malloc(PyArray_NDIM(input) * sizeof(double)); if (!shifts) { PyErr_NoMemory(); goto exit; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { /* along the direction of the real transform we must use the given length of that dimensons, unless a complex transform is assumed (n < 0): */ int shape = kk == axis ? (n < 0 ? PyArray_DIM(input, kk) : n) : PyArray_DIM(input, kk); shifts[kk] = -2.0 * M_PI * *ishifts++ / (double)shape; } /* allocate memory for tables: */ params = malloc(PyArray_NDIM(input) * sizeof(double*)); if (!params) { PyErr_NoMemory(); goto exit; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { params[kk] = NULL; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { if (PyArray_DIM(input, kk) > 1) { params[kk] = malloc(PyArray_DIM(input, kk) * sizeof(double)); if (!params[kk]) { PyErr_NoMemory(); goto exit; } } } NPY_BEGIN_THREADS; for (hh = 0; hh < PyArray_NDIM(input); hh++) { if (params[hh]) { if (hh == axis && n >= 0) { for (kk = 0; kk < PyArray_DIM(input, hh); kk++) { params[hh][kk] = shifts[hh] * kk; } } else { int jj = 0; for (kk = 0; kk < (PyArray_DIM(input, hh) + 1) / 2; kk++) { params[hh][jj++] = shifts[hh] * kk; } for (kk = -(PyArray_DIM(input, hh) / 2); kk < 0; kk++) { params[hh][jj++] = shifts[hh] * kk; } } } } /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = PyArray_SIZE(input); /* iterator over the elements: */ for(hh = 0; hh < size; hh++) { double tmp = 0.0, sint, cost, r = 0.0, i = 0.0; for (kk = 0; kk < PyArray_NDIM(input); kk++) { if (params[kk]) tmp += params[kk][ii.coordinates[kk]]; } sint = sin(tmp); cost = cos(tmp); switch (PyArray_TYPE(input)) { CASE_FOURIER_SHIFT_R(NPY_BOOL, npy_bool, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_UBYTE, npy_ubyte, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_USHORT, npy_ushort, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_UINT, npy_uint, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_ULONG, npy_ulong, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_ULONGLONG, npy_ulonglong, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_BYTE, npy_byte, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_SHORT, npy_short, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_INT, npy_int, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_LONG, npy_long, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_LONGLONG, npy_longlong, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_FLOAT, npy_float, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_R(NPY_DOUBLE, npy_double, pi, tmp, r, i, cost, sint); CASE_FOURIER_SHIFT_C(NPY_CFLOAT, npy_cfloat, pi, r, i, cost, sint); CASE_FOURIER_SHIFT_C(NPY_CDOUBLE, npy_cdouble, pi, r, i, cost, sint); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_FOURIER_OUT_CC(NPY_CFLOAT, npy_cfloat, po, r, i); CASE_FOURIER_OUT_CC(NPY_CDOUBLE, npy_cdouble, po, r, i); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } NI_ITERATOR_NEXT2(ii, io, pi, po); } exit: NPY_END_THREADS; free(shifts); if (params) { for (kk = 0; kk < PyArray_NDIM(input); kk++) { free(params[kk]); } free(params); } return PyErr_Occurred() ? 0 : 1; }
int NI_FourierFilter(PyArrayObject *input, PyArrayObject* parameter_array, npy_intp n, int axis, PyArrayObject* output, int filter_type) { NI_Iterator ii, io; char *pi, *po; double *parameters = NULL, **params = NULL; npy_intp kk, hh, size; npy_double *iparameters = (void *)PyArray_DATA(parameter_array); NPY_BEGIN_THREADS_DEF; /* precalculate the parameters: */ parameters = malloc(PyArray_NDIM(input) * sizeof(double)); if (!parameters) { PyErr_NoMemory(); goto exit; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { /* along the direction of the real transform we must use the given length of that dimensons, unless a complex transform is assumed (n < 0): */ int shape = kk == axis ? (n < 0 ? PyArray_DIM(input, kk) : n) : PyArray_DIM(input, kk); switch (filter_type) { case _NI_GAUSSIAN: parameters[kk] = *iparameters++ * M_PI / (double)shape; parameters[kk] = -2.0 * parameters[kk] * parameters[kk]; break; case _NI_ELLIPSOID: case _NI_UNIFORM: parameters[kk] = *iparameters++; break; } } /* allocate memory for tables: */ params = malloc(PyArray_NDIM(input) * sizeof(double*)); if (!params) { PyErr_NoMemory(); goto exit; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { params[kk] = NULL; } for (kk = 0; kk < PyArray_NDIM(input); kk++) { if (PyArray_DIM(input, kk) > 1) { params[kk] = malloc(PyArray_DIM(input, kk) * sizeof(double)); if (!params[kk]) { PyErr_NoMemory(); goto exit; } } } NPY_BEGIN_THREADS; switch (filter_type) { case _NI_GAUSSIAN: /* calculate the tables of exponentials: */ for (hh = 0; hh < PyArray_NDIM(input); hh++) { if (params[hh]) { if (hh == axis && n >= 0) { for (kk = 0; kk < PyArray_DIM(input, hh); kk++) { double tmp = parameters[hh] * kk * kk; params[hh][kk] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); } } else { const npy_intp dim = PyArray_DIM(input, hh); int jj = 0; for (kk = 0; kk < (dim + 1) / 2; kk++) { double tmp = parameters[hh] * kk * kk; params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); } for (kk = -(dim / 2); kk < 0; kk++) { double tmp = parameters[hh] * kk * kk; params[hh][jj++] = fabs(tmp) > 50.0 ? 0.0 : exp(tmp); } } } } break; case _NI_UNIFORM: /* calculate the tables of parameters: */ for (hh = 0; hh < PyArray_NDIM(input); hh++) { if (params[hh]) { params[hh][0] = 1.0; if (hh == axis && n >= 0) { double tmp = M_PI * parameters[hh] / n; for (kk = 1; kk < PyArray_DIM(input, hh); kk++) { params[hh][kk] = tmp > 0.0 ? sin(tmp * kk) / (tmp * kk) : 0.0; } } else { const npy_intp dim = PyArray_DIM(input, hh); double tmp = M_PI * parameters[hh] / dim; int jj = 1; for (kk = 1; kk < (dim + 1) / 2; kk++) { params[hh][jj++] = tmp > 0.0 ? sin(tmp * kk) / (tmp * kk) : 0.0; } for (kk = -(dim / 2); kk < 0; kk++) { params[hh][jj++] = tmp > 0.0 ? sin(tmp * kk) / (tmp * kk) : 0.0; } } } } break; case _NI_ELLIPSOID: /* calculate the tables of parameters: */ for (hh = 0; hh < PyArray_NDIM(input); hh++) { if (params[hh]) { params[hh][0] = 1.0; if (hh == axis && n >= 0) { double tmp = M_PI * parameters[hh] / n; for (kk = 0; kk < PyArray_DIM(input, hh); kk++) { params[hh][kk] = (double)kk * tmp; } } else { const npy_intp dim = PyArray_DIM(input, hh); double tmp = M_PI * parameters[hh] / dim; int jj = 0; for(kk = 0; kk < (dim + 1) / 2; kk++) { params[hh][jj++] = (double)kk * tmp; } for(kk = -(dim / 2); kk < 0; kk++) { params[hh][jj++] = (double)kk * tmp; } } } else if (PyArray_DIM(input, hh) > 0) { params[hh][0] = 1.0; } } if (PyArray_NDIM(input) > 1) for(hh = 0; hh < PyArray_NDIM(input); hh++) for(kk = 0; kk < PyArray_DIM(input, hh); kk++) { params[hh][kk] *= params[hh][kk]; } break; default: break; } /* initialize input element iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* initialize output element iterator: */ if (!NI_InitPointIterator(output, &io)) goto exit; pi = (void *)PyArray_DATA(input); po = (void *)PyArray_DATA(output); size = PyArray_SIZE(input); /* iterator over the elements: */ for(hh = 0; hh < size; hh++) { double tmp = 1.0; switch (filter_type) { case _NI_GAUSSIAN: case _NI_UNIFORM: for (kk = 0; kk < PyArray_NDIM(input); kk++) { if (params[kk]) tmp *= params[kk][ii.coordinates[kk]]; } break; case _NI_ELLIPSOID: switch (PyArray_NDIM(input)) { case 1: tmp = params[0][ii.coordinates[0]]; tmp = tmp > 0.0 ? sin(tmp) / (tmp) : 1.0; break; case 2: tmp = 0.0; for(kk = 0; kk < 2; kk++) tmp += params[kk][ii.coordinates[kk]]; tmp = sqrt(tmp); tmp = tmp > 0.0 ? 2.0 * _bessel_j1(tmp) / tmp : 1.0; break; case 3: { double r = 0.0; for(kk = 0; kk < 3; kk++) r += params[kk][ii.coordinates[kk]]; r = sqrt(r); if (r > 0.0) { tmp = 3.0 * (sin(r) - r * cos(r)); tmp /= r * r * r; } else { tmp = 1.0; } } break; } break; default: break; } if (PyArray_TYPE(input) == NPY_CFLOAT || PyArray_TYPE(input) == NPY_CDOUBLE) { double tmp_r = 0.0, tmp_i = 0.0; switch (PyArray_TYPE(input)) { CASE_FOURIER_FILTER_RC(NPY_CFLOAT, npy_cfloat, pi, tmp, tmp_r, tmp_i); CASE_FOURIER_FILTER_RC(NPY_CDOUBLE, npy_cdouble, pi, tmp, tmp_r, tmp_i); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_FOURIER_OUT_CC(NPY_CFLOAT, npy_cfloat, po, tmp_r, tmp_i); CASE_FOURIER_OUT_CC(NPY_CDOUBLE, npy_cdouble, po, tmp_r, tmp_i); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } } else { switch (PyArray_TYPE(input)) { CASE_FOURIER_FILTER_RR(NPY_BOOL, npy_bool, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_UBYTE, npy_ubyte, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_USHORT, npy_ushort, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_UINT, npy_uint, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_ULONG, npy_ulong, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_ULONGLONG, npy_ulonglong, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_BYTE, npy_byte, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_SHORT, npy_short, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_INT, npy_int, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_LONG, npy_long, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_LONGLONG, npy_longlong, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_FLOAT, npy_float, pi, tmp); CASE_FOURIER_FILTER_RR(NPY_DOUBLE, npy_double, pi, tmp); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } switch (PyArray_TYPE(output)) { CASE_FOURIER_OUT_RR(NPY_FLOAT, npy_float, po, tmp); CASE_FOURIER_OUT_RR(NPY_DOUBLE, npy_double, po, tmp); CASE_FOURIER_OUT_RC(NPY_CFLOAT, npy_cfloat, po, tmp); CASE_FOURIER_OUT_RC(NPY_CDOUBLE, npy_cdouble, po, tmp); default: NPY_END_THREADS; PyErr_SetString(PyExc_RuntimeError, "data type not supported"); goto exit; } } NI_ITERATOR_NEXT2(ii, io, pi, po); } exit: NPY_END_THREADS; free(parameters); if (params) { for (kk = 0; kk < PyArray_NDIM(input); kk++) { free(params[kk]); } free(params); } return PyErr_Occurred() ? 0 : 1; }
int NI_Histogram(PyArrayObject *input, PyArrayObject *labels, npy_intp min_label, npy_intp max_label, npy_intp *indices, npy_intp n_results, PyArrayObject **histograms, double min, double max, npy_intp nbins) { char *pi = NULL, *pm = NULL; NI_Iterator ii, mi; npy_intp jj, kk, size, idx = 0, label = 1, doit = 1; Int32 **ph = NULL; double bsize; int qq; NPY_BEGIN_THREADS_DEF; /* input iterator: */ if (!NI_InitPointIterator(input, &ii)) goto exit; /* input data: */ pi = (void *)PyArray_DATA(input); if (labels) { if (!NI_InitPointIterator(labels, &mi)) goto exit; pm = (void *)PyArray_DATA(labels); } ph = (Int32**)malloc(n_results * sizeof(Int32*)); if (!ph) { PyErr_NoMemory(); goto exit; } NPY_BEGIN_THREADS; for(jj = 0; jj < n_results; jj++) { ph[jj] = (Int32*)PyArray_DATA(histograms[jj]); for(kk = 0; kk < nbins; kk++) ph[jj][kk] = 0; } bsize = (max - min) / (double)nbins; /* input size: */ size = 1; for(qq = 0; qq < input->nd; qq++) size *= input->dimensions[qq]; /* iterate over array: */ for(jj = 0; jj < size; jj++) { NI_GET_LABEL(pm, label, NI_NormalizeType(labels->descr->type_num)); if (min_label >= 0) { if (label >= min_label && label <= max_label) { idx = indices[label - min_label]; doit = idx >= 0; } else { doit = 0; } } else { doit = label != 0; } if (doit) { npy_intp bin; double val; NI_GET_VALUE(pi, val, NI_NormalizeType(input->descr->type_num)); if (val >= min && val < max) { bin = (npy_intp)((val - min) / bsize); ++(ph[idx][bin]); } } if (labels) { NI_ITERATOR_NEXT2(ii, mi, pi, pm); } else { NI_ITERATOR_NEXT(ii, pi); } } exit: NPY_END_THREADS; free(ph); return PyErr_Occurred() == NULL; }