Esempio n. 1
0
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;
}
Esempio n. 2
0
/* 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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/* 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;
}