Exemple #1
0
static PyObject*
libtfr_stft(PyObject *self, PyObject *args)
{
        /* arguments */
        PyObject *o = NULL;
        PyArrayObject *signal = NULL;
        PyArrayObject *signal_cast = NULL;
        PyObject *o2 = NULL;
        PyArrayObject *window = NULL;
        int step;
        int N = 0;
        int Npoints, Ntapers;

        /* output data */
        npy_intp out_shape[3];
        PyArrayObject *outdata = NULL;
        int do_complex = 0;
        double *spec;
        complex double *zspec_tmp;
        npy_cdouble *zspec;

        /* internal stuff */
        mfft *mtmh;
        double *samples = NULL;
        double *windowp;

        /* parse arguments */
        if (!PyArg_ParseTuple(args, "OOi|ii", &o, &o2, &step, &N, &do_complex))
                return NULL;
        signal = (PyArrayObject*) PyArray_FromAny(o, NULL, 1, 1, NPY_CONTIGUOUS, NULL);
        if (signal==NULL) {
                PyErr_SetString(PyExc_TypeError, "Input signal must be an ndarray");
                return NULL;
        }
        window = (PyArrayObject*) PyArray_FromAny(o2, NULL, 1, 2, NPY_CONTIGUOUS, NULL);
        if (window==NULL) {
                PyErr_SetString(PyExc_TypeError, "Window must be a 1D or 2D ndarray");
                goto fail;
        }
        /* determine dimensions of window */
        if (PyArray_NDIM(window)==1) {
                Ntapers = 1;
                Npoints = PyArray_DIM(window, 0);
        }
        else {
                Ntapers = PyArray_DIM(window, 0);
                Npoints = PyArray_DIM(window, 1);
        }

        /* coerce data to proper type */
        samples = coerce_ndarray_double(signal, &signal_cast);
        if (samples==NULL) {
                PyErr_SetString(PyExc_TypeError, "Unable to cast signal to supported data type");
                goto fail;
        }
        /* need to copy the window function b/c mtm_destroy() will demalloc it */
        if (PyArray_TYPE(window)!=NPY_DOUBLE) {
                PyErr_SetString(PyExc_TypeError, "Window function must be double precision float");
                goto fail;
        }
        windowp = malloc(Npoints * Ntapers * sizeof(double));
        memcpy(windowp, PyArray_DATA(window), Npoints * Ntapers * sizeof(double));

        /* allocate outputs and do the transform */
        if (N < 1)
                N = Npoints;
        mtmh = mtm_init(N, Npoints, Ntapers, windowp, NULL);
        out_shape[0] = N/2+1;
        if (do_complex) {
                out_shape[1] = Ntapers;
                out_shape[2] = SPEC_NFRAMES(mtmh, PyArray_SIZE(signal), step);
                outdata  = (PyArrayObject*) PyArray_ZEROS(3,out_shape,NPY_CDOUBLE,1); // fortran-order
                zspec = (npy_cdouble*) PyArray_DATA(outdata);
                //printf("output dimensions: %d, %d, %d\n", out_shape[0], out_shape[1], out_shape[2]);
                zspec_tmp = (complex double*)malloc(PyArray_SIZE(outdata) * sizeof(complex double));
                mtm_zspec(mtmh, zspec_tmp, samples, PyArray_SIZE(signal), step);
                cmplx_c99tonpy(zspec_tmp, zspec, PyArray_SIZE(outdata));
                free(zspec_tmp);
        }
        else {
                out_shape[1] = SPEC_NFRAMES(mtmh, PyArray_SIZE(signal), step);
                outdata  = (PyArrayObject*) PyArray_ZEROS(2,out_shape,NPY_DOUBLE,1); // fortran-order
                spec = (double*) PyArray_DATA(outdata);
                mtm_spec(mtmh, spec, samples, PyArray_SIZE(signal), step, 0);
        }
        mtm_destroy(mtmh);

        Py_DECREF(signal);
        Py_DECREF(window);
        Py_XDECREF(signal_cast);
        return PyArray_Return(outdata);
fail:
        Py_XDECREF(signal_cast);
        Py_XDECREF(signal);
        Py_XDECREF(window);
        Py_XDECREF(outdata);
        return NULL;
}
Exemple #2
0
NPY_NO_EXPORT PyObject *
__New_PyArray_Std(PyArrayObject *self, int axis, int rtype, PyArrayObject *out,
                  int variance, int num)
{
    PyObject *obj1 = NULL, *obj2 = NULL, *obj3 = NULL;
    PyArrayObject *arr1 = NULL, *arr2 = NULL, *arrnew = NULL;
    PyObject *ret = NULL, *newshape = NULL;
    int i, n;
    npy_intp val;

    arrnew = (PyArrayObject *)PyArray_CheckAxis(self, &axis, 0);
    if (arrnew == NULL) {
        return NULL;
    }
    /* Compute and reshape mean */
    arr1 = (PyArrayObject *)PyArray_EnsureAnyArray(
                    PyArray_Mean(arrnew, axis, rtype, NULL));
    if (arr1 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    n = PyArray_NDIM(arrnew);
    newshape = PyTuple_New(n);
    if (newshape == NULL) {
        Py_DECREF(arr1);
        Py_DECREF(arrnew);
        return NULL;
    }
    for (i = 0; i < n; i++) {
        if (i == axis) {
            val = 1;
        }
        else {
            val = PyArray_DIM(arrnew,i);
        }
        PyTuple_SET_ITEM(newshape, i, PyInt_FromLong((long)val));
    }
    arr2 = (PyArrayObject *)PyArray_Reshape(arr1, newshape);
    Py_DECREF(arr1);
    Py_DECREF(newshape);
    if (arr2 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }

    /* Compute x = x - mx */
    arr1 = (PyArrayObject *)PyArray_EnsureAnyArray(
                PyNumber_Subtract((PyObject *)arrnew, (PyObject *)arr2));
    Py_DECREF(arr2);
    if (arr1 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    /* Compute x * x */
    if (PyArray_ISCOMPLEX(arr1)) {
        obj3 = PyArray_Conjugate(arr1, NULL);
    }
    else {
        obj3 = (PyObject *)arr1;
        Py_INCREF(arr1);
    }
    if (obj3 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    arr2 = (PyArrayObject *)PyArray_EnsureAnyArray(
                PyArray_GenericBinaryFunction(arr1, obj3, n_ops.multiply));
    Py_DECREF(arr1);
    Py_DECREF(obj3);
    if (arr2 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    if (PyArray_ISCOMPLEX(arr2)) {
        obj3 = PyObject_GetAttrString((PyObject *)arr2, "real");
        switch(rtype) {
        case NPY_CDOUBLE:
            rtype = NPY_DOUBLE;
            break;
        case NPY_CFLOAT:
            rtype = NPY_FLOAT;
            break;
        case NPY_CLONGDOUBLE:
            rtype = NPY_LONGDOUBLE;
            break;
        }
    }
    else {
        obj3 = (PyObject *)arr2;
        Py_INCREF(arr2);
    }
    if (obj3 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    /* Compute add.reduce(x*x,axis) */
    obj1 = PyArray_GenericReduceFunction((PyArrayObject *)obj3, n_ops.add,
                                         axis, rtype, NULL);
    Py_DECREF(obj3);
    Py_DECREF(arr2);
    if (obj1 == NULL) {
        Py_DECREF(arrnew);
        return NULL;
    }
    n = PyArray_DIM(arrnew,axis);
    Py_DECREF(arrnew);
    n = (n-num);
    if (n == 0) {
        n = 1;
    }
    obj2 = PyFloat_FromDouble(1.0/((double )n));
    if (obj2 == NULL) {
        Py_DECREF(obj1);
        return NULL;
    }
    ret = PyNumber_Multiply(obj1, obj2);
    Py_DECREF(obj1);
    Py_DECREF(obj2);

    if (!variance) {
        arr1 = (PyArrayObject *)PyArray_EnsureAnyArray(ret);
        /* sqrt() */
        ret = PyArray_GenericUnaryFunction(arr1, n_ops.sqrt);
        Py_DECREF(arr1);
    }
    if (ret == NULL) {
        return NULL;
    }
    if (PyArray_CheckExact(self)) {
        goto finish;
    }
    if (PyArray_Check(self) && Py_TYPE(self) == Py_TYPE(ret)) {
        goto finish;
    }
    arr1 = (PyArrayObject *)PyArray_EnsureArray(ret);
    if (arr1 == NULL) {
        return NULL;
    }
    ret = PyArray_View(arr1, NULL, Py_TYPE(self));
    Py_DECREF(arr1);

finish:
    if (out) {
        if (PyArray_AssignArray(out, (PyArrayObject *)ret,
                    NULL, NPY_DEFAULT_ASSIGN_CASTING) < 0) {
            Py_DECREF(ret);
            return NULL;
        }
        Py_DECREF(ret);
        Py_INCREF(out);
        return (PyObject *)out;
    }
    return ret;
}
Exemple #3
0
/*NUMPY_API
 * Round
 */
NPY_NO_EXPORT PyObject *
PyArray_Round(PyArrayObject *a, int decimals, PyArrayObject *out)
{
    PyObject *f, *ret = NULL, *tmp, *op1, *op2;
    int ret_int=0;
    PyArray_Descr *my_descr;
    if (out && (PyArray_SIZE(out) != PyArray_SIZE(a))) {
        PyErr_SetString(PyExc_ValueError,
                        "invalid output shape");
        return NULL;
    }
    if (PyArray_ISCOMPLEX(a)) {
        PyObject *part;
        PyObject *round_part;
        PyObject *arr;
        int res;

        if (out) {
            arr = (PyObject *)out;
            Py_INCREF(arr);
        }
        else {
            arr = PyArray_Copy(a);
            if (arr == NULL) {
                return NULL;
            }
        }

        /* arr.real = a.real.round(decimals) */
        part = PyObject_GetAttrString(arr, "real");
        if (part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        part = PyArray_EnsureAnyArray(part);
        round_part = PyArray_Round((PyArrayObject *)part,
                                   decimals, NULL);
        Py_DECREF(part);
        if (round_part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        res = PyObject_SetAttrString(arr, "real", round_part);
        Py_DECREF(round_part);
        if (res < 0) {
            Py_DECREF(arr);
            return NULL;
        }

        /* arr.imag = a.imag.round(decimals) */
        part = PyObject_GetAttrString(arr, "imag");
        if (part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        part = PyArray_EnsureAnyArray(part);
        round_part = PyArray_Round((PyArrayObject *)part,
                                   decimals, NULL);
        Py_DECREF(part);
        if (round_part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        res = PyObject_SetAttrString(arr, "imag", round_part);
        Py_DECREF(round_part);
        if (res < 0) {
            Py_DECREF(arr);
            return NULL;
        }
        return arr;
    }
    /* do the most common case first */
    if (decimals >= 0) {
        if (PyArray_ISINTEGER(a)) {
            if (out) {
                if (PyArray_AssignArray(out, a,
                            NULL, NPY_DEFAULT_ASSIGN_CASTING) < 0) {
                    return NULL;
                }
                Py_INCREF(out);
                return (PyObject *)out;
            }
            else {
                Py_INCREF(a);
                return (PyObject *)a;
            }
        }
        if (decimals == 0) {
            if (out) {
                return PyObject_CallFunction(n_ops.rint, "OO", a, out);
            }
            return PyObject_CallFunction(n_ops.rint, "O", a);
        }
        op1 = n_ops.multiply;
        op2 = n_ops.true_divide;
    }
    else {
        op1 = n_ops.true_divide;
        op2 = n_ops.multiply;
        decimals = -decimals;
    }
    if (!out) {
        if (PyArray_ISINTEGER(a)) {
            ret_int = 1;
            my_descr = PyArray_DescrFromType(NPY_DOUBLE);
        }
        else {
            Py_INCREF(PyArray_DESCR(a));
            my_descr = PyArray_DESCR(a);
        }
        out = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(a), PyArray_DIMS(a),
                                             my_descr,
                                             PyArray_ISFORTRAN(a));
        if (out == NULL) {
            return NULL;
        }
    }
    else {
        Py_INCREF(out);
    }
    f = PyFloat_FromDouble(power_of_ten(decimals));
    if (f == NULL) {
        return NULL;
    }
    ret = PyObject_CallFunction(op1, "OOO", a, f, out);
    if (ret == NULL) {
        goto finish;
    }
    tmp = PyObject_CallFunction(n_ops.rint, "OO", ret, ret);
    if (tmp == NULL) {
        Py_DECREF(ret);
        ret = NULL;
        goto finish;
    }
    Py_DECREF(tmp);
    tmp = PyObject_CallFunction(op2, "OOO", ret, f, ret);
    if (tmp == NULL) {
        Py_DECREF(ret);
        ret = NULL;
        goto finish;
    }
    Py_DECREF(tmp);

 finish:
    Py_DECREF(f);
    Py_DECREF(out);
    if (ret_int) {
        Py_INCREF(PyArray_DESCR(a));
        tmp = PyArray_CastToType((PyArrayObject *)ret,
                                 PyArray_DESCR(a), PyArray_ISFORTRAN(a));
        Py_DECREF(ret);
        return tmp;
    }
    return ret;
}
Exemple #4
0
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;
}
Exemple #5
0
static PyObject *nfft(PyObject *self, PyObject *args, PyObject *kwargs)
{
  PyObject *in_obj, *coord_obj;

  
  
  static char *kwlist[] = {"real_space", "coordinates", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &in_obj, &coord_obj)) {
    return NULL;
  }
  
  PyObject *coord_array = PyArray_FROM_OTF(coord_obj, NPY_DOUBLE, NPY_IN_ARRAY);
  PyObject *in_array = PyArray_FROM_OTF(in_obj, NPY_COMPLEX128, NPY_IN_ARRAY);
  if (coord_array == NULL || in_array == NULL) {
    Py_XDECREF(coord_array);
    Py_XDECREF(in_array);
    return NULL;
  }

  int ndim = PyArray_NDIM(in_array);
  if (ndim <= 0) {
    PyErr_SetString(PyExc_ValueError, "Input array can't be 0 dimensional\n");
    return NULL;
  }

  if ((PyArray_NDIM(coord_array) != 2 || PyArray_DIM(coord_array, 1) != ndim) && (ndim != 1 || PyArray_NDIM(coord_array) != 1)) {
    PyErr_SetString(PyExc_ValueError, "Coordinates must be given as array of dimensions [NUMBER_OF_POINTS, NUMBER_OF_DIMENSIONS] of [NUMBER_OF_POINTS for 1D transforms.\n");
    Py_XDECREF(coord_array);
    Py_XDECREF(in_array);
    return NULL;
  }
  int number_of_points = (int) PyArray_DIM(coord_array, 0);

  
  nfft_plan my_plan;
  int total_number_of_pixels = 1;
  int dims[ndim];
  int dim;
  for (dim = 0; dim < ndim; ++dim) {
    dims[dim] = (int)PyArray_DIM(in_array, dim);
    total_number_of_pixels *= dims[dim];
  }

  #if defined(ENABLE_THREADS)
  printf("OMP_NUM_THREADS=%s\n",getenv("OMP_NUM_THREADS"));   
  printf("nthreads = %d\n", nfft_get_num_threads());
  fftw_init_threads();
  #endif

  nfft_init(&my_plan, ndim, dims, number_of_points);
  memcpy(my_plan.f_hat, PyArray_DATA(in_array), total_number_of_pixels*sizeof(fftw_complex));
  memcpy(my_plan.x, PyArray_DATA(coord_array), ndim*number_of_points*sizeof(double));
  
  if (my_plan.nfft_flags &PRE_PSI) {
    nfft_precompute_one_psi(&my_plan);
  }

  nfft_trafo(&my_plan);

  int out_dim[] = {number_of_points};
  PyObject *out_array = (PyObject *)PyArray_FromDims(1, out_dim, NPY_COMPLEX128);
  memcpy(PyArray_DATA(out_array), my_plan.f, number_of_points*sizeof(fftw_complex));

  // Clean up memory
  
  nfft_finalize(&my_plan);

  #if defined(ENABLE_THREADS)
  fftw_cleanup_threads();
  #endif

  Py_XDECREF(coord_array);
  Py_XDECREF(in_array);
  
  return out_array;
}
// =============================================================================
int Epetra_NumPySerialDenseVector::getVectorSize(PyObject * pyObject)
{
  if (!tmp_array) getArray(pyObject);
  return (int) PyArray_MultiplyList(PyArray_DIMS(tmp_array),
                                    PyArray_NDIM(tmp_array));
}
Exemple #7
0
static PyObject *spa_calc(PyObject *self, PyObject *args)
{
    int N_IN, N_DOUBLE_IN, N_ARRAY_IN, N_DOUBLE_OUT, N_ARRAY_OUT, N;
    
    PyObject *input_obj[PYSPA_MAX_ARGS];
    double    input_double[PYSPA_MAX_ARGS];
    
    PyArrayObject *input_arr[PYSPA_MAX_ARGS],     *output_arr[PYSPA_MAX_ARGS];
    double        *input_arr_ptr[PYSPA_MAX_ARGS], *output_arr_ptr[PYSPA_MAX_ARGS];
    int            input_arr_map[PYSPA_MAX_ARGS], input_double_map[PYSPA_MAX_ARGS], input_type[PYSPA_MAX_ARGS];
    
    double    year=0, month=0, day=0, hour=0, minute=0, second=0, latitude=0, longitude=0, elevation=0, slope=0, aspect=0;
    double    zenith, azimuth, incidence;
    double    value;
    
    int       flag;
    
    int       i, j, ndim, dims[NPY_MAXDIMS], rc=0;
    spa_data  spa;
    
    static const double m_air   = 0.02896; // molecular mass of air, kg mol^-1
    static const double R_const = 8.3143;  // gas constant, N M mol^-1 K^-1
    static const double g_const = 9.807;   // gravity constant, m s^-2
    static const double T_const = 288.15;  // "default" air temperature, K
        
    /* Parse the input tuple */
    for (i=0; i<64; i++) input_obj[i] = NULL;
    if (!PyArg_ParseTuple(args, "OOOOOOOO|OOO", &input_obj[0], &input_obj[1], &input_obj[2], &input_obj[3], &input_obj[4], 
                                                &input_obj[5], &input_obj[6], &input_obj[7], &input_obj[8], &input_obj[9], &input_obj[10]))
        return NULL;
    
    if (input_obj[8] == NULL) {
        // fprintf(stderr, "Running SPA_ZA mode ...\n");
        spa.function = SPA_ZA;
        N_IN         = 8;
        N_DOUBLE_OUT = 0;
        N_ARRAY_OUT  = 2;
    }
    else {
        // fprintf(stderr, "Running SPA_ZA_INC mode ...\n");
        spa.function = SPA_ZA_INC;
        N_IN         = 11;
        N_DOUBLE_OUT = 0;
        N_ARRAY_OUT  = 3;
    }
    
    N_DOUBLE_IN = 0;
    N_ARRAY_IN  = 0;
    for (i=0; i<N_IN; i++) {
        /* Interpret the input objects as numpy arrays. */
        input_arr[i] = (PyArrayObject *) PyArray_FROM_OTF(input_obj[i], NPY_DOUBLE, NPY_IN_ARRAY);
        /* Is is really a numpy array? */
        if (PyArray_NDIM(input_arr[i])==0) {
            input_type[i] = 0;
            input_double_map[N_DOUBLE_IN] = i;
            N_DOUBLE_IN++;
            input_double[i] = PyFloat_AsDouble(input_obj[i]);
            Py_XDECREF(input_arr[i]);
        }
        else {
            input_type[i] = 1;
            input_arr_map[N_ARRAY_IN] = i;
            N_ARRAY_IN++;
        }
    }
    
    /* If that didn't work, throw an exception. */
    flag = 0; for (i=0; i<N_ARRAY_IN; i++) if (input_arr[input_arr_map[i]]==NULL) flag = 1;
    if (flag==1) {
        for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
        return NULL;
    }
    
    /* Get pointers to the data as C-types. */
    for (i=0; i<N_ARRAY_IN; i++) input_arr_ptr[input_arr_map[i]] = (double*) PyArray_DATA(input_arr[input_arr_map[i]]);
    
    /* How many data points are there? */
    ndim = (int)PyArray_NDIM(input_arr[input_arr_map[0]]);
    
    N=1;
    for (j=0; j<ndim; j++) {
         dims[j] = PyArray_DIM(input_arr[input_arr_map[0]], j);
         N *= dims[j];
         /* check for dimension size compatibility */
         flag = 0; for (i=1; i<N_ARRAY_IN; i++) if (dims[j] != PyArray_DIM(input_arr[input_arr_map[i]], j)) flag = 1;
         if (flag==1) {
             for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
             PyErr_SetString(PyExc_RuntimeError, "different dimensions of input arrays.");
             return NULL;
         }
    }
        
    for (i=0; i<N_ARRAY_OUT; i++) {
        output_arr[i]     = (PyArrayObject *) PyArray_FromDims(ndim, dims, NPY_DOUBLE);
        output_arr_ptr[i] = (double*) PyArray_DATA(output_arr[i]);
    }
    
    /* Call the external C function to compute the results. */
    for (j=0; j<N; j++) {
        
        for (i=0; i<N_IN; i++) {
            if (input_type[i] == 0) value = input_double[i];
            else                    value = input_arr_ptr[i][j];
            switch (i) {
                case  0: year      = value;
                case  1: month     = value;
                case  2: day       = value;
                case  3: hour      = value;
                case  4: minute    = value;
                case  5: second    = value;
                case  6: latitude  = value;
                case  7: longitude = value;
                case  8: elevation = value;
                case  9: slope     = value;
                case 10: aspect    = value;
            }
        }
        
        /* some checks */
        if (longitude>180) longitude -= 360;
        
        /* SPA's azm_rotation angle is measured from south and most aspect angle is measured from north */
        aspect -= 180; if (aspect<-360) aspect += 360;
        
        spa.year          = (int) year;
        spa.month         = (int) month;
        spa.day           = (int) day;
        spa.hour          = (int) hour;
        spa.minute        = (int) minute;
        spa.second        = (int) second;
        spa.latitude      = latitude;
        spa.longitude     = longitude;
        spa.timezone      = 0.0;
        spa.delta_t       = 0;
        spa.elevation     = elevation;
        spa.pressure      = 1000*exp(-m_air*g_const*elevation/(R_const*T_const));
        spa.temperature   = 0;
        spa.slope         = slope;
        spa.azm_rotation  = aspect;
        spa.atmos_refract = 0.5667;
        
        rc = spa_calculate(&spa);
        
        if (rc == 0) {
            zenith    = spa.zenith;
            azimuth   = spa.azimuth;
            incidence = spa.incidence;
        }
        else {
            zenith    = -9999;
            azimuth   = -9999;
            incidence = -9999;
        }
        
        output_arr_ptr[0][j] = zenith; output_arr_ptr[1][j] = azimuth;
        if (spa.function == SPA_ZA_INC) output_arr_ptr[2][j] = incidence;
        
    }
    
    /* Clean up. */
    for (i=0; i<N_ARRAY_IN; i++) Py_XDECREF(input_arr[input_arr_map[i]]);
    
    /* Build the output tuple */
    if (spa.function == SPA_ZA)
        return Py_BuildValue("OO", output_arr[0], output_arr[1]);
    else
        return Py_BuildValue("OOO", output_arr[0], output_arr[1], output_arr[2]);
}
Exemple #8
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;
}
Exemple #9
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;
    npy_double *fw;
    NI_LineBuffer iline_buffer, oline_buffer;
    NPY_BEGIN_THREADS_DEF;

    /* test for symmetry or anti-symmetry: */
    filter_size = PyArray_SIZE(weights);
    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 = PyArray_NDIM(input) > 0 ? PyArray_DIM(input, axis) : 1;
    fw += size1;
    /* 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(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)) {
            goto exit;
        }
    } while(more);
exit:
    NPY_END_THREADS;
    free(ibuffer);
    free(obuffer);
    return PyErr_Occurred() ? 0 : 1;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
0
static PyObject *div_unit_grad1(PyObject *self, PyObject *args)
{
  PyObject* f = NULL;
  npy_intp Nx;
  int i, im1, im2, ip1;
  npy_float64* f_data_dp = NULL;
  npy_float64* r_data_dp = NULL;
  double hx;
  double hx2;
  PyArrayObject* r = NULL;
  double fip, fim, fijk;
  double aim, aijk;
  double Dxpf, Dxmf;
  double Dxma;
  if (!PyArg_ParseTuple(args, "Od", &f, &hx))
    return NULL;
  hx2 = 2*hx;
  if (!PyArray_Check(f))
    {
      PyErr_SetString(PyExc_TypeError,"first argument must be array");
      return NULL;
    }
  if (PyArray_NDIM(f) != 1)
    {
      PyErr_SetString(PyExc_TypeError,"array argument must have rank 1");
      return NULL;
    }
  Nx = PyArray_DIM(f, 0);
  r = (PyArrayObject*)PyArray_SimpleNew(1, PyArray_DIMS(f), PyArray_TYPE(f));

  if (PyArray_TYPE(f) == PyArray_FLOAT64)
    {
      f_data_dp = (npy_float64*)PyArray_DATA(f);
      r_data_dp = (npy_float64*)PyArray_DATA(r);
      for (i=0; i<Nx; ++i)
	{
	  im1 = (i?i-1:0);
      	  ip1 = (i+1==Nx?i:i+1);
	  fim = *((npy_float64*)PyArray_GETPTR1(f, im1));
	  fijk = *((npy_float64*)PyArray_GETPTR1(f, i));
	  fip = *((npy_float64*)PyArray_GETPTR1(f, ip1));
	  Dxpf = (fip - fijk) / hx;
	  //if (Dxpf==0.0) aijk = 0.0;
	  //else if (Dxpf<0.0) aijk = -1.0;
	  //else aijk = 1.0;
	  aijk = sqrt(Dxpf*Dxpf);
	  aijk = (aijk>FLOAT64_EPS?Dxpf / aijk:0.0);
	  //aijk = abs(Dxpf);
	  //aijk = (aijk>FLOAT64_EPS?Dxpf / aijk:0.0);
	  Dxpf = (fijk - fim) / hx;
	  //if (Dxpf==0.0) aim = 0.0;
	  //else if (Dxpf<0.0) aim = -1.0;
	  //else aim = 1.0;
	  //aim = abs(Dxpf);
	  //aim = (aim>FLOAT64_EPS?Dxpf/aim:0.0); 		  
	  aim = sqrt(Dxpf*Dxpf);
	  aim = (aim>FLOAT64_EPS?Dxpf/aim:0.0);
	  Dxma = (aijk - aim) / hx;
	  *((npy_float64*)PyArray_GETPTR1(r, i)) = Dxma;
	}
    }
  else
    {
      PyErr_SetString(PyExc_TypeError,"array argument type must be float64");
      return NULL;
    }
  return Py_BuildValue("N", r);
}
Exemple #14
0
static PyObject *div_unit_grad(PyObject *self, PyObject *args)
{
  PyObject* f = NULL;
  npy_intp Nx, Ny, Nz;
  int i, j, k, im1, im2, ip1, jm1, jm2, jp1, km1, km2, kp1;
  npy_float64* f_data_dp = NULL;
  npy_float64* r_data_dp = NULL;
  npy_float32* f_data_sp = NULL;
  npy_float32* r_data_sp = NULL;
  double hx, hy, hz;
  double hx2, hy2, hz2;
  PyArrayObject* r = NULL;
  double fip, fim, fjp, fjm, fkp, fkm, fijk;
  double fimkm, fipkm, fjmkm, fjpkm, fimjm, fipjm, fimkp, fjmkp, fimjp;
  double aim, bjm, ckm, aijk, bijk, cijk;
  double Dxpf, Dxmf, Dypf, Dymf, Dzpf, Dzmf;
  double Dxma, Dymb, Dzmc;
  if (!PyArg_ParseTuple(args, "O(ddd)", &f, &hx, &hy, &hz))
    return NULL;
  hx2 = 2*hx;  hy2 = 2*hy;  hz2 = 2*hz;
  if (!PyArray_Check(f))
    {
      PyErr_SetString(PyExc_TypeError,"first argument must be array");
      return NULL;
    }
  if (PyArray_NDIM(f) != 3)
    {
      PyErr_SetString(PyExc_TypeError,"array argument must have rank 3");
      return NULL;
    }
  Nx = PyArray_DIM(f, 0);
  Ny = PyArray_DIM(f, 1);
  Nz = PyArray_DIM(f, 2);
  r = (PyArrayObject*)PyArray_SimpleNew(3, PyArray_DIMS(f), PyArray_TYPE(f));

  if (PyArray_TYPE(f) == PyArray_FLOAT32)
    {
      f_data_sp = (npy_float32*)PyArray_DATA(f);
      r_data_sp = (npy_float32*)PyArray_DATA(r);
      for (i=0; i<Nx; ++i)
	{
	  im1 = (i?i-1:0);
	  im2 = (im1?im1-1:0);
      	  ip1 = (i+1==Nx?i:i+1);
	  for (j=0; j<Ny; ++j)
	    {
	      jm1 = (j?j-1:0);
	      jm2 = (jm1?jm1-1:0);
	      jp1 = (j+1==Ny?j:j+1);
	      for (k=0; k<Nz; ++k)
		{
		  km1 = (k?k-1:0);
		  km2 = (km1?km1-1:0);
		  kp1 = (k+1==Nz?k:k+1);

		  fimjm = *((npy_float32*)PyArray_GETPTR3(f, im1, jm1, k));
		  fim = *((npy_float32*)PyArray_GETPTR3(f, im1, j, k));
		  fimkm = *((npy_float32*)PyArray_GETPTR3(f, im1, j, km1));
		  fimkp = *((npy_float32*)PyArray_GETPTR3(f, im1, j, kp1));
		  fimjp = *((npy_float32*)PyArray_GETPTR3(f, im1, jp1, k));

		  fjmkm = *((npy_float32*)PyArray_GETPTR3(f, i, jm1, km1));
		  fjm = *((npy_float32*)PyArray_GETPTR3(f, i, jm1, k));
		  fjmkp = *((npy_float32*)PyArray_GETPTR3(f, i, jm1, kp1));

		  fkm = *((npy_float32*)PyArray_GETPTR3(f, i, j, km1));
		  fijk = *((npy_float32*)PyArray_GETPTR3(f, i, j, k));
		  fkp = *((npy_float32*)PyArray_GETPTR3(f, i, j, kp1));

		  fjpkm = *((npy_float32*)PyArray_GETPTR3(f, i, jp1, km1));
		  fjp = *((npy_float32*)PyArray_GETPTR3(f, i, jp1, k));

		  fipjm = *((npy_float32*)PyArray_GETPTR3(f, ip1, jm1, k));
		  fipkm = *((npy_float32*)PyArray_GETPTR3(f, ip1, j, km1));
		  fip = *((npy_float32*)PyArray_GETPTR3(f, ip1, j, k));

		  Dxpf = (fip - fijk) / hx;
		  Dxmf = (fijk - fim) / hx;
		  Dypf = (fjp - fijk) / hy;
		  Dymf = (fijk - fjm) / hy;
		  Dzpf = (fkp - fijk) / hz;
		  Dzmf = (fijk - fkm) / hz;
		  aijk = hypot3(Dxpf, m(Dypf, Dymf), m(Dzpf, Dzmf));
		  bijk = hypot3(Dypf, m(Dxpf, Dxmf), m(Dzpf, Dzmf));
		  cijk = hypot3(Dzpf, m(Dypf, Dymf), m(Dxpf, Dxmf));

		  aijk = (aijk>FLOAT32_EPS?Dxpf / aijk:0.0);
		  bijk = (bijk>FLOAT32_EPS?Dypf / bijk: 0.0);
		  cijk = (cijk>FLOAT32_EPS?Dzpf / cijk:0.0); 
		  

		  Dxpf = (fijk - fim) / hx;
		  Dypf = (fimjp - fim) / hy;
		  Dymf = (fim - fimjm) / hy;
		  Dzpf = (fimkp - fim) / hz;
		  Dzmf = (fim - fimkm) / hz;
		  aim = hypot3(Dxpf, m(Dypf, Dymf), m(Dzpf, Dzmf));

		  aim = (aim>FLOAT32_EPS?Dxpf/aim:0.0); 


		  Dxpf = (fipjm - fjm) / hx;
		  Dxmf = (fjm - fimjm) / hx;
		  Dypf = (fijk - fjm) / hy;
		  Dzpf = (fjmkp - fjm) / hz;
		  Dzmf = (fjm - fjmkm) / hz;
		  bjm = hypot3(Dypf, m(Dxpf, Dxmf), m(Dzpf, Dzmf));

		  bjm = (bjm>FLOAT32_EPS?Dypf/bjm:0.0);
		  

		  Dxpf = (fipkm - fkm) / hx;
		  Dxmf = (fjm - fimkm) / hx;
		  Dypf = (fjpkm - fkm) / hy;
		  Dymf = (fkm - fjmkm) / hy;
		  Dzpf = (fijk - fkm) / hz;
		  ckm = hypot3(Dzpf, m(Dypf, Dymf), m(Dxpf, Dxmf));

		  ckm = (ckm>FLOAT32_EPS?Dzpf/ckm:0.0); 

		  Dxma = (aijk - aim) / hx;
		  Dymb = (bijk - bjm) / hy;
		  Dzmc = (cijk - ckm) / hz;
		  
		  //*((npy_float32*)PyArray_GETPTR3(r, i, j, k)) = Dxma/hx + Dymb/hy + Dzmc/hz;
		  *((npy_float32*)PyArray_GETPTR3(r, i, j, k)) = Dxma + Dymb + Dzmc;
		}
	    }
	}      
    }
  else if (PyArray_TYPE(f) == PyArray_FLOAT64)
    {
      f_data_dp = (npy_float64*)PyArray_DATA(f);
      r_data_dp = (npy_float64*)PyArray_DATA(r);
      for (i=0; i<Nx; ++i)
	{
	  im1 = (i?i-1:0);
	  im2 = (im1?im1-1:0);
      	  ip1 = (i+1==Nx?i:i+1);
	  for (j=0; j<Ny; ++j)
	    {
	      jm1 = (j?j-1:0);
	      jm2 = (jm1?jm1-1:0);
	      jp1 = (j+1==Ny?j:j+1);
	      for (k=0; k<Nz; ++k)
		{
		  km1 = (k?k-1:0);
		  km2 = (km1?km1-1:0);
		  kp1 = (k+1==Nz?k:k+1);

		  fimjm = *((npy_float64*)PyArray_GETPTR3(f, im1, jm1, k));
		  fim = *((npy_float64*)PyArray_GETPTR3(f, im1, j, k));
		  fimkm = *((npy_float64*)PyArray_GETPTR3(f, im1, j, km1));
		  fimkp = *((npy_float64*)PyArray_GETPTR3(f, im1, j, kp1));
		  fimjp = *((npy_float64*)PyArray_GETPTR3(f, im1, jp1, k));

		  fjmkm = *((npy_float64*)PyArray_GETPTR3(f, i, jm1, km1));
		  fjm = *((npy_float64*)PyArray_GETPTR3(f, i, jm1, k));
		  fjmkp = *((npy_float64*)PyArray_GETPTR3(f, i, jm1, kp1));

		  fkm = *((npy_float64*)PyArray_GETPTR3(f, i, j, km1));
		  fijk = *((npy_float64*)PyArray_GETPTR3(f, i, j, k));
		  fkp = *((npy_float64*)PyArray_GETPTR3(f, i, j, kp1));

		  fjpkm = *((npy_float64*)PyArray_GETPTR3(f, i, jp1, km1));
		  fjp = *((npy_float64*)PyArray_GETPTR3(f, i, jp1, k));

		  fipjm = *((npy_float64*)PyArray_GETPTR3(f, ip1, jm1, k));
		  fipkm = *((npy_float64*)PyArray_GETPTR3(f, ip1, j, km1));
		  fip = *((npy_float64*)PyArray_GETPTR3(f, ip1, j, k));

		  Dxpf = (fip - fijk) / hx;
		  Dxmf = (fijk - fim) / hx;
		  Dypf = (fjp - fijk) / hy;
		  Dymf = (fijk - fjm) / hy;
		  Dzpf = (fkp - fijk) / hz;
		  Dzmf = (fijk - fkm) / hz;
		  aijk = hypot3(Dxpf, m(Dypf, Dymf), m(Dzpf, Dzmf));
		  aijk = (aijk>FLOAT64_EPS?Dxpf / aijk:0.0);
		  bijk = hypot3(Dypf, m(Dxpf, Dxmf), m(Dzpf, Dzmf));
		  bijk = (bijk>FLOAT64_EPS?Dypf / bijk: 0.0);
		  cijk = hypot3(Dzpf, m(Dypf, Dymf), m(Dxpf, Dxmf));
		  cijk = (cijk>FLOAT64_EPS?Dzpf/cijk:0.0);

		  Dxpf = (fijk - fim) / hx;
		  Dypf = (fimjp - fim) / hy;
		  Dymf = (fim - fimjm) / hy;
		  Dzpf = (fimkp - fim) / hz;
		  Dzmf = (fim - fimkm) / hz;
		  aim = hypot3(Dxpf, m(Dypf, Dymf), m(Dzpf, Dzmf));
		  aim = (aim>FLOAT64_EPS?Dxpf/aim:0.0); 

		  Dxpf = (fipjm - fjm) / hx;
		  Dxmf = (fjm - fimjm) / hx;
		  Dypf = (fijk - fjm) / hy;
		  Dzpf = (fjmkp - fjm) / hz;
		  Dzmf = (fjm - fjmkm) / hz;
		  bjm = hypot3(Dypf, m(Dxpf, Dxmf), m(Dzpf, Dzmf));
		  bjm = (bjm>FLOAT64_EPS?Dypf/bjm:0.0);
		  


		  Dxpf = (fipkm - fkm) / hx;
		  Dxmf = (fjm - fimkm) / hx;
		  Dypf = (fjpkm - fkm) / hy;
		  Dymf = (fkm - fjmkm) / hy;
		  Dzpf = (fijk - fkm) / hz;
		  ckm = hypot3(Dzpf, m(Dypf, Dymf), m(Dxpf, Dxmf));
		  ckm = (ckm>FLOAT64_EPS?Dzpf/ckm:0.0); 
		  
		  Dxma = (aijk - aim) / hx;
		  Dymb = (bijk - bjm) / hy;
		  Dzmc = (cijk - ckm) / hz;

		  //*((npy_float64*)PyArray_GETPTR3(r, i, j, k)) = Dxma/hx + Dymb/hy + Dzmc/hz;
		  *((npy_float64*)PyArray_GETPTR3(r, i, j, k)) = Dxma + Dymb + Dzmc;
		}
	    }
	}
    }
  else
    {
      PyErr_SetString(PyExc_TypeError,"array argument type must be float64");
      return NULL;
    }
  return Py_BuildValue("N", r);
}
Exemple #15
0
/*
 * Converts a Python input into a non-normalized list of holidays.
 *
 * IMPORTANT: This function can't do the normalization, because it doesn't
 *            know the weekmask. You must call 'normalize_holiday_list'
 *            on the result before using it.
 */
NPY_NO_EXPORT int
PyArray_HolidaysConverter(PyObject *dates_in, npy_holidayslist *holidays)
{
    PyArrayObject *dates = NULL;
    PyArray_Descr *date_dtype = NULL;
    npy_intp count;

    /* Make 'dates' into an array */
    if (PyArray_Check(dates_in)) {
        dates = (PyArrayObject *)dates_in;
        Py_INCREF(dates);
    }
    else {
        PyArray_Descr *datetime_dtype;

        /* Use the datetime dtype with generic units so it fills it in */
        datetime_dtype = PyArray_DescrFromType(NPY_DATETIME);
        if (datetime_dtype == NULL) {
            goto fail;
        }

        /* This steals the datetime_dtype reference */
        dates = (PyArrayObject *)PyArray_FromAny(dates_in, datetime_dtype,
                                                0, 0, 0, dates_in);
        if (dates == NULL) {
            goto fail;
        }
    }

    date_dtype = create_datetime_dtype_with_unit(NPY_DATETIME, NPY_FR_D);
    if (date_dtype == NULL) {
        goto fail;
    }

    if (!PyArray_CanCastTypeTo(PyArray_DESCR(dates),
                                    date_dtype, NPY_SAFE_CASTING)) {
        PyErr_SetString(PyExc_ValueError, "Cannot safely convert "
                        "provided holidays input into an array of dates");
        goto fail;
    }
    if (PyArray_NDIM(dates) != 1) {
        PyErr_SetString(PyExc_ValueError, "holidays must be a provided "
                        "as a one-dimensional array");
        goto fail;
    }

    /* Allocate the memory for the dates */
    count = PyArray_DIM(dates, 0);
    holidays->begin = PyArray_malloc(sizeof(npy_datetime) * count);
    if (holidays->begin == NULL) {
        PyErr_NoMemory();
        goto fail;
    }
    holidays->end = holidays->begin + count;

    /* Cast the data into a raw date array */
    if (PyArray_CastRawArrays(count,
                            PyArray_BYTES(dates), (char *)holidays->begin,
                            PyArray_STRIDE(dates, 0), sizeof(npy_datetime),
                            PyArray_DESCR(dates), date_dtype,
                            0) != NPY_SUCCEED) {
        goto fail;
    }

    Py_DECREF(dates);
    Py_DECREF(date_dtype);

    return 1;

fail:
    Py_XDECREF(dates);
    Py_XDECREF(date_dtype);
    return 0;
}
Exemple #16
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;

    struct pairs {
        double value;
        npy_intp death;
    } *ring = NULL, *minpair, *end, *last;

    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;

    /* 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)) {
            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)) {
            goto exit;
        }
    } while(more);

 exit:
    NPY_END_THREADS;
    free(ibuffer);
    free(obuffer);
    free(ring);
    return PyErr_Occurred() ? 0 : 1;
}
Exemple #17
0
static PyObject *fit_ellipse_double_func(PyObject *self, PyObject *args)
{
    PyObject *points=NULL;
    PyObject *points_arr=NULL;

    /* Local variables for handling the dimensions of the ndarrays. */
    long *points_arr_dims=NULL;
    int points_arr_nd=0;

    /* Pointers into the ndarrays. */
    npy_int32 *points_arr_ptr=NULL;

    /* Loop counters and other local variables. */
    int i;

    /* Parse the input to correct pointers. */
    if (!PyArg_ParseTuple(args, "O", &points))
        return NULL;

    points_arr = PyArray_FROM_OTF(points, NPY_INT32, NPY_IN_ARRAY);
    if (points_arr == NULL) goto fail;

    /* Dimensions of the arrays. */
    points_arr_nd        = PyArray_NDIM(points_arr);
    points_arr_dims      = PyArray_DIMS(points_arr);

    if (points_arr_nd != 2)
    {
        printf("Dimension of coordinates array must be equal to zero. (%d != 2).\n",
               points_arr_nd);
        goto fail;
    }

    int32_t *x = (int32_t*) malloc(sizeof(int32_t) * points_arr_dims[0]);
    int32_t *y = (int32_t*) malloc(sizeof(int32_t) * points_arr_dims[0]);
    for (i = 0; i < points_arr_dims[0]; i++)
    {
        points_arr_ptr = PyArray_GETPTR2(points_arr, i, 0);
        x[i] = points_arr_ptr[0];
        y[i] = points_arr_ptr[1];
    }

    // Call the actual ellipse fitting function.
    EllipseDouble ellipse = FitEllipse_double(x, y, (int16_t) points_arr_dims[0]);

    /* Decrease reference counters and free memory to avoid memory leaks. */
    free(x);
    free(y);
    Py_DECREF(points_arr);

    if (ellipse.isValid)
    {
        int out_dims[1] = {2};
        PyArrayObject *xy;
        npy_float64 *xy_ptr;
        xy = (PyArrayObject *) PyArray_FromDims(1, out_dims, NPY_FLOAT64);
        xy_ptr = (npy_float64 *)PyArray_GETPTR1(xy, 0);
        xy_ptr[0] = ellipse.centerX;
        xy_ptr[1] = ellipse.centerY;

        PyArrayObject *axes;
        npy_float64 *axes_ptr;
        axes = (PyArrayObject *) PyArray_FromDims(1, out_dims, NPY_FLOAT64);
        axes_ptr = (npy_float64 *)PyArray_GETPTR1(axes, 0);
        axes_ptr[0] = ellipse.xAxis;
        axes_ptr[1] = ellipse.yAxis;

        PyObject *tuple_result = PyTuple_New(3);
        PyTuple_SetItem(tuple_result, 0, PyArray_Return(xy));
        PyTuple_SetItem(tuple_result, 1, PyArray_Return(axes));
        PyTuple_SetItem(tuple_result, 2, PyFloat_FromDouble(ellipse.rotationAngle));

        return (PyObject *)tuple_result;
    }
    else
    {
        Py_RETURN_NONE;
    }

 fail:
    /* If error occurs, decrease reference counters to avoid memory leaks. */
    Py_XDECREF(points_arr);
    /* Return error indication. */
    return NULL;
}
Exemple #18
0
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;
}
bool numpy_to_mat(const PyObject* o, cv::Mat& m, const char* name, bool allowND)
{
  if(!o || o == Py_None)
    {
        if( !m.data )
            m.allocator = &g_numpyAllocator;
        return true;
    }

    if( !PyArray_Check(o) )
    {
        failmsg("%s is not a numpy array", name);
        return false;
    }

    int typenum = PyArray_TYPE(o);
    int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :
               typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :
               typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :
               typenum == NPY_FLOAT ? CV_32F :
               typenum == NPY_DOUBLE ? CV_64F : -1;

    if( type < 0 )
    {
        failmsg("%s data type = %d is not supported", name, typenum);
        return false;
    }

    int ndims = PyArray_NDIM(o);
    if(ndims >= CV_MAX_DIM)
    {
        failmsg("%s dimensionality (=%d) is too high", name, ndims);
        return false;
    }

    int size[CV_MAX_DIM+1];
    size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);
    const npy_intp* _sizes = PyArray_DIMS(o);
    const npy_intp* _strides = PyArray_STRIDES(o);

    for(int i = 0; i < ndims; i++)
    {
        size[i] = (int)_sizes[i];
        step[i] = (size_t)_strides[i];
    }

    if( ndims == 0 || step[ndims-1] > elemsize ) {
        size[ndims] = 1;
        step[ndims] = elemsize;
        ndims++;
    }

    if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )
    {
        ndims--;
        type |= CV_MAKETYPE(0, size[2]);
    }

    if( ndims > 2 && !allowND )
    {
        failmsg("%s has more than 2 dimensions", name);
        return false;
    }

    m = Mat(ndims, size, type, PyArray_DATA(o), step);

    if( m.data )
    {
        m.refcount = refcountFromPyObject(o);
        m.addref(); // protect the original numpy array from deallocation
                    // (since Mat destructor will decrement the reference counter)
    };
    m.allocator = &g_numpyAllocator;
    return true;
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}
Exemple #22
0
/*
 * This function initializes a result array for a reduction operation
 * which has no identity. This means it needs to copy the first element
 * it sees along the reduction axes to result, then return a view of
 * the operand which excludes that element.
 *
 * If a reduction has an identity, such as 0 or 1, the result should be
 * initialized by calling PyArray_AssignZero(result, NULL, NULL) or
 * PyArray_AssignOne(result, NULL, NULL), because this function raises an
 * exception when there are no elements to reduce (which appropriate iff the
 * reduction operation has no identity).
 * 
 * This means it copies the subarray indexed at zero along each reduction axis
 * into 'result', then returns a view into 'operand' excluding those copied
 * elements.
 *
 * result  : The array into which the result is computed. This must have
 *           the same number of dimensions as 'operand', but for each
 *           axis i where 'axis_flags[i]' is True, it has a single element.
 * operand : The array being reduced.
 * axis_flags : An array of boolean flags, one for each axis of 'operand'.
 *              When a flag is True, it indicates to reduce along that axis.
 * reorderable : If True, the reduction being done is reorderable, which
 *               means specifying multiple axes of reduction at once is ok,
 *               and the reduction code may calculate the reduction in an
 *               arbitrary order. The calculation may be reordered because
 *               of cache behavior or multithreading requirements.
 * out_skip_first_count : This gets populated with the number of first-visit
 *                        elements that should be skipped during the
 *                        iteration loop.
 * funcname : The name of the reduction operation, for the purpose of
 *            better quality error messages. For example, "numpy.max"
 *            would be a good name for NumPy's max function.
 *
 * Returns a view which contains the remaining elements on which to do
 * the reduction.
 */
NPY_NO_EXPORT PyArrayObject *
PyArray_InitializeReduceResult(
                    PyArrayObject *result, PyArrayObject *operand,
                    npy_bool *axis_flags, int reorderable,
                    npy_intp *out_skip_first_count, const char *funcname)
{
    npy_intp *strides, *shape, shape_orig[NPY_MAXDIMS];
    PyArrayObject *op_view = NULL;
    int idim, ndim, nreduce_axes;

    ndim = PyArray_NDIM(operand);

    /* Default to no skipping first-visit elements in the iteration */
    *out_skip_first_count = 0;

    /*
     * If this reduction is non-reorderable, make sure there are
     * only 0 or 1 axes in axis_flags.
     */
    if (!reorderable && check_nonreorderable_axes(ndim,
                                    axis_flags, funcname) < 0) {
        return NULL;
    }

    /* Take a view into 'operand' which we can modify. */
    op_view = (PyArrayObject *)PyArray_View(operand, NULL, &PyArray_Type);
    if (op_view == NULL) {
        return NULL;
    }

    /*
     * Now copy the subarray of the first element along each reduction axis,
     * then return a view to the rest.
     *
     * Adjust the shape to only look at the first element along
     * any of the reduction axes. We count the number of reduction axes
     * at the same time.
     */
    shape = PyArray_SHAPE(op_view);
    nreduce_axes = 0;
    memcpy(shape_orig, shape, ndim * sizeof(npy_intp));
    for (idim = 0; idim < ndim; ++idim) {
        if (axis_flags[idim]) {
            if (shape[idim] == 0) {
                PyErr_Format(PyExc_ValueError,
                             "zero-size array to reduction operation %s "
                             "which has no identity",
                             funcname);
                Py_DECREF(op_view);
                return NULL;
            }
            shape[idim] = 1;
            ++nreduce_axes;
        }
    }

    /*
     * Copy the elements into the result to start.
     */
    if (PyArray_CopyInto(result, op_view) < 0) {
        Py_DECREF(op_view);
        return NULL;
    }

    /*
     * If there is one reduction axis, adjust the view's
     * shape to only look at the remaining elements
     */
    if (nreduce_axes == 1) {
        strides = PyArray_STRIDES(op_view);
        for (idim = 0; idim < ndim; ++idim) {
            if (axis_flags[idim]) {
                shape[idim] = shape_orig[idim] - 1;
                ((PyArrayObject_fields *)op_view)->data += strides[idim];
            }
        }
    }
    /* If there are zero reduction axes, make the view empty */
    else if (nreduce_axes == 0) {
        for (idim = 0; idim < ndim; ++idim) {
            shape[idim] = 0;
        }
    }
    /*
     * Otherwise iterate over the whole operand, but tell the inner loop
     * to skip the elements we already copied by setting the skip_first_count.
     */
    else {
        *out_skip_first_count = PyArray_SIZE(result);

        Py_DECREF(op_view);
        Py_INCREF(operand);
        op_view = operand;
    }

    return op_view;
}
Exemple #23
0
static PyObject*
PyUnits_convert(
    PyUnits* self,
    PyObject* args,
    PyObject* kwds) {

  int            status       = 1;
  PyObject*      input        = NULL;
  PyArrayObject* input_arr    = NULL;
  PyArrayObject* output_arr   = NULL;
  PyObject*      input_iter   = NULL;
  PyObject*      output_iter  = NULL;
  double         input_val;
  double         output_val;

  if (!PyArg_ParseTuple(args, "O:UnitConverter.convert", &input)) {
    goto exit;
  }

  input_arr = (PyArrayObject*)PyArray_FromObject(
      input, NPY_DOUBLE, 0, NPY_MAXDIMS);
  if (input_arr == NULL) {
    goto exit;
  }

  output_arr = (PyArrayObject*)PyArray_SimpleNew(
      PyArray_NDIM(input_arr), PyArray_DIMS(input_arr), PyArray_DOUBLE);
  if (output_arr == NULL) {
    goto exit;
  }

  input_iter = PyArray_IterNew((PyObject*)input_arr);
  if (input_iter == NULL) {
    goto exit;
  }

  output_iter = PyArray_IterNew((PyObject*)output_arr);
  if (output_iter == NULL) {
    goto exit;
  }

  if (self->power != 1.0) {
    while (PyArray_ITER_NOTDONE(input_iter)) {
      input_val = *(double *)PyArray_ITER_DATA(input_iter);
      output_val = pow(self->scale*input_val + self->offset, self->power);
      if (errno) {
        PyErr_SetFromErrno(PyExc_ValueError);
        goto exit;
      }
      *(double *)PyArray_ITER_DATA(output_iter) = output_val;
      PyArray_ITER_NEXT(input_iter);
      PyArray_ITER_NEXT(output_iter);
    }
  } else {
    while (PyArray_ITER_NOTDONE(input_iter)) {
      input_val = *(double *)PyArray_ITER_DATA(input_iter);
      output_val = self->scale*input_val + self->offset;
      *(double *)PyArray_ITER_DATA(output_iter) = output_val;
      PyArray_ITER_NEXT(input_iter);
      PyArray_ITER_NEXT(output_iter);
    }
  }

  status = 0;

 exit:

  Py_XDECREF((PyObject*)input_arr);
  Py_XDECREF(input_iter);
  Py_XDECREF(output_iter);
  if (status) {
    Py_XDECREF((PyObject*)output_arr);
    return NULL;
  }
  return (PyObject*)output_arr;
}
Exemple #24
0
/*
 * This function executes all the standard NumPy reduction function
 * boilerplate code, just calling assign_identity and the appropriate
 * inner loop function where necessary.
 *
 * operand     : The array to be reduced.
 * out         : NULL, or the array into which to place the result.
 * wheremask   : NOT YET SUPPORTED, but this parameter is placed here
 *               so that support can be added in the future without breaking
 *               API compatibility. Pass in NULL.
 * operand_dtype : The dtype the inner loop expects for the operand.
 * result_dtype : The dtype the inner loop expects for the result.
 * casting     : The casting rule to apply to the operands.
 * axis_flags  : Flags indicating the reduction axes of 'operand'.
 * reorderable : If True, the reduction being done is reorderable, which
 *               means specifying multiple axes of reduction at once is ok,
 *               and the reduction code may calculate the reduction in an
 *               arbitrary order. The calculation may be reordered because
 *               of cache behavior or multithreading requirements.
 * keepdims    : If true, leaves the reduction dimensions in the result
 *               with size one.
 * subok       : If true, the result uses the subclass of operand, otherwise
 *               it is always a base class ndarray.
 * assign_identity : If NULL, PyArray_InitializeReduceResult is used, otherwise
 *               this function is called to initialize the result to
 *               the reduction's unit.
 * loop        : The loop which does the reduction.
 * data        : Data which is passed to assign_identity and the inner loop.
 * buffersize  : Buffer size for the iterator. For the default, pass in 0.
 * funcname    : The name of the reduction function, for error messages.
 *
 * TODO FIXME: if you squint, this is essentially an second independent
 * implementation of generalized ufuncs with signature (i)->(), plus a few
 * extra bells and whistles. (Indeed, as far as I can tell, it was originally
 * split out to support a fancy version of count_nonzero... which is not
 * actually a reduction function at all, it's just a (i)->() function!) So
 * probably these two implementation should be merged into one. (In fact it
 * would be quite nice to support axis= and keepdims etc. for arbitrary
 * generalized ufuncs!)
 */
NPY_NO_EXPORT PyArrayObject *
PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out,
                      PyArrayObject *wheremask,
                      PyArray_Descr *operand_dtype,
                      PyArray_Descr *result_dtype,
                      NPY_CASTING casting,
                      npy_bool *axis_flags, int reorderable,
                      int keepdims,
                      int subok,
                      PyArray_AssignReduceIdentityFunc *assign_identity,
                      PyArray_ReduceLoopFunc *loop,
                      void *data, npy_intp buffersize, const char *funcname)
{
    PyArrayObject *result = NULL, *op_view = NULL;
    npy_intp skip_first_count = 0;

    /* Iterator parameters */
    NpyIter *iter = NULL;
    PyArrayObject *op[2];
    PyArray_Descr *op_dtypes[2];
    npy_uint32 flags, op_flags[2];

    /* Validate that the parameters for future expansion are NULL */
    if (wheremask != NULL) {
        PyErr_SetString(PyExc_RuntimeError,
                "Reduce operations in NumPy do not yet support "
                "a where mask");
        return NULL;
    }

    /*
     * This either conforms 'out' to the ndim of 'operand', or allocates
     * a new array appropriate for this reduction.
     */
    Py_INCREF(result_dtype);
    result = PyArray_CreateReduceResult(operand, out,
                            result_dtype, axis_flags,
                            keepdims, subok, funcname);
    if (result == NULL) {
        goto fail;
    }

    /*
     * Initialize the result to the reduction unit if possible,
     * otherwise copy the initial values and get a view to the rest.
     */
    if (assign_identity != NULL) {
        /*
         * If this reduction is non-reorderable, make sure there are
         * only 0 or 1 axes in axis_flags.
         */
        if (!reorderable && check_nonreorderable_axes(PyArray_NDIM(operand),
                                        axis_flags, funcname) < 0) {
            goto fail;
        }

        if (assign_identity(result, data) < 0) {
            goto fail;
        }
        op_view = operand;
        Py_INCREF(op_view);
    }
    else {
        op_view = PyArray_InitializeReduceResult(result, operand,
                            axis_flags, reorderable,
                            &skip_first_count, funcname);
        if (op_view == NULL) {
            goto fail;
        }
        if (PyArray_SIZE(op_view) == 0) {
            Py_DECREF(op_view);
            op_view = NULL;
            goto finish;
        }
    }

    /* Set up the iterator */
    op[0] = result;
    op[1] = op_view;
    op_dtypes[0] = result_dtype;
    op_dtypes[1] = operand_dtype;

    flags = NPY_ITER_BUFFERED |
            NPY_ITER_EXTERNAL_LOOP |
            NPY_ITER_GROWINNER |
            NPY_ITER_DONT_NEGATE_STRIDES |
            NPY_ITER_ZEROSIZE_OK |
            NPY_ITER_REDUCE_OK |
            NPY_ITER_REFS_OK;
    op_flags[0] = NPY_ITER_READWRITE |
                  NPY_ITER_ALIGNED |
                  NPY_ITER_NO_SUBTYPE;
    op_flags[1] = NPY_ITER_READONLY |
                  NPY_ITER_ALIGNED;

    iter = NpyIter_AdvancedNew(2, op, flags,
                               NPY_KEEPORDER, casting,
                               op_flags,
                               op_dtypes,
                               0, NULL, NULL, buffersize);
    if (iter == NULL) {
        goto fail;
    }

    if (NpyIter_GetIterSize(iter) != 0) {
        NpyIter_IterNextFunc *iternext;
        char **dataptr;
        npy_intp *strideptr;
        npy_intp *countptr;
        int needs_api;

        iternext = NpyIter_GetIterNext(iter, NULL);
        if (iternext == NULL) {
            goto fail;
        }
        dataptr = NpyIter_GetDataPtrArray(iter);
        strideptr = NpyIter_GetInnerStrideArray(iter);
        countptr = NpyIter_GetInnerLoopSizePtr(iter);

        needs_api = NpyIter_IterationNeedsAPI(iter);

        /* Straightforward reduction */
        if (loop == NULL) {
            PyErr_Format(PyExc_RuntimeError,
                    "reduction operation %s did not supply an "
                    "inner loop function", funcname);
            goto fail;
        }

        if (loop(iter, dataptr, strideptr, countptr,
                        iternext, needs_api, skip_first_count, data) < 0) {

            goto fail;
        }
    }

    NpyIter_Deallocate(iter);
    Py_DECREF(op_view);

finish:
    /* Strip out the extra 'one' dimensions in the result */
    if (out == NULL) {
        if (!keepdims) {
            PyArray_RemoveAxesInPlace(result, axis_flags);
        }
    }
    else {
        Py_DECREF(result);
        result = out;
        Py_INCREF(result);
    }

    return result;

fail:
    Py_XDECREF(result);
    Py_XDECREF(op_view);
    if (iter != NULL) {
        NpyIter_Deallocate(iter);
    }

    return NULL;
}
Exemple #25
0
static PyObject *Py_FindObjects(PyObject *obj, PyObject *args)
{
    PyArrayObject *input = NULL;
    PyObject *result = NULL, *tuple = NULL, *start = NULL, *end = NULL;
    PyObject *slc = NULL;
    int jj;
    npy_intp max_label;
    npy_intp ii, *regions = NULL;

    if (!PyArg_ParseTuple(args, "O&n",
                          NI_ObjectToInputArray, &input, &max_label))
        goto exit;

    if (max_label < 0)
        max_label = 0;
    if (max_label > 0) {
        if (PyArray_NDIM(input) > 0) {
            regions = (npy_intp*)malloc(2 * max_label * PyArray_NDIM(input) *
                                        sizeof(npy_intp));
        } else {
            regions = (npy_intp*)malloc(max_label * sizeof(npy_intp));
        }
        if (!regions) {
            PyErr_NoMemory();
            goto exit;
        }
    }

    if (!NI_FindObjects(input, max_label, regions))
        goto exit;

    result = PyList_New(max_label);
    if (!result) {
        PyErr_NoMemory();
        goto exit;
    }

    for(ii = 0; ii < max_label; ii++) {
        npy_intp idx =
                PyArray_NDIM(input) > 0 ? 2 * PyArray_NDIM(input) * ii : ii;
        if (regions[idx] >= 0) {
            PyObject *tuple = PyTuple_New(PyArray_NDIM(input));
            if (!tuple) {
                PyErr_NoMemory();
                goto exit;
            }
            for(jj = 0; jj < PyArray_NDIM(input); jj++) {
                start = PyLong_FromSsize_t(regions[idx + jj]);
                end = PyLong_FromSsize_t(regions[idx + jj +
                                             PyArray_NDIM(input)]);
                if (!start || !end) {
                    PyErr_NoMemory();
                    goto exit;
                }
                slc = PySlice_New(start, end, NULL);
                if (!slc) {
                    PyErr_NoMemory();
                    goto exit;
                }
                Py_XDECREF(start);
                Py_XDECREF(end);
                start = end = NULL;
                PyTuple_SetItem(tuple, jj, slc);
                slc = NULL;
            }
            PyList_SetItem(result, ii, tuple);
            tuple = NULL;
        } else {
            Py_INCREF(Py_None);
            PyList_SetItem(result, ii, Py_None);
        }
    }

    Py_INCREF(result);

 exit:
    Py_XDECREF(input);
    Py_XDECREF(result);
    Py_XDECREF(tuple);
    Py_XDECREF(start);
    Py_XDECREF(end);
    Py_XDECREF(slc);
    free(regions);
    if (PyErr_Occurred()) {
        Py_XDECREF(result);
        return NULL;
    } else {
        return result;
    }
}
Exemple #26
0
/*
 * Conforms an output parameter 'out' to have 'ndim' dimensions
 * with dimensions of size one added in the appropriate places
 * indicated by 'axis_flags'.
 *
 * The return value is a view into 'out'.
 */
