static PyObject* write_coords(PyObject* self, PyObject* args) { oskar_MeasurementSet* h = 0; PyObject *capsule = 0; PyObject *obj[] = {0, 0, 0}; PyArrayObject *uu = 0, *vv = 0, *ww = 0; int start_row = 0, num_baselines = 0; double exposure_sec = 0.0, interval_sec = 0.0, time_stamp = 0.0; if (!PyArg_ParseTuple(args, "OiiOOOddd", &capsule, &start_row, &num_baselines, &obj[0], &obj[1], &obj[2], &exposure_sec, &interval_sec, &time_stamp)) return 0; if (!(h = (oskar_MeasurementSet*) get_handle(capsule, name))) return 0; /* Make sure input objects are arrays. Convert if required. */ uu = (PyArrayObject*) PyArray_FROM_OF(obj[0], NPY_ARRAY_IN_ARRAY); vv = (PyArrayObject*) PyArray_FROM_OF(obj[1], NPY_ARRAY_IN_ARRAY); ww = (PyArrayObject*) PyArray_FROM_OF(obj[2], NPY_ARRAY_IN_ARRAY); if (!uu || !vv || !ww) goto fail; /* Check dimensions. */ if (num_baselines != (int) PyArray_SIZE(uu) || num_baselines != (int) PyArray_SIZE(vv) || num_baselines != (int) PyArray_SIZE(ww)) { PyErr_SetString(PyExc_RuntimeError, "Input data dimension mismatch."); goto fail; } /* Write the coordinates. */ Py_BEGIN_ALLOW_THREADS if (PyArray_TYPE(uu) == NPY_DOUBLE) oskar_ms_write_coords_d(h, start_row, num_baselines, (const double*)PyArray_DATA(uu), (const double*)PyArray_DATA(vv), (const double*)PyArray_DATA(ww), exposure_sec, interval_sec, time_stamp); else oskar_ms_write_coords_f(h, start_row, num_baselines, (const float*)PyArray_DATA(uu), (const float*)PyArray_DATA(vv), (const float*)PyArray_DATA(ww), exposure_sec, interval_sec, time_stamp); Py_END_ALLOW_THREADS Py_XDECREF(uu); Py_XDECREF(vv); Py_XDECREF(ww); return Py_BuildValue(""); fail: Py_XDECREF(uu); Py_XDECREF(vv); Py_XDECREF(ww); return 0; }
static PyObject* write_vis(PyObject* self, PyObject* args) { oskar_MeasurementSet* h = 0; PyObject *capsule = 0; PyObject *obj = 0; PyArrayObject *vis = 0; int start_row = 0, start_channel = 0; int num_channels = 0, num_baselines = 0, num_pols = 0; if (!PyArg_ParseTuple(args, "OiiiiO", &capsule, &start_row, &start_channel, &num_channels, &num_baselines, &obj)) return 0; if (!(h = get_handle(capsule))) return 0; /* Make sure input objects are arrays. Convert if required. */ vis = (PyArrayObject*) PyArray_FROM_OF(obj, NPY_ARRAY_IN_ARRAY); if (!vis) goto fail; /* Get precision of complex visibility data. */ if (!PyArray_ISCOMPLEX(vis)) { PyErr_SetString(PyExc_RuntimeError, "Input visibility data must be complex."); goto fail; } /* Check dimensions. */ num_pols = oskar_ms_num_pols(h); if (num_baselines * num_channels * num_pols != (int) PyArray_SIZE(vis)) { PyErr_SetString(PyExc_RuntimeError, "Input data dimension mismatch."); goto fail; } /* Allow threads. */ Py_BEGIN_ALLOW_THREADS /* Write the visibilities. */ if (PyArray_TYPE(vis) == NPY_DOUBLE) oskar_ms_write_vis_d(h, start_row, start_channel, num_channels, num_baselines, (const double*)PyArray_DATA(vis)); else oskar_ms_write_vis_f(h, start_row, start_channel, num_channels, num_baselines, (const float*)PyArray_DATA(vis)); /* Disallow threads. */ Py_END_ALLOW_THREADS Py_XDECREF(vis); return Py_BuildValue(""); fail: Py_XDECREF(vis); return 0; }
/*NUMPY_API * * Useful to pass as converter function for O& processing in PyArgs_ParseTuple. * * This conversion function can be used with the "O&" argument for * PyArg_ParseTuple. It will immediately return an object of array type * or will convert to a NPY_ARRAY_CARRAY any other object. * * If you use PyArray_Converter, you must DECREF the array when finished * as you get a new reference to it. */ NPY_NO_EXPORT int PyArray_Converter(PyObject *object, PyObject **address) { if (PyArray_Check(object)) { *address = object; Py_INCREF(object); return NPY_SUCCEED; } else { *address = PyArray_FROM_OF(object, NPY_ARRAY_CARRAY); if (*address == NULL) { return NPY_FAIL; } return NPY_SUCCEED; } }
static size_t wrap_send(uhd::tx_streamer *tx_stream, bp::object &np_array, bp::object &metadata, const double timeout = 0.1) { // Extract the metadata bp::extract<uhd::tx_metadata_t&> get_metadata(metadata); // TODO: throw an error here? if (not get_metadata.check()) { return 0; } // Get a numpy array object from given python object // No sanity checking possible! // Note: this increases the ref count, which we'll need to manually decrease at the end PyObject* array_obj = PyArray_FROM_OF(np_array.ptr(),NPY_ARRAY_CARRAY); PyArrayObject* array_type_obj = reinterpret_cast<PyArrayObject*>(array_obj); // Get dimensions of the numpy array const size_t dims = PyArray_NDIM(array_type_obj); const npy_intp* shape = PyArray_SHAPE(array_type_obj); // How many bytes to jump to get to the next element of the stride // (next row) const npy_intp* strides = PyArray_STRIDES(array_type_obj); const size_t channels = tx_stream->get_num_channels(); // Check if numpy array sizes are ok if (((channels > 1) && (dims != 2)) or ((size_t) shape[0] < channels)) { // Manually decrement the ref count Py_DECREF(array_obj); // If we don't have a 2D NumPy array, assume we have a 1D array size_t input_channels = (dims != 2) ? 1 : shape[0]; throw uhd::runtime_error(str(boost::format( "Number of TX channels (%d) does not match the dimensions of the data array (%d)") % channels % input_channels)); } // Get a pointer to the storage std::vector<void*> channel_storage; char* data = PyArray_BYTES(array_type_obj); for (size_t i = 0; i < channels; ++i) { channel_storage.push_back((void*)(data + i * strides[0])); } // Get data buffer and size of the array size_t nsamps_per_buff = (dims > 1) ? (size_t) shape[1] : PyArray_SIZE(array_type_obj); // Release the GIL only for the send() call const size_t result = [&]() { scoped_gil_release gil_release; // Call the real send() return tx_stream->send( channel_storage, nsamps_per_buff, get_metadata(), timeout ); }(); // Manually decrement the ref count Py_DECREF(array_obj); return result; }
/* * Returns input array with values inserted sequentially into places * indicated by the mask */ NPY_NO_EXPORT PyObject * arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) { PyObject *mask = NULL, *vals = NULL; PyArrayObject *ainput = NULL, *amask = NULL, *avals = NULL, *tmp = NULL; int numvals, totmask, sameshape; char *input_data, *mptr, *vptr, *zero = NULL; int melsize, delsize, nd, objarray, k; npy_intp *instrides, *inshape; static char *kwlist[] = {"input", "mask", "vals", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O&OO", kwlist, PyArray_Converter, &ainput, &mask, &vals)) { goto fail; } amask = (PyArrayObject *)PyArray_FROM_OF(mask, NPY_ARRAY_CARRAY); if (amask == NULL) { goto fail; } /* Cast an object array */ if (PyArray_DESCR(amask)->type_num == NPY_OBJECT) { tmp = (PyArrayObject *)PyArray_Cast(amask, NPY_INTP); if (tmp == NULL) { goto fail; } Py_DECREF(amask); amask = tmp; } sameshape = 1; if (PyArray_NDIM(amask) == PyArray_NDIM(ainput)) { for (k = 0; k < PyArray_NDIM(amask); k++) { if (PyArray_DIMS(amask)[k] != PyArray_DIMS(ainput)[k]) { sameshape = 0; } } } else { /* Test to see if amask is 1d */ if (PyArray_NDIM(amask) != 1) { sameshape = 0; } else if ((PyArray_SIZE(ainput)) != PyArray_SIZE(amask)) { sameshape = 0; } } if (!sameshape) { PyErr_SetString(PyExc_TypeError, "mask array must be 1-d or same shape as input array"); goto fail; } avals = (PyArrayObject *)PyArray_FromObject(vals, PyArray_DESCR(ainput)->type_num, 0, 1); if (avals == NULL) { goto fail; } numvals = PyArray_SIZE(avals); nd = PyArray_NDIM(ainput); input_data = PyArray_DATA(ainput); mptr = PyArray_DATA(amask); melsize = PyArray_DESCR(amask)->elsize; vptr = PyArray_DATA(avals); delsize = PyArray_DESCR(avals)->elsize; zero = PyArray_Zero(amask); if (zero == NULL) { goto fail; } objarray = (PyArray_DESCR(ainput)->type_num == NPY_OBJECT); if (!numvals) { /* nothing to insert! fail unless none of mask is true */ const char *iter = mptr; const char *const last = iter + PyArray_NBYTES(amask); while (iter != last && !memcmp(iter, zero, melsize)) { iter += melsize; } if (iter != last) { PyErr_SetString(PyExc_ValueError, "Cannot insert from an empty array!"); goto fail; } goto finish; } /* Handle zero-dimensional case separately */ if (nd == 0) { if (memcmp(mptr,zero,melsize) != 0) { /* Copy value element over to input array */ memcpy(input_data,vptr,delsize); if (objarray) { Py_INCREF(*((PyObject **)vptr)); } } Py_DECREF(amask); Py_DECREF(avals); PyDataMem_FREE(zero); Py_DECREF(ainput); Py_RETURN_NONE; } totmask = (int) PyArray_SIZE(amask); instrides = PyArray_STRIDES(ainput); inshape = PyArray_DIMS(ainput); if (objarray) { /* object array, need to refcount, can't release the GIL */ arr_insert_loop(mptr, vptr, input_data, zero, PyArray_DATA(avals), melsize, delsize, objarray, totmask, numvals, nd, instrides, inshape); } else { /* No increfs take place in arr_insert_loop, so release the GIL */ NPY_BEGIN_ALLOW_THREADS; arr_insert_loop(mptr, vptr, input_data, zero, PyArray_DATA(avals), melsize, delsize, objarray, totmask, numvals, nd, instrides, inshape); NPY_END_ALLOW_THREADS; } finish: Py_DECREF(amask); Py_DECREF(avals); PyDataMem_FREE(zero); Py_DECREF(ainput); Py_RETURN_NONE; fail: PyDataMem_FREE(zero); Py_XDECREF(ainput); Py_XDECREF(amask); Py_XDECREF(avals); return NULL; }