static void write_pixels(oskar_Mem* data, const char* filename, int width, int height, int num_planes, int i_plane, int* status) { long naxes[3], firstpix[3], num_pix; int dims_ok = 0; fitsfile* f = 0; if (*status) return; if (oskar_file_exists(filename)) { int naxis = 0, imagetype = 0; fits_open_file(&f, filename, READWRITE, status); fits_get_img_param(f, 3, &imagetype, &naxis, naxes, status); if (naxis == 3 && naxes[0] == width && naxes[1] == height && naxes[2] == num_planes) { dims_ok = 1; } else { *status = 0; fits_close_file(f, status); remove(filename); f = 0; } } if (!dims_ok) { naxes[0] = width; naxes[1] = height; naxes[2] = num_planes; fits_create_file(&f, filename, status); fits_create_img(f, oskar_mem_is_double(data) ? DOUBLE_IMG : FLOAT_IMG, 3, naxes, status); } if (*status || !f) { if (f) fits_close_file(f, status); *status = OSKAR_ERR_FILE_IO; return; } num_pix = width * height; firstpix[0] = 1; firstpix[1] = 1; firstpix[2] = 1 + i_plane; if (i_plane < 0) { firstpix[2] = 1; num_pix *= num_planes; } fits_write_pix(f, oskar_mem_is_double(data) ? TDOUBLE : TFLOAT, firstpix, num_pix, oskar_mem_void(data), status); fits_close_file(f, status); }
static PyObject* auto_correlations(PyObject* self, PyObject* args) { oskar_VisBlock* h = 0; oskar_Mem* m = 0; PyObject *capsule = 0; PyArrayObject *array = 0; npy_intp dims[4]; if (!PyArg_ParseTuple(args, "O", &capsule)) return 0; if (!(h = (oskar_VisBlock*) get_handle(capsule, name))) return 0; /* Check that auto-correlations exist. */ if (!oskar_vis_block_has_auto_correlations(h)) { PyErr_SetString(PyExc_RuntimeError, "No auto-correlations in block."); return 0; } /* Return an array reference to Python. */ m = oskar_vis_block_auto_correlations(h); dims[0] = oskar_vis_block_num_times(h); dims[1] = oskar_vis_block_num_channels(h); dims[2] = oskar_vis_block_num_stations(h); dims[3] = oskar_vis_block_num_pols(h); array = (PyArrayObject*)PyArray_SimpleNewFromData(4, dims, (oskar_mem_is_double(m) ? NPY_CDOUBLE : NPY_CFLOAT), oskar_mem_void(m)); return Py_BuildValue("N", array); /* Don't increment refcount. */ }
static void check_values(const oskar_Mem* approx, const oskar_Mem* accurate) { int status = 0; double min_rel_error, max_rel_error, avg_rel_error, std_rel_error, tol; oskar_mem_evaluate_relative_error(approx, accurate, &min_rel_error, &max_rel_error, &avg_rel_error, &std_rel_error, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); tol = oskar_mem_is_double(approx) && oskar_mem_is_double(accurate) ? 1e-11 : 2e-3; EXPECT_LT(max_rel_error, tol) << std::setprecision(5) << "RELATIVE ERROR" << " MIN: " << min_rel_error << " MAX: " << max_rel_error << " AVG: " << avg_rel_error << " STD: " << std_rel_error; tol = oskar_mem_is_double(approx) && oskar_mem_is_double(accurate) ? 1e-12 : 1e-5; EXPECT_LT(avg_rel_error, tol) << std::setprecision(5) << "RELATIVE ERROR" << " MIN: " << min_rel_error << " MAX: " << max_rel_error << " AVG: " << avg_rel_error << " STD: " << std_rel_error; }
TEST(Mem, type_check_double_complex) { int status = 0; oskar_Mem *mem; mem = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, 0, &status); EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_double(mem)); EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_complex(mem)); EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_scalar(mem)); EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_double(OSKAR_DOUBLE_COMPLEX)); EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_complex(OSKAR_DOUBLE_COMPLEX)); EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_scalar(OSKAR_DOUBLE_COMPLEX)); oskar_mem_free(mem, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); }
TEST(Mem, type_check_single) { int status = 0; oskar_Mem *mem; mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, 0, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); EXPECT_EQ((int)OSKAR_FALSE, oskar_mem_is_double(mem)); EXPECT_EQ((int)OSKAR_FALSE, oskar_mem_is_complex(mem)); EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_scalar(mem)); EXPECT_EQ((int)OSKAR_FALSE, oskar_type_is_double(OSKAR_SINGLE)); EXPECT_EQ((int)OSKAR_FALSE, oskar_type_is_complex(OSKAR_SINGLE)); EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_scalar(OSKAR_SINGLE)); oskar_mem_free(mem, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); }
void write_plane(oskar_Imager* h, oskar_Mem* plane, int t, int c, int p, int* status) { int datatype, num_pixels; long firstpix[4]; if (*status) return; if (!h->fits_file[p]) return; datatype = (oskar_mem_is_double(plane) ? TDOUBLE : TFLOAT); firstpix[0] = 1; firstpix[1] = 1; firstpix[2] = 1 + c; firstpix[3] = 1 + t; num_pixels = h->image_size * h->image_size; fits_write_pix(h->fits_file[p], datatype, firstpix, num_pixels, oskar_mem_void(plane), status); }
void oskar_gaussian_circular(int num_points, const oskar_Mem* l, const oskar_Mem* m, double std, oskar_Mem* out, int* status) { if (*status) return; const int location = oskar_mem_location(out); const double inv_2_var = 1.0 / (2.0 * std * std); const float inv_2_var_f = (float)inv_2_var; if (oskar_mem_precision(out) != oskar_mem_type(l) || oskar_mem_precision(out) != oskar_mem_type(m)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (location != oskar_mem_location(l) || location != oskar_mem_location(m)) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if ((int)oskar_mem_length(l) < num_points || (int)oskar_mem_length(m) < num_points) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } oskar_mem_ensure(out, num_points, status); if (*status) return; if (location == OSKAR_CPU) { switch (oskar_mem_type(out)) { case OSKAR_SINGLE_COMPLEX: gaussian_circular_complex_f(num_points, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), inv_2_var_f, oskar_mem_float2(out, status)); break; case OSKAR_DOUBLE_COMPLEX: gaussian_circular_complex_d(num_points, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), inv_2_var, oskar_mem_double2(out, status)); break; case OSKAR_SINGLE_COMPLEX_MATRIX: gaussian_circular_matrix_f(num_points, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), inv_2_var_f, oskar_mem_float4c(out, status)); break; case OSKAR_DOUBLE_COMPLEX_MATRIX: gaussian_circular_matrix_d(num_points, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), inv_2_var, oskar_mem_double4c(out, status)); break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; break; } } else { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; const char* k = 0; const int is_dbl = oskar_mem_is_double(out); switch (oskar_mem_type(out)) { case OSKAR_SINGLE_COMPLEX: k = "gaussian_circular_complex_float"; break; case OSKAR_DOUBLE_COMPLEX: k = "gaussian_circular_complex_double"; break; case OSKAR_SINGLE_COMPLEX_MATRIX: k = "gaussian_circular_matrix_float"; break; case OSKAR_DOUBLE_COMPLEX_MATRIX: k = "gaussian_circular_matrix_double"; break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_points, local_size[0]); const oskar_Arg args[] = { {INT_SZ, &num_points}, {PTR_SZ, oskar_mem_buffer_const(l)}, {PTR_SZ, oskar_mem_buffer_const(m)}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&inv_2_var : (const void*)&inv_2_var_f}, {PTR_SZ, oskar_mem_buffer(out)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } }
void oskar_evaluate_element_weights_dft(int num_elements, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, double wavenumber, double x_beam, double y_beam, double z_beam, oskar_Mem* weights, int* status) { if (*status) return; const int location = oskar_mem_location(weights); const int type = oskar_mem_type(weights); const int precision = oskar_mem_precision(weights); if (oskar_mem_location(x) != location || oskar_mem_location(y) != location || oskar_mem_location(z) != location) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if (oskar_mem_type(x) != precision || oskar_mem_type(y) != precision || oskar_mem_type(z) != precision) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if ((int)oskar_mem_length(weights) < num_elements || (int)oskar_mem_length(x) < num_elements || (int)oskar_mem_length(y) < num_elements || (int)oskar_mem_length(z) < num_elements) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } if (location == OSKAR_CPU) { if (type == OSKAR_DOUBLE_COMPLEX) evaluate_element_weights_dft_d(num_elements, oskar_mem_double_const(x, status), oskar_mem_double_const(y, status), oskar_mem_double_const(z, status), wavenumber, x_beam, y_beam, z_beam, oskar_mem_double2(weights, status)); else if (type == OSKAR_SINGLE_COMPLEX) evaluate_element_weights_dft_f(num_elements, oskar_mem_float_const(x, status), oskar_mem_float_const(y, status), oskar_mem_float_const(z, status), wavenumber, x_beam, y_beam, z_beam, oskar_mem_float2(weights, status)); else *status = OSKAR_ERR_BAD_DATA_TYPE; } else { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; const char* k = 0; const int is_dbl = oskar_mem_is_double(weights); if (type == OSKAR_DOUBLE_COMPLEX) k = "evaluate_element_weights_dft_double"; else if (type == OSKAR_SINGLE_COMPLEX) k = "evaluate_element_weights_dft_float"; else { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } const float w = (float) wavenumber; const float x1 = (float) x_beam; const float y1 = (float) y_beam; const float z1 = (float) z_beam; oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_elements, local_size[0]); const oskar_Arg args[] = { {INT_SZ, &num_elements}, {PTR_SZ, oskar_mem_buffer_const(x)}, {PTR_SZ, oskar_mem_buffer_const(y)}, {PTR_SZ, oskar_mem_buffer_const(z)}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&wavenumber : (const void*)&w}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&x_beam : (const void*)&x1}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&y_beam : (const void*)&y1}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&z_beam : (const void*)&z1}, {PTR_SZ, oskar_mem_buffer(weights)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } }
void oskar_dftw( int normalise, int num_in, double wavenumber, const oskar_Mem* weights_in, const oskar_Mem* x_in, const oskar_Mem* y_in, const oskar_Mem* z_in, int offset_coord_out, int num_out, const oskar_Mem* x_out, const oskar_Mem* y_out, const oskar_Mem* z_out, const oskar_Mem* data, int offset_out, oskar_Mem* output, int* status) { if (*status) return; const int location = oskar_mem_location(output); const int type = oskar_mem_precision(output); const int is_dbl = oskar_mem_is_double(output); const int is_3d = (z_in != NULL && z_out != NULL); const int is_data = (data != NULL); const int is_matrix = oskar_mem_is_matrix(output); if (!oskar_mem_is_complex(output) || !oskar_mem_is_complex(weights_in) || oskar_mem_is_matrix(weights_in)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } if (oskar_mem_location(weights_in) != location || oskar_mem_location(x_in) != location || oskar_mem_location(y_in) != location || oskar_mem_location(x_out) != location || oskar_mem_location(y_out) != location) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if (oskar_mem_precision(weights_in) != type || oskar_mem_type(x_in) != type || oskar_mem_type(y_in) != type || oskar_mem_type(x_out) != type || oskar_mem_type(y_out) != type) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (is_data) { if (oskar_mem_location(data) != location) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if (!oskar_mem_is_complex(data) || oskar_mem_type(data) != oskar_mem_type(output) || oskar_mem_precision(data) != type) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } } if (is_3d) { if (oskar_mem_location(z_in) != location || oskar_mem_location(z_out) != location) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if (oskar_mem_type(z_in) != type || oskar_mem_type(z_out) != type) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } } oskar_mem_ensure(output, (size_t) offset_out + num_out, status); if (*status) return; if (location == OSKAR_CPU) { if (is_data) { if (is_matrix) { if (is_3d) { if (is_dbl) dftw_m2m_3d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), oskar_mem_double_const(z_in, status), offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), oskar_mem_double_const(z_out, status), oskar_mem_double4c_const(data, status), offset_out, oskar_mem_double4c(output, status), 0); else dftw_m2m_3d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), oskar_mem_float_const(z_in, status), offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), oskar_mem_float_const(z_out, status), oskar_mem_float4c_const(data, status), offset_out, oskar_mem_float4c(output, status), 0); } else { if (is_dbl) dftw_m2m_2d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), 0, oskar_mem_double4c_const(data, status), offset_out, oskar_mem_double4c(output, status), 0); else dftw_m2m_2d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), 0, oskar_mem_float4c_const(data, status), offset_out, oskar_mem_float4c(output, status), 0); } } else { if (is_3d) { if (is_dbl) dftw_c2c_3d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), oskar_mem_double_const(z_in, status), offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), oskar_mem_double_const(z_out, status), oskar_mem_double2_const(data, status), offset_out, oskar_mem_double2(output, status), 0); else dftw_c2c_3d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), oskar_mem_float_const(z_in, status), offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), oskar_mem_float_const(z_out, status), oskar_mem_float2_const(data, status), offset_out, oskar_mem_float2(output, status), 0); } else { if (is_dbl) dftw_c2c_2d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), 0, oskar_mem_double2_const(data, status), offset_out, oskar_mem_double2(output, status), 0); else dftw_c2c_2d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), 0, oskar_mem_float2_const(data, status), offset_out, oskar_mem_float2(output, status), 0); } } } else { if (is_3d) { if (is_dbl) dftw_o2c_3d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), oskar_mem_double_const(z_in, status), offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), oskar_mem_double_const(z_out, status), 0, offset_out, oskar_mem_double2(output, status), 0); else dftw_o2c_3d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), oskar_mem_float_const(z_in, status), offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), oskar_mem_float_const(z_out, status), 0, offset_out, oskar_mem_float2(output, status), 0); } else { if (is_dbl) dftw_o2c_2d_double(num_in, wavenumber, oskar_mem_double2_const(weights_in, status), oskar_mem_double_const(x_in, status), oskar_mem_double_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_double_const(x_out, status), oskar_mem_double_const(y_out, status), 0, 0, offset_out, oskar_mem_double2(output, status), 0); else dftw_o2c_2d_float(num_in, (float)wavenumber, oskar_mem_float2_const(weights_in, status), oskar_mem_float_const(x_in, status), oskar_mem_float_const(y_in, status), 0, offset_coord_out, num_out, oskar_mem_float_const(x_out, status), oskar_mem_float_const(y_out, status), 0, 0, offset_out, oskar_mem_float2(output, status), 0); } } } else { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; const void* np = 0; const char* k = 0; int max_in_chunk; float wavenumber_f = (float) wavenumber; /* Select the kernel. */ switch (is_dbl * DBL | is_3d * D3 | is_data * DAT | is_matrix * MAT) { case D2 | FLT: k = "dftw_o2c_2d_float"; break; case D2 | DBL: k = "dftw_o2c_2d_double"; break; case D3 | FLT: k = "dftw_o2c_3d_float"; break; case D3 | DBL: k = "dftw_o2c_3d_double"; break; case D2 | FLT | DAT: k = "dftw_c2c_2d_float"; break; case D2 | DBL | DAT: k = "dftw_c2c_2d_double"; break; case D3 | FLT | DAT: k = "dftw_c2c_3d_float"; break; case D3 | DBL | DAT: k = "dftw_c2c_3d_double"; break; case D2 | FLT | DAT | MAT: k = "dftw_m2m_2d_float"; break; case D2 | DBL | DAT | MAT: k = "dftw_m2m_2d_double"; break; case D3 | FLT | DAT | MAT: k = "dftw_m2m_3d_float"; break; case D3 | DBL | DAT | MAT: k = "dftw_m2m_3d_double"; break; default: *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; return; } if (oskar_device_is_nv(location)) local_size[0] = (size_t) get_block_size(num_out); oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_out, local_size[0]); /* max_in_chunk must be multiple of 16. */ max_in_chunk = is_3d ? (is_dbl ? 384 : 800) : (is_dbl ? 448 : 896); if (is_data && is_3d && !is_dbl) max_in_chunk = 768; const size_t element_size = is_dbl ? sizeof(double) : sizeof(float); const size_t local_mem_size = max_in_chunk * element_size; const size_t arg_size_local[] = { 2 * local_mem_size, 2 * local_mem_size, (is_3d ? local_mem_size : 0) }; /* Set kernel arguments. */ const oskar_Arg args[] = { {INT_SZ, &num_in}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (void*)&wavenumber : (void*)&wavenumber_f}, {PTR_SZ, oskar_mem_buffer_const(weights_in)}, {PTR_SZ, oskar_mem_buffer_const(x_in)}, {PTR_SZ, oskar_mem_buffer_const(y_in)}, {PTR_SZ, is_3d ? oskar_mem_buffer_const(z_in) : &np}, {INT_SZ, &offset_coord_out}, {INT_SZ, &num_out}, {PTR_SZ, oskar_mem_buffer_const(x_out)}, {PTR_SZ, oskar_mem_buffer_const(y_out)}, {PTR_SZ, is_3d ? oskar_mem_buffer_const(z_out) : &np}, {PTR_SZ, is_data ? oskar_mem_buffer_const(data) : &np}, {INT_SZ, &offset_out}, {PTR_SZ, oskar_mem_buffer(output)}, {INT_SZ, &max_in_chunk} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, sizeof(arg_size_local) / sizeof(size_t), arg_size_local, status); } if (normalise) oskar_mem_scale_real(output, 1. / num_in, offset_out, num_out, status); }