static PyArrayObject *
conform_reduce_result(int ndim, npy_bool *axis_flags,
                    PyArrayObject *out, int keepdims, const char *funcname)
{
    npy_intp strides[NPY_MAXDIMS], shape[NPY_MAXDIMS];
    npy_intp *strides_out = PyArray_STRIDES(out);
    npy_intp *shape_out = PyArray_DIMS(out);
    int idim, idim_out, ndim_out = PyArray_NDIM(out);
    PyArray_Descr *dtype;
    PyArrayObject_fields *ret;

    /*
     * If the 'keepdims' parameter is true, do a simpler validation and
     * return a new reference to 'out'.
     */
    if (keepdims) {
        if (PyArray_NDIM(out) != ndim) {
            PyErr_Format(PyExc_ValueError,
                    "output parameter for reduction operation %s "
                    "has the wrong number of dimensions (must match "
                    "the operand's when keepdims=True)", funcname);
            return NULL;
        }

        for (idim = 0; idim < ndim; ++idim) {
            if (axis_flags[idim]) {
                if (shape_out[idim] != 1) {
                    PyErr_Format(PyExc_ValueError,
                            "output parameter for reduction operation %s "
                            "has a reduction dimension not equal to one "
                            "(required when keepdims=True)", funcname);
                    return NULL;
                }
            }
        }

        Py_INCREF(out);
        return out;
    }

    /* Construct the strides and shape */
    idim_out = 0;
    for (idim = 0; idim < ndim; ++idim) {
        if (axis_flags[idim]) {
            strides[idim] = 0;
            shape[idim] = 1;
        }
        else {
            if (idim_out >= ndim_out) {
                PyErr_Format(PyExc_ValueError,
                        "output parameter for reduction operation %s "
                        "does not have enough dimensions", funcname);
                return NULL;
            }
            strides[idim] = strides_out[idim_out];
            shape[idim] = shape_out[idim_out];
            ++idim_out;
        }
    }

    if (idim_out != ndim_out) {
        PyErr_Format(PyExc_ValueError,
                "output parameter for reduction operation %s "
                "has too many dimensions", funcname);
        return NULL;
    }

    /* Allocate the view */
    dtype = PyArray_DESCR(out);
    Py_INCREF(dtype);
    ret = (PyArrayObject_fields *)PyArray_NewFromDescr(&PyArray_Type,
                               dtype,
                               ndim, shape,
                               strides,
                               PyArray_DATA(out),
                               PyArray_FLAGS(out),
                               NULL);
    if (ret == NULL) {
        return NULL;
    }
    Py_INCREF(out);
    if (PyArray_SetBaseObject((PyArrayObject *)ret, (PyObject *)out) < 0) {
        Py_DECREF(ret);
        return NULL;
    }

    return (PyArrayObject *)ret;
}
Exemple #27
0
/*NUMPY_API
 * ArgMax
 */
