int NI_GenericFilter1D(PyArrayObject *input, int (*function)(double*, npy_intp, double*, npy_intp, void*), void* data, npy_intp filter_size, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, npy_intp origin) { int more; npy_intp ii, lines, length, size1, size2; double *ibuffer = NULL, *obuffer = NULL; NI_LineBuffer iline_buffer, oline_buffer; /* allocate and initialize the line buffers: */ size1 = filter_size / 2; size2 = filter_size - size1 - 1; lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; length = input->nd > 0 ? input->dimensions[axis] : 1; /* iterate over all the array lines: */ do { char errmsg[NI_MAX_ERR_MSG]; /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more, errmsg)) { PyErr_SetString(PyExc_RuntimeError, errmsg); goto exit; } /* iterate over the lines in the buffers: */ for(ii = 0; ii < lines; ii++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, ii); double *oline = NI_GET_LINE(oline_buffer, ii); if (!function(iline, length + size1 + size2, oline, length, data)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "unknown error in line processing function"); goto exit; } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer, errmsg)) { PyErr_SetString(PyExc_RuntimeError, errmsg); goto exit; } } while(more); exit: if (ibuffer) free(ibuffer); if (obuffer) free(obuffer); return PyErr_Occurred() ? 0 : 1; }
/* one-dimensional spline filter: */ int NI_SplineFilter1D(PyArrayObject *input, int order, int axis, PyArrayObject *output) { int hh, npoles = 0, more; npy_intp kk, ll, lines, len; double *buffer = NULL, weight, pole[2]; NI_LineBuffer iline_buffer, oline_buffer; NPY_BEGIN_THREADS_DEF; len = PyArray_NDIM(input) > 0 ? PyArray_DIM(input, axis) : 1; if (len < 1) goto exit; /* these are used in the spline filter calculation below: */ switch (order) { case 2: npoles = 1; pole[0] = sqrt(8.0) - 3.0; break; case 3: npoles = 1; pole[0] = sqrt(3.0) - 2.0; break; case 4: npoles = 2; pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0; pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0; break; case 5: npoles = 2; pole[0] = sqrt(67.5 - sqrt(4436.25)) + sqrt(26.25) - 6.5; pole[1] = sqrt(67.5 + sqrt(4436.25)) - sqrt(26.25) - 6.5; break; default: break; } weight = 1.0; for(hh = 0; hh < npoles; hh++) weight *= (1.0 - pole[hh]) * (1.0 - 1.0 / pole[hh]); /* allocate an initialize the line buffer, only a single one is used, because the calculation is in-place: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, 0, 0, &lines, BUFFER_SIZE, &buffer)) goto exit; if (!NI_InitLineBuffer(input, axis, 0, 0, lines, buffer, NI_EXTEND_DEFAULT, 0.0, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, buffer, NI_EXTEND_DEFAULT, 0.0, &oline_buffer)) goto exit; NPY_BEGIN_THREADS; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) { goto exit; } /* iterate over the lines in the buffer: */ for(kk = 0; kk < lines; kk++) { /* get line: */ double *ln = NI_GET_LINE(iline_buffer, kk); /* spline filter: */ if (len > 1) { for(ll = 0; ll < len; ll++) ln[ll] *= weight; for(hh = 0; hh < npoles; hh++) { double p = pole[hh]; int max = (int)ceil(log(TOLERANCE) / log(fabs(p))); if (max < len) { double zn = p; double sum = ln[0]; for(ll = 1; ll < max; ll++) { sum += zn * ln[ll]; zn *= p; } ln[0] = sum; } else { double zn = p; double iz = 1.0 / p; double z2n = pow(p, (double)(len - 1)); double sum = ln[0] + z2n * ln[len - 1]; z2n *= z2n * iz; for(ll = 1; ll <= len - 2; ll++) { sum += (zn + z2n) * ln[ll]; zn *= p; z2n *= iz; } ln[0] = sum / (1.0 - zn * zn); } for(ll = 1; ll < len; ll++) ln[ll] += p * ln[ll - 1]; ln[len-1] = (p / (p * p - 1.0)) * (ln[len-1] + p * ln[len-2]); for(ll = len - 2; ll >= 0; ll--) ln[ll] = p * (ln[ll + 1] - ln[ll]); } } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer)) { goto exit; } } while(more); exit: NPY_END_THREADS; free(buffer); return PyErr_Occurred() ? 0 : 1; }
int NI_Correlate1D(PyArrayObject *input, PyArrayObject *weights, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, npy_intp origin) { int symmetric = 0, more; npy_intp ii, jj, ll, lines, length, size1, size2, filter_size; double *ibuffer = NULL, *obuffer = NULL; Float64 *fw; NI_LineBuffer iline_buffer, oline_buffer; char errmsg[NI_MAX_ERR_MSG]; NPY_BEGIN_THREADS_DEF; errmsg[0] = 0; /* test for symmetry or anti-symmetry: */ filter_size = weights->dimensions[0]; size1 = filter_size / 2; size2 = filter_size - size1 - 1; fw = (void *)PyArray_DATA(weights); if (filter_size & 0x1) { symmetric = 1; for(ii = 1; ii <= filter_size / 2; ii++) { if (fabs(fw[ii + size1] - fw[size1 - ii]) > DBL_EPSILON) { symmetric = 0; break; } } if (symmetric == 0) { symmetric = -1; for(ii = 1; ii <= filter_size / 2; ii++) { if (fabs(fw[size1 + ii] + fw[size1 - ii]) > DBL_EPSILON) { symmetric = 0; break; } } } } /* allocate and initialize the line buffers: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; NPY_BEGIN_THREADS; length = input->nd > 0 ? input->dimensions[axis] : 1; fw += size1; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more, errmsg)) goto exit; /* iterate over the lines in the buffers: */ for(ii = 0; ii < lines; ii++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, ii) + size1; double *oline = NI_GET_LINE(oline_buffer, ii); /* the correlation calculation: */ if (symmetric > 0) { for(ll = 0; ll < length; ll++) { oline[ll] = iline[0] * fw[0]; for(jj = -size1 ; jj < 0; jj++) oline[ll] += (iline[jj] + iline[-jj]) * fw[jj]; ++iline; } } else if (symmetric < 0) { for(ll = 0; ll < length; ll++) { oline[ll] = iline[0] * fw[0]; for(jj = -size1 ; jj < 0; jj++) oline[ll] += (iline[jj] - iline[-jj]) * fw[jj]; ++iline; } } else { for(ll = 0; ll < length; ll++) { oline[ll] = iline[size2] * fw[size2]; for(jj = -size1; jj < size2; jj++) oline[ll] += iline[jj] * fw[jj]; ++iline; } } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer, errmsg)) goto exit; } while(more); exit: NPY_END_THREADS; if (errmsg[0] != 0) { PyErr_SetString(PyExc_RuntimeError, errmsg); } if (ibuffer) free(ibuffer); if (obuffer) free(obuffer); return PyErr_Occurred() ? 0 : 1; }
int NI_MinOrMaxFilter1D(PyArrayObject *input, npy_intp filter_size, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, npy_intp origin, int minimum) { npy_intp lines, kk, ll, length, size1, size2; int more; double *ibuffer = NULL, *obuffer = NULL; NI_LineBuffer iline_buffer, oline_buffer; char errmsg[NI_MAX_ERR_MSG]; NPY_BEGIN_THREADS_DEF; errmsg[0] = 0; struct pairs { double value; npy_intp death; } *ring = NULL, *minpair, *end, *last; size1 = filter_size / 2; size2 = filter_size - size1 - 1; /* allocate and initialize the line buffers: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; NPY_BEGIN_THREADS; length = input->nd > 0 ? input->dimensions[axis] : 1; /* ring is a dequeue of pairs implemented as a circular array */ ring = malloc(filter_size * sizeof(struct pairs)); if (!ring) { goto exit; } end = ring + filter_size; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more, errmsg)) goto exit; /* iterate over the lines in the buffers: */ for(kk = 0; kk < lines; kk++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, kk); double *oline = NI_GET_LINE(oline_buffer, kk); /* This check could be moved out to the Python wrapper */ if (filter_size == 1) { memcpy(oline, iline, sizeof(double) * length); } else { /* * Original code by Richard Harter, adapted from: * http://www.richardhartersworld.com/cri/2001/slidingmin.html */ minpair = ring; minpair->value = *iline++; minpair->death = filter_size; last = ring; for (ll = 1; ll < filter_size + length - 1; ll++) { double val = *iline++; if (minpair->death == ll) { INCREASE_RING_PTR(minpair) } if ((minimum && val <= minpair->value) || (!minimum && val >= minpair->value)) { minpair->value = val; minpair->death = ll + filter_size; last = minpair; } else { while ((minimum && last->value >= val) || (!minimum && last->value <= val)) { DECREASE_RING_PTR(last) } INCREASE_RING_PTR(last) last->value = val; last->death = ll + filter_size; } if (ll >= filter_size - 1) { *oline++ = minpair->value; } } } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer, errmsg)) goto exit; } while(more); exit: NPY_END_THREADS; if (errmsg[0] != 0) { PyErr_SetString(PyExc_RuntimeError, errmsg); } if (ibuffer) free(ibuffer); if (obuffer) free(obuffer); if (ring) free(ring); return PyErr_Occurred() ? 0 : 1; }
int NI_UniformFilter1D(PyArrayObject *input, npy_intp filter_size, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, npy_intp origin) { npy_intp lines, kk, ll, length, size1, size2; int more; double *ibuffer = NULL, *obuffer = NULL; NI_LineBuffer iline_buffer, oline_buffer; char errmsg[NI_MAX_ERR_MSG]; NPY_BEGIN_THREADS_DEF; errmsg[0] = 0; size1 = filter_size / 2; size2 = filter_size - size1 - 1; /* allocate and initialize the line buffers: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; NPY_BEGIN_THREADS; length = input->nd > 0 ? input->dimensions[axis] : 1; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more, errmsg)) goto exit; /* iterate over the lines in the buffers: */ for(kk = 0; kk < lines; kk++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, kk); double *oline = NI_GET_LINE(oline_buffer, kk); /* do the uniform filter: */ double tmp = 0.0; double *l1 = iline; double *l2 = iline + filter_size; for(ll = 0; ll < filter_size; ll++) tmp += iline[ll]; tmp /= (double)filter_size; oline[0] = tmp; for(ll = 1; ll < length; ll++) { tmp += (*l2++ - *l1++) / (double)filter_size; oline[ll] = tmp; } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer, errmsg)) goto exit; } while(more); exit: NPY_END_THREADS; if (errmsg[0] != 0) { PyErr_SetString(PyExc_RuntimeError, errmsg); } if (ibuffer) free(ibuffer); if (obuffer) free(obuffer); return PyErr_Occurred() ? 0 : 1; }
int NI_MinOrMaxFilter1D(PyArrayObject *input, long filter_size, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, long origin, int minimum) { maybelong lines, kk, jj, ll, length, size1, size2; int more; double *ibuffer = NULL, *obuffer = NULL; NI_LineBuffer iline_buffer, oline_buffer; size1 = filter_size / 2; size2 = filter_size - size1 - 1; /* allocate and initialize the line buffers: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; length = input->nd > 0 ? input->dimensions[axis] : 1; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) goto exit; /* iterate over the lines in the buffers: */ for(kk = 0; kk < lines; kk++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, kk) + size1; double *oline = NI_GET_LINE(oline_buffer, kk); for(ll = 0; ll < length; ll++) { /* find minimum or maximum filter: */ double val = iline[ll - size1]; for(jj = -size1 + 1; jj <= size2; jj++) { double tmp = iline[ll + jj]; if (minimum) { if (tmp < val) val = tmp; } else { if (tmp > val) val = tmp; } } oline[ll] = val; } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer)) goto exit; } while(more); exit: if (ibuffer) free(ibuffer); if (obuffer) free(obuffer); return PyErr_Occurred() ? 0 : 1; }
int NI_UniformFilter1D(PyArrayObject *input, npy_intp filter_size, int axis, PyArrayObject *output, NI_ExtendMode mode, double cval, npy_intp origin) { npy_intp lines, kk, ll, length, size1, size2; int more; double *ibuffer = NULL, *obuffer = NULL; NI_LineBuffer iline_buffer, oline_buffer; NPY_BEGIN_THREADS_DEF; size1 = filter_size / 2; size2 = filter_size - size1 - 1; /* allocate and initialize the line buffers: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, size1 + origin, size2 - origin, &lines, BUFFER_SIZE, &ibuffer)) goto exit; if (!NI_AllocateLineBuffer(output, axis, 0, 0, &lines, BUFFER_SIZE, &obuffer)) goto exit; if (!NI_InitLineBuffer(input, axis, size1 + origin, size2 - origin, lines, ibuffer, mode, cval, &iline_buffer)) goto exit; if (!NI_InitLineBuffer(output, axis, 0, 0, lines, obuffer, mode, 0.0, &oline_buffer)) goto exit; NPY_BEGIN_THREADS; length = PyArray_NDIM(input) > 0 ? PyArray_DIM(input, axis) : 1; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) { goto exit; } /* iterate over the lines in the buffers: */ for(kk = 0; kk < lines; kk++) { /* get lines: */ double *iline = NI_GET_LINE(iline_buffer, kk); double *oline = NI_GET_LINE(oline_buffer, kk); /* do the uniform filter: */ double tmp = 0.0; double *l1 = iline; double *l2 = iline + filter_size; for (ll = 0; ll < filter_size; ++ll) { tmp += iline[ll]; } oline[0] = tmp / filter_size; for (ll = 1; ll < length; ++ll) { tmp += *l2++ - *l1++; oline[ll] = tmp / filter_size; } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer)) { goto exit; } } while(more); exit: NPY_END_THREADS; free(ibuffer); free(obuffer); return PyErr_Occurred() ? 0 : 1; }
/* one-dimensional spline filter: */ int NI_SplineFilter1D(PyArrayObject *input, int order, int axis, NI_ExtendMode mode, PyArrayObject *output) { int npoles = 0, more; npy_intp kk, lines, len; double *buffer = NULL, poles[MAX_SPLINE_FILTER_POLES]; NI_LineBuffer iline_buffer, oline_buffer; NPY_BEGIN_THREADS_DEF; len = PyArray_NDIM(input) > 0 ? PyArray_DIM(input, axis) : 1; if (len < 1) goto exit; /* these are used in the spline filter calculation below: */ if (get_filter_poles(order, &npoles, poles)) { goto exit; } /* allocate an initialize the line buffer, only a single one is used, because the calculation is in-place: */ lines = -1; if (!NI_AllocateLineBuffer(input, axis, 0, 0, &lines, BUFFER_SIZE, &buffer)) { goto exit; } if (!NI_InitLineBuffer(input, axis, 0, 0, lines, buffer, NI_EXTEND_DEFAULT, 0.0, &iline_buffer)) { goto exit; } if (!NI_InitLineBuffer(output, axis, 0, 0, lines, buffer, NI_EXTEND_DEFAULT, 0.0, &oline_buffer)) { goto exit; } NPY_BEGIN_THREADS; /* iterate over all the array lines: */ do { /* copy lines from array to buffer: */ if (!NI_ArrayToLineBuffer(&iline_buffer, &lines, &more)) { goto exit; } /* iterate over the lines in the buffer: */ for(kk = 0; kk < lines; kk++) { /* get line: */ double *ln = NI_GET_LINE(iline_buffer, kk); /* spline filter: */ if (len > 1) { apply_filter(ln, len, poles, npoles, mode); } } /* copy lines from buffer to array: */ if (!NI_LineBufferToArray(&oline_buffer)) { goto exit; } } while(more); exit: NPY_END_THREADS; free(buffer); return PyErr_Occurred() ? 0 : 1; }