NPY_NO_EXPORT PyObject *
PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
{
    PyArrayObject *ap = NULL, *rp = NULL;
    PyArray_ArgFunc* arg_func;
    char *ip;
    npy_intp *rptr;
    npy_intp i, n, m;
    int elsize;
    NPY_BEGIN_THREADS_DEF;

    if ((ap = (PyArrayObject *)PyArray_CheckAxis(op, &axis, 0)) == NULL) {
        return NULL;
    }
    /*
     * We need to permute the array so that axis is placed at the end.
     * And all other dimensions are shifted left.
     */
    if (axis != PyArray_NDIM(ap)-1) {
        PyArray_Dims newaxes;
        npy_intp dims[NPY_MAXDIMS];
        int j;

        newaxes.ptr = dims;
        newaxes.len = PyArray_NDIM(ap);
        for (j = 0; j < axis; j++) {
            dims[j] = j;
        }
        for (j = axis; j < PyArray_NDIM(ap) - 1; j++) {
            dims[j] = j + 1;
        }
        dims[PyArray_NDIM(ap) - 1] = axis;
        op = (PyArrayObject *)PyArray_Transpose(ap, &newaxes);
        Py_DECREF(ap);
        if (op == NULL) {
            return NULL;
        }
    }
    else {
        op = ap;
    }

    /* Will get native-byte order contiguous copy. */
    ap = (PyArrayObject *)PyArray_ContiguousFromAny((PyObject *)op,
                                  PyArray_DESCR(op)->type_num, 1, 0);
    Py_DECREF(op);
    if (ap == NULL) {
        return NULL;
    }
    arg_func = PyArray_DESCR(ap)->f->argmax;
    if (arg_func == NULL) {
        PyErr_SetString(PyExc_TypeError,
                "data type not ordered");
        goto fail;
    }
    elsize = PyArray_DESCR(ap)->elsize;
    m = PyArray_DIMS(ap)[PyArray_NDIM(ap)-1];
    if (m == 0) {
        PyErr_SetString(PyExc_ValueError,
                "attempt to get argmax of an empty sequence");
        goto fail;
    }

    if (!out) {
        rp = (PyArrayObject *)PyArray_New(Py_TYPE(ap), PyArray_NDIM(ap)-1,
                                          PyArray_DIMS(ap), NPY_INTP,
                                          NULL, NULL, 0, 0,
                                          (PyObject *)ap);
        if (rp == NULL) {
            goto fail;
        }
    }
    else {
        if ((PyArray_NDIM(out) != PyArray_NDIM(ap) - 1) ||
                !PyArray_CompareLists(PyArray_DIMS(out), PyArray_DIMS(ap),
                                      PyArray_NDIM(out))) {
            PyErr_SetString(PyExc_ValueError,
                    "output array does not match result of np.argmax.");
            goto fail;
        }
        rp = (PyArrayObject *)PyArray_FromArray(out,
                              PyArray_DescrFromType(NPY_INTP),
                              NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY);
        if (rp == NULL) {
            goto fail;
        }
    }

    NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ap));
    n = PyArray_SIZE(ap)/m;
    rptr = (npy_intp *)PyArray_DATA(rp);
    for (ip = PyArray_DATA(ap), i = 0; i < n; i++, ip += elsize*m) {
        arg_func(ip, m, rptr, ap);
        rptr += 1;
    }
    NPY_END_THREADS_DESCR(PyArray_DESCR(ap));

    Py_DECREF(ap);
    /* Trigger the UPDATEIFCOPY if necessary */
    if (out != NULL && out != rp) {
        Py_DECREF(rp);
        rp = out;
        Py_INCREF(rp);
    }
    return (PyObject *)rp;

 fail:
    Py_DECREF(ap);
    Py_XDECREF(rp);
    return NULL;
}
Exemple #28
0
NPY_NO_EXPORT int
PyArray_WeekMaskConverter(PyObject *weekmask_in, npy_bool *weekmask)
{
    PyObject *obj = weekmask_in;

    /* Make obj into an ASCII string if it is UNICODE */
    Py_INCREF(obj);
    if (PyUnicode_Check(obj)) {
        /* accept unicode input */
        PyObject *obj_str;
        obj_str = PyUnicode_AsASCIIString(obj);
        if (obj_str == NULL) {
            Py_DECREF(obj);
            return 0;
        }
        Py_DECREF(obj);
        obj = obj_str;
    }

    if (PyBytes_Check(obj)) {
        char *str;
        Py_ssize_t len;
        int i;

        if (PyBytes_AsStringAndSize(obj, &str, &len) < 0) {
            Py_DECREF(obj);
            return 0;
        }

        /* Length 7 is a string like "1111100" */
        if (len == 7) {
            for (i = 0; i < 7; ++i) {
                switch(str[i]) {
                    case '0':
                        weekmask[i] = 0;
                        break;
                    case '1':
                        weekmask[i] = 1;
                        break;
                    default:
                        goto general_weekmask_string;
                }
            }

            goto finish;
        }

general_weekmask_string:
        /* a string like "SatSun" or "Mon Tue Wed" */
        memset(weekmask, 0, 7);
        for (i = 0; i < len; i += 3) {
            while (isspace(str[i]))
                ++i;

            if (i == len) {
                goto finish;
            }
            else if (i + 2 >= len) {
                goto invalid_weekmask_string;
            }

            switch (str[i]) {
                case 'M':
                    if (str[i+1] == 'o' && str[i+2] == 'n') {
                        weekmask[0] = 1;
                    }
                    else {
                        goto invalid_weekmask_string;
                    }
                    break;
                case 'T':
                    if (str[i+1] == 'u' && str[i+2] == 'e') {
                        weekmask[1] = 1;
                    }
                    else if (str[i+1] == 'h' && str[i+2] == 'u') {
                        weekmask[3] = 1;
                    }
                    else {
                        goto invalid_weekmask_string;
                    }
                    break;
                case 'W':
                    if (str[i+1] == 'e' && str[i+2] == 'd') {
                        weekmask[2] = 1;
                    }
                    else {
                        goto invalid_weekmask_string;
                    }
                    break;
                case 'F':
                    if (str[i+1] == 'r' && str[i+2] == 'i') {
                        weekmask[4] = 1;
                    }
                    else {
                        goto invalid_weekmask_string;
                    }
                    break;
                case 'S':
                    if (str[i+1] == 'a' && str[i+2] == 't') {
                        weekmask[5] = 1;
                    }
                    else if (str[i+1] == 'u' && str[i+2] == 'n') {
                        weekmask[6] = 1;
                    }
                    else {
                        goto invalid_weekmask_string;
                    }
                    break;
                default:
                    goto invalid_weekmask_string;
            }
        }

        goto finish;

invalid_weekmask_string:
        PyErr_Format(PyExc_ValueError,
                "Invalid business day weekmask string \"%s\"",
                str);
        Py_DECREF(obj);
        return 0;
    }
    /* Something like [1,1,1,1,1,0,0] */
    else if (PySequence_Check(obj)) {
        if (PySequence_Size(obj) != 7 ||
                        (PyArray_Check(obj) &&
                         PyArray_NDIM((PyArrayObject *)obj) != 1)) {
            PyErr_SetString(PyExc_ValueError,
                "A business day weekmask array must have length 7");
            Py_DECREF(obj);
            return 0;
        }
        else {
            int i;
            PyObject *f;

            for (i = 0; i < 7; ++i) {
                long val;

                f = PySequence_GetItem(obj, i);
                if (f == NULL) {
                    Py_DECREF(obj);
                    return 0;
                }

                val = PyInt_AsLong(f);
                if (val == -1 && PyErr_Occurred()) {
                    Py_DECREF(obj);
                    return 0;
                }
                if (val == 0) {
                    weekmask[i] = 0;
                }
                else if (val == 1) {
                    weekmask[i] = 1;
                }
                else {
                    PyErr_SetString(PyExc_ValueError,
                        "A business day weekmask array must have all "
                        "1's and 0's");
                    Py_DECREF(obj);
                    return 0;
                }
            }

            goto finish;
        }
    }

    PyErr_SetString(PyExc_ValueError,
            "Couldn't convert object into a business day weekmask");
    Py_DECREF(obj);
    return 0;

finish:
    Py_DECREF(obj);
    return 1;
}
Exemple #29
0
/*NUMPY_API
 * Clip
 */
NPY_NO_EXPORT PyObject *
PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out)
{
    PyArray_FastClipFunc *func;
    int outgood = 0, ingood = 0;
    PyArrayObject *maxa = NULL;
    PyArrayObject *mina = NULL;
    PyArrayObject *newout = NULL, *newin = NULL;
    PyArray_Descr *indescr = NULL, *newdescr = NULL;
    char *max_data, *min_data;
    PyObject *zero;

    /* Treat None the same as NULL */
    if (min == Py_None) {
        min = NULL;
    }
    if (max == Py_None) {
        max = NULL;
    }

    if ((max == NULL) && (min == NULL)) {
        PyErr_SetString(PyExc_ValueError,
                        "array_clip: must set either max or min");
        return NULL;
    }

    func = PyArray_DESCR(self)->f->fastclip;
    if (func == NULL
        || (min != NULL && !PyArray_CheckAnyScalar(min))
        || (max != NULL && !PyArray_CheckAnyScalar(max))) {
        return _slow_array_clip(self, min, max, out);
    }
    /* Use the fast scalar clip function */

    /* First we need to figure out the correct type */
    if (min != NULL) {
        indescr = PyArray_DescrFromObject(min, NULL);
        if (indescr == NULL) {
            goto fail;
        }
    }
    if (max != NULL) {
        newdescr = PyArray_DescrFromObject(max, indescr);
        Py_XDECREF(indescr);
        indescr = NULL;
        if (newdescr == NULL) {
            goto fail;
        }
    }
    else {
        /* Steal the reference */
        newdescr = indescr;
        indescr = NULL;
    }


    /*
     * Use the scalar descriptor only if it is of a bigger
     * KIND than the input array (and then find the
     * type that matches both).
     */
    if (PyArray_ScalarKind(newdescr->type_num, NULL) >
        PyArray_ScalarKind(PyArray_DESCR(self)->type_num, NULL)) {
        indescr = PyArray_PromoteTypes(newdescr, PyArray_DESCR(self));
        if (indescr == NULL) {
            goto fail;
        }
        func = indescr->f->fastclip;
        if (func == NULL) {
            Py_DECREF(indescr);
            return _slow_array_clip(self, min, max, out);
        }
    }
    else {
        indescr = PyArray_DESCR(self);
        Py_INCREF(indescr);
    }
    Py_DECREF(newdescr);
    newdescr = NULL;

    if (!PyDataType_ISNOTSWAPPED(indescr)) {
        PyArray_Descr *descr2;
        descr2 = PyArray_DescrNewByteorder(indescr, '=');
        Py_DECREF(indescr);
        indescr = NULL;
        if (descr2 == NULL) {
            goto fail;
        }
        indescr = descr2;
    }

    /* Convert max to an array */
    if (max != NULL) {
        Py_INCREF(indescr);
        maxa = (PyArrayObject *)PyArray_FromAny(max, indescr, 0, 0,
                                 NPY_ARRAY_DEFAULT, NULL);
        if (maxa == NULL) {
            goto fail;
        }
    }

    /*
     * If we are unsigned, then make sure min is not < 0
     * This is to match the behavior of _slow_array_clip
     *
     * We allow min and max to go beyond the limits
     * for other data-types in which case they
     * are interpreted as their modular counterparts.
    */
    if (min != NULL) {
        if (PyArray_ISUNSIGNED(self)) {
            int cmp;
            zero = PyInt_FromLong(0);
            cmp = PyObject_RichCompareBool(min, zero, Py_LT);
            if (cmp == -1) {
                Py_DECREF(zero);
                goto fail;
            }
            if (cmp == 1) {
                min = zero;
            }
            else {
                Py_DECREF(zero);
                Py_INCREF(min);
            }
        }
        else {
            Py_INCREF(min);
        }

        /* Convert min to an array */
        Py_INCREF(indescr);
        mina = (PyArrayObject *)PyArray_FromAny(min, indescr, 0, 0,
                                 NPY_ARRAY_DEFAULT, NULL);
        Py_DECREF(min);
        if (mina == NULL) {
            goto fail;
        }
    }


    /*
     * Check to see if input is single-segment, aligned,
     * and in native byteorder
     */
    if (PyArray_ISONESEGMENT(self) &&
                            PyArray_CHKFLAGS(self, NPY_ARRAY_ALIGNED) &&
                            PyArray_ISNOTSWAPPED(self) &&
                            (PyArray_DESCR(self) == indescr)) {
        ingood = 1;
    }
    if (!ingood) {
        int flags;

        if (PyArray_ISFORTRAN(self)) {
            flags = NPY_ARRAY_FARRAY;
        }
        else {
            flags = NPY_ARRAY_CARRAY;
        }
        Py_INCREF(indescr);
        newin = (PyArrayObject *)PyArray_FromArray(self, indescr, flags);
        if (newin == NULL) {
            goto fail;
        }
    }
    else {
        newin = self;
        Py_INCREF(newin);
    }

    /*
     * At this point, newin is a single-segment, aligned, and correct
     * byte-order array of the correct type
     *
     * if ingood == 0, then it is a copy, otherwise,
     * it is the original input.
     */

    /*
     * If we have already made a copy of the data, then use
     * that as the output array
     */
    if (out == NULL && !ingood) {
        out = newin;
    }

    /*
     * Now, we know newin is a usable array for fastclip,
     * we need to make sure the output array is available
     * and usable
     */
    if (out == NULL) {
        Py_INCREF(indescr);
        out = (PyArrayObject*)PyArray_NewFromDescr(Py_TYPE(self),
                                            indescr, PyArray_NDIM(self),
                                            PyArray_DIMS(self),
                                            NULL, NULL,
                                            PyArray_ISFORTRAN(self),
                                            (PyObject *)self);
        if (out == NULL) {
            goto fail;
        }

        outgood = 1;
    }
    else Py_INCREF(out);
    /* Input is good at this point */
    if (out == newin) {
        outgood = 1;
    }
    if (!outgood && PyArray_ISONESEGMENT(out) &&
                        PyArray_CHKFLAGS(out, NPY_ARRAY_ALIGNED) &&
                        PyArray_ISNOTSWAPPED(out) &&
                        PyArray_EquivTypes(PyArray_DESCR(out), indescr)) {
        outgood = 1;
    }

    /*
     * Do we still not have a suitable output array?
     * Create one, now
     */
    if (!outgood) {
        int oflags;
        if (PyArray_ISFORTRAN(out))
            oflags = NPY_ARRAY_FARRAY;
        else
            oflags = NPY_ARRAY_CARRAY;
        oflags |= NPY_ARRAY_UPDATEIFCOPY | NPY_ARRAY_FORCECAST;
        Py_INCREF(indescr);
        newout = (PyArrayObject*)PyArray_FromArray(out, indescr, oflags);
        if (newout == NULL) {
            goto fail;
        }
    }
    else {
        newout = out;
        Py_INCREF(newout);
    }

    /* make sure the shape of the output array is the same */
    if (!PyArray_SAMESHAPE(newin, newout)) {
        PyErr_SetString(PyExc_ValueError, "clip: Output array must have the"
                        "same shape as the input.");
        goto fail;
    }
    if (PyArray_DATA(newout) != PyArray_DATA(newin)) {
        if (PyArray_AssignArray(newout, newin,
                    NULL, NPY_DEFAULT_ASSIGN_CASTING) < 0) {
            goto fail;
        }
    }

    /* Now we can call the fast-clip function */
    min_data = max_data = NULL;
    if (mina != NULL) {
        min_data = PyArray_DATA(mina);
    }
    if (maxa != NULL) {
        max_data = PyArray_DATA(maxa);
    }
    func(PyArray_DATA(newin), PyArray_SIZE(newin), min_data, max_data, PyArray_DATA(newout));

    /* Clean up temporary variables */
    Py_XDECREF(indescr);
    Py_XDECREF(newdescr);
    Py_XDECREF(mina);
    Py_XDECREF(maxa);
    Py_DECREF(newin);
    /* Copy back into out if out was not already a nice array. */
    Py_DECREF(newout);
    return (PyObject *)out;

 fail:
    Py_XDECREF(indescr);
    Py_XDECREF(newdescr);
    Py_XDECREF(maxa);
    Py_XDECREF(mina);
    Py_XDECREF(newin);
    PyArray_XDECREF_ERR(newout);
    return NULL;
}
Exemple #30
0
Py::Object
_path_module::affine_transform(const Py::Tuple& args)
{
    args.verify_length(2);

    Py::Object vertices_obj = args[0];
    Py::Object transform_obj = args[1];

    PyArrayObject* vertices = NULL;
    PyArrayObject* transform = NULL;
    PyArrayObject* result = NULL;

    try
    {
        vertices = (PyArrayObject*)PyArray_FromObject
                   (vertices_obj.ptr(), PyArray_DOUBLE, 1, 2);
        if (!vertices ||
            (PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 0) != 0 &&
             PyArray_DIM(vertices, 1) != 2) ||
            (PyArray_NDIM(vertices) == 1 &&
             PyArray_DIM(vertices, 0) != 2 && PyArray_DIM(vertices, 0) != 0))
        {
            throw Py::ValueError("Invalid vertices array.");
        }

        transform = (PyArrayObject*) PyArray_FromObject
                    (transform_obj.ptr(), PyArray_DOUBLE, 2, 2);
        if (!transform ||
            PyArray_DIM(transform, 0) != 3 ||
            PyArray_DIM(transform, 1) != 3)
        {
            throw Py::ValueError("Invalid transform.");
        }

        double a, b, c, d, e, f;
        {
            size_t stride0 = PyArray_STRIDE(transform, 0);
            size_t stride1 = PyArray_STRIDE(transform, 1);
            char* row0 = PyArray_BYTES(transform);
            char* row1 = row0 + stride0;

            a = *(double*)(row0);
            row0 += stride1;
            c = *(double*)(row0);
            row0 += stride1;
            e = *(double*)(row0);

            b = *(double*)(row1);
            row1 += stride1;
            d = *(double*)(row1);
            row1 += stride1;
            f = *(double*)(row1);
        }

        result = (PyArrayObject*)PyArray_SimpleNew
                 (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE);
        if (result == NULL)
        {
            throw Py::MemoryError("Could not allocate memory for path");
        }
        if (PyArray_NDIM(vertices) == 2)
        {
            size_t n = PyArray_DIM(vertices, 0);
            char* vertex_in = PyArray_BYTES(vertices);
            double* vertex_out = (double*)PyArray_DATA(result);
            size_t stride0 = PyArray_STRIDE(vertices, 0);
            size_t stride1 = PyArray_STRIDE(vertices, 1);
            double x;
            double y;

            for (size_t i = 0; i < n; ++i)
            {
                x = *(double*)(vertex_in);
                y = *(double*)(vertex_in + stride1);

                *vertex_out++ = a * x + c * y + e;
                *vertex_out++ = b * x + d * y + f;

                vertex_in += stride0;
            }
        }
        else if (PyArray_DIM(vertices, 0) != 0)
        {
            char* vertex_in = PyArray_BYTES(vertices);
            double* vertex_out = (double*)PyArray_DATA(result);
            size_t stride0 = PyArray_STRIDE(vertices, 0);
            double x;
            double y;
            x = *(double*)(vertex_in);
            y = *(double*)(vertex_in + stride0);
            *vertex_out++ = a * x + c * y + e;
            *vertex_out++ = b * x + d * y + f;
        }
    }
    catch (...)
    {
        Py_XDECREF(vertices);
        Py_XDECREF(transform);
        Py_XDECREF(result);
        throw;
    }

    Py_XDECREF(vertices);
    Py_XDECREF(transform);

    return Py::Object((PyObject*)result, true);
}