void oskar_fft_exec(oskar_FFT* h, oskar_Mem* data, int* status) { oskar_Mem *data_copy = 0, *data_ptr = data; if (oskar_mem_location(data) != h->location) { data_copy = oskar_mem_create_copy(data, h->location, status); data_ptr = data_copy; } if (h->location == OSKAR_CPU) { if (h->num_dim == 1) { *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; } else if (h->num_dim == 2) { if (h->precision == OSKAR_DOUBLE) oskar_fftpack_cfft2f(h->dim_size, h->dim_size, h->dim_size, oskar_mem_double(data_ptr, status), oskar_mem_double(h->fftpack_wsave, status), oskar_mem_double(h->fftpack_work, status)); else oskar_fftpack_cfft2f_f(h->dim_size, h->dim_size, h->dim_size, oskar_mem_float(data_ptr, status), oskar_mem_float(h->fftpack_wsave, status), oskar_mem_float(h->fftpack_work, status)); /* This step not needed for W-kernel generation, so turn it off. */ if (h->ensure_consistent_norm) oskar_mem_scale_real(data_ptr, (double)h->num_cells_total, 0, h->num_cells_total, status); } } else if (h->location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (h->precision == OSKAR_DOUBLE) cufftExecZ2Z(h->cufft_plan, (cufftDoubleComplex*) oskar_mem_void(data_ptr), (cufftDoubleComplex*) oskar_mem_void(data_ptr), CUFFT_FORWARD); else cufftExecC2C(h->cufft_plan, (cufftComplex*) oskar_mem_void(data_ptr), (cufftComplex*) oskar_mem_void(data_ptr), CUFFT_FORWARD); #endif } else *status = OSKAR_ERR_BAD_LOCATION; if (oskar_mem_location(data) != h->location) oskar_mem_copy(data, data_ptr, status); oskar_mem_free(data_copy, status); }
void oskar_imager_rotate_vis(size_t num_vis, const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww, oskar_Mem* amps, const double delta_l, const double delta_m, const double delta_n) { size_t i; if (oskar_mem_precision(amps) == OSKAR_DOUBLE) { const double *u, *v, *w; double2* a; u = (const double*)oskar_mem_void_const(uu); v = (const double*)oskar_mem_void_const(vv); w = (const double*)oskar_mem_void_const(ww); a = (double2*)oskar_mem_void(amps); for (i = 0; i < num_vis; ++i) { double arg, phase_re, phase_im, re, im; arg = 2.0*M_PI * (u[i] * delta_l + v[i] * delta_m + w[i] * delta_n); phase_re = cos(arg); phase_im = sin(arg); re = a[i].x * phase_re - a[i].y * phase_im; im = a[i].x * phase_im + a[i].y * phase_re; a[i].x = re; a[i].y = im; } } else { const float *u, *v, *w; float2* a; u = (const float*)oskar_mem_void_const(uu); v = (const float*)oskar_mem_void_const(vv); w = (const float*)oskar_mem_void_const(ww); a = (float2*)oskar_mem_void(amps); for (i = 0; i < num_vis; ++i) { float arg, phase_re, phase_im, re, im; arg = 2.0*M_PI * (u[i] * delta_l + v[i] * delta_m + w[i] * delta_n); phase_re = cos(arg); phase_im = sin(arg); re = a[i].x * phase_re - a[i].y * phase_im; im = a[i].x * phase_im + a[i].y * phase_re; a[i].x = re; a[i].y = im; } } }
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. */ }
oskar_Mem* oskar_mem_read_binary_raw(const char* filename, int type, int location, int* status) { size_t num_elements, element_size, size_bytes; oskar_Mem *mem = 0; FILE* stream; /* Check if safe to proceed. */ if (*status) return 0; /* Open the input file. */ stream = fopen(filename, "rb"); if (!stream) { *status = OSKAR_ERR_FILE_IO; return 0; } /* Get the file size. */ fseek(stream, 0, SEEK_END); size_bytes = ftell(stream); /* Create memory block of the right size. */ element_size = oskar_mem_element_size(type); num_elements = (size_t)ceil(size_bytes / element_size); mem = oskar_mem_create(type, OSKAR_CPU, num_elements, status); if (*status) { oskar_mem_free(mem, status); fclose(stream); return 0; } /* Read the data. */ fseek(stream, 0, SEEK_SET); if (fread(oskar_mem_void(mem), 1, size_bytes, stream) != size_bytes) { oskar_mem_free(mem, status); fclose(stream); *status = OSKAR_ERR_FILE_IO; return 0; } /* Close the input file. */ fclose(stream); /* Copy to GPU memory if required. */ if (location != OSKAR_CPU) { oskar_Mem* gpu; gpu = oskar_mem_create_copy(mem, location, status); oskar_mem_free(mem, status); return gpu; } return mem; }
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); }
void oskar_imager_finalise(oskar_Imager* h, int num_output_images, oskar_Mem** output_images, int num_output_grids, oskar_Mem** output_grids, int* status) { int t, c, p, i; if (*status || !h->planes) return; /* Adjust normalisation if required. */ if (h->scale_norm_with_num_input_files) { for (i = 0; i < h->num_planes; ++i) h->plane_norm[i] /= h->num_files; } /* Copy grids to output grid planes if given. */ for (i = 0; (i < h->num_planes) && (i < num_output_grids); ++i) { oskar_mem_copy(output_grids[i], h->planes[i], status); oskar_mem_scale_real(output_grids[i], 1.0 / h->plane_norm[i], status); } /* Check if images are required. */ if (h->fits_file[0] || output_images) { /* Finalise all the planes. */ for (i = 0; i < h->num_planes; ++i) { oskar_imager_finalise_plane(h, h->planes[i], h->plane_norm[i], status); oskar_imager_trim_image(h->planes[i], h->grid_size, h->image_size, status); } /* Copy images to output image planes if given. */ for (i = 0; (i < h->num_planes) && (i < num_output_images); ++i) { memcpy(oskar_mem_void(output_images[i]), oskar_mem_void_const(h->planes[i]), h->image_size * h->image_size * oskar_mem_element_size(h->imager_prec)); } /* Write to files if required. */ for (t = 0, i = 0; t < h->im_num_times; ++t) for (c = 0; c < h->im_num_channels; ++c) for (p = 0; p < h->im_num_pols; ++p, ++i) write_plane(h, h->planes[i], t, c, p, status); } /* Reset imager memory. */ oskar_imager_reset_cache(h, 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_binary_read_mem_ext(oskar_Binary* handle, oskar_Mem* mem, const char* name_group, const char* name_tag, int user_index, int* status) { int type; oskar_Mem *temp = 0, *data = 0; size_t size_bytes = 0, element_size = 0; /* Check if safe to proceed. */ if (*status) return; /* Get the data type. */ type = oskar_mem_type(mem); /* Initialise temporary (to zero length). */ temp = oskar_mem_create(type, OSKAR_CPU, 0, status); /* Check if data is in CPU or GPU memory. */ data = (oskar_mem_location(mem) == OSKAR_CPU) ? mem : temp; /* Query the tag index to find out how big the block is. */ element_size = oskar_mem_element_size(type); oskar_binary_query_ext(handle, (unsigned char)type, name_group, name_tag, user_index, &size_bytes, status); /* Resize memory block if necessary, so that it can hold the data. */ oskar_mem_realloc(data, size_bytes / element_size, status); /* Load the memory. */ oskar_binary_read_ext(handle, (unsigned char)type, name_group, name_tag, user_index, size_bytes, oskar_mem_void(data), status); /* Copy to GPU memory if required. */ if (oskar_mem_location(mem) != OSKAR_CPU) oskar_mem_copy(mem, temp, status); /* Free the temporary. */ oskar_mem_free(temp, status); }
void oskar_imager_finalise_plane(oskar_Imager* h, oskar_Mem* plane, double plane_norm, int* status) { int size, num_cells; DeviceData* d; if (*status) return; /* Apply normalisation. */ if (plane_norm > 0.0 || plane_norm < 0.0) oskar_mem_scale_real(plane, 1.0 / plane_norm, status); if (h->algorithm == OSKAR_ALGORITHM_DFT_2D || h->algorithm == OSKAR_ALGORITHM_DFT_3D) return; /* Check plane is complex type, as plane must be gridded visibilities. */ if (!oskar_mem_is_complex(plane)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Make image using FFT and apply grid correction. */ size = h->grid_size; num_cells = size * size; d = &h->d[0]; if (oskar_mem_precision(plane) == OSKAR_DOUBLE) { oskar_fftphase_cd(size, size, oskar_mem_double(plane, status)); if (h->fft_on_gpu) { #ifdef OSKAR_HAVE_CUDA oskar_device_set(h->cuda_device_ids[0], status); oskar_mem_copy(d->plane_gpu, plane, status); cufftExecZ2Z(h->cufft_plan, oskar_mem_void(d->plane_gpu), oskar_mem_void(d->plane_gpu), CUFFT_FORWARD); oskar_mem_copy(plane, d->plane_gpu, status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else { oskar_fftpack_cfft2f(size, size, size, oskar_mem_double(plane, status), oskar_mem_double(h->fftpack_wsave, status), oskar_mem_double(h->fftpack_work, status)); oskar_mem_scale_real(plane, (double)num_cells, status); } oskar_fftphase_cd(size, size, oskar_mem_double(plane, status)); oskar_grid_correction_d(size, oskar_mem_double(h->corr_func, status), oskar_mem_double(plane, status)); } else { oskar_fftphase_cf(size, size, oskar_mem_float(plane, status)); if (h->fft_on_gpu) { #ifdef OSKAR_HAVE_CUDA oskar_device_set(h->cuda_device_ids[0], status); oskar_mem_copy(d->plane_gpu, plane, status); cufftExecC2C(h->cufft_plan, oskar_mem_void(d->plane_gpu), oskar_mem_void(d->plane_gpu), CUFFT_FORWARD); oskar_mem_copy(plane, d->plane_gpu, status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else { oskar_fftpack_cfft2f_f(size, size, size, oskar_mem_float(plane, status), oskar_mem_float(h->fftpack_wsave, status), oskar_mem_float(h->fftpack_work, status)); oskar_mem_scale_real(plane, (double)num_cells, status); } oskar_fftphase_cf(size, size, oskar_mem_float(plane, status)); oskar_grid_correction_f(size, oskar_mem_double(h->corr_func, status), oskar_mem_float(plane, status)); } }
int main(int argc, char** argv) { int status = 0; oskar::OptionParser opt("oskar_evaulate_pierce_points", oskar_version_string()); opt.add_required("settings file"); if (!opt.check_options(argc, argv)) return EXIT_FAILURE; const char* settings_file = opt.get_arg(); // Create the log. oskar_Log* log = oskar_log_create(OSKAR_LOG_MESSAGE, OSKAR_LOG_STATUS); oskar_log_message(log, 'M', 0, "Running binary %s", argv[0]); // Enum values used in writing time-freq data binary files enum OSKAR_TIME_FREQ_TAGS { TIME_IDX = 0, FREQ_IDX = 1, TIME_MJD_UTC = 2, FREQ_HZ = 3, NUM_FIELDS = 4, NUM_FIELD_TAGS = 5, HEADER_OFFSET = 10, DATA = 0, DIMS = 1, LABEL = 2, UNITS = 3, GRP = OSKAR_TAG_GROUP_TIME_FREQ_DATA }; oskar_Settings_old settings; oskar_settings_old_load(&settings, log, settings_file, &status); oskar_log_set_keep_file(log, settings.sim.keep_log_file); if (status) return status; oskar_Telescope* tel = oskar_settings_to_telescope(&settings, log, &status); oskar_Sky* sky = oskar_settings_to_sky(&settings, log, &status); // FIXME remove this restriction ... (see evaluate Z) if (settings.ionosphere.num_TID_screens != 1) return OSKAR_ERR_SETUP_FAIL; int type = settings.sim.double_precision ? OSKAR_DOUBLE : OSKAR_SINGLE; int loc = OSKAR_CPU; int num_sources = oskar_sky_num_sources(sky); oskar_Mem *hor_x, *hor_y, *hor_z; hor_x = oskar_mem_create(type, loc, num_sources, &status); hor_y = oskar_mem_create(type, loc, num_sources, &status); hor_z = oskar_mem_create(type, loc, num_sources, &status); oskar_Mem *pp_lon, *pp_lat, *pp_rel_path; int num_stations = oskar_telescope_num_stations(tel); int num_pp = num_stations * num_sources; pp_lon = oskar_mem_create(type, loc, num_pp, &status); pp_lat = oskar_mem_create(type, loc, num_pp, &status); pp_rel_path = oskar_mem_create(type, loc, num_pp, &status); // Pierce points for one station (non-owned oskar_Mem pointers) oskar_Mem *pp_st_lon, *pp_st_lat, *pp_st_rel_path; pp_st_lon = oskar_mem_create_alias(0, 0, 0, &status); pp_st_lat = oskar_mem_create_alias(0, 0, 0, &status); pp_st_rel_path = oskar_mem_create_alias(0, 0, 0, &status); int num_times = settings.obs.num_time_steps; double obs_start_mjd_utc = settings.obs.start_mjd_utc; double dt_dump = settings.obs.dt_dump_days; // Binary file meta-data std::string label1 = "pp_lon"; std::string label2 = "pp_lat"; std::string label3 = "pp_path"; std::string units = "radians"; std::string units2 = ""; oskar_Mem *dims = oskar_mem_create(OSKAR_INT, loc, 2, &status); /* FIXME is this the correct dimension order ? * FIXME get the MATLAB reader to respect dimension ordering */ oskar_mem_int(dims, &status)[0] = num_sources; oskar_mem_int(dims, &status)[1] = num_stations; const char* filename = settings.ionosphere.pierce_points.filename; oskar_Binary* h = oskar_binary_create(filename, 'w', &status); double screen_height_m = settings.ionosphere.TID->height_km * 1000.0; // printf("Number of times = %i\n", num_times); // printf("Number of stations = %i\n", num_stations); void *x_, *y_, *z_; x_ = oskar_mem_void(oskar_telescope_station_true_x_offset_ecef_metres(tel)); y_ = oskar_mem_void(oskar_telescope_station_true_y_offset_ecef_metres(tel)); z_ = oskar_mem_void(oskar_telescope_station_true_z_offset_ecef_metres(tel)); for (int t = 0; t < num_times; ++t) { double t_dump = obs_start_mjd_utc + t * dt_dump; // MJD UTC double gast = oskar_convert_mjd_to_gast_fast(t_dump + dt_dump / 2.0); for (int i = 0; i < num_stations; ++i) { const oskar_Station* station = oskar_telescope_station_const(tel, i); double lon = oskar_station_lon_rad(station); double lat = oskar_station_lat_rad(station); double alt = oskar_station_alt_metres(station); double x_ecef, y_ecef, z_ecef, x_offset, y_offset, z_offset; if (type == OSKAR_DOUBLE) { x_offset = ((double*)x_)[i]; y_offset = ((double*)y_)[i]; z_offset = ((double*)z_)[i]; } else { x_offset = (double)((float*)x_)[i]; y_offset = (double)((float*)y_)[i]; z_offset = (double)((float*)z_)[i]; } oskar_convert_offset_ecef_to_ecef(1, &x_offset, &y_offset, &z_offset, lon, lat, alt, &x_ecef, &y_ecef, &z_ecef); double last = gast + lon; if (type == OSKAR_DOUBLE) { oskar_convert_apparent_ra_dec_to_enu_directions_d(num_sources, oskar_mem_double_const(oskar_sky_ra_rad_const(sky), &status), oskar_mem_double_const(oskar_sky_dec_rad_const(sky), &status), last, lat, oskar_mem_double(hor_x, &status), oskar_mem_double(hor_y, &status), oskar_mem_double(hor_z, &status)); } else { oskar_convert_apparent_ra_dec_to_enu_directions_f(num_sources, oskar_mem_float_const(oskar_sky_ra_rad_const(sky), &status), oskar_mem_float_const(oskar_sky_dec_rad_const(sky), &status), last, lat, oskar_mem_float(hor_x, &status), oskar_mem_float(hor_y, &status), oskar_mem_float(hor_z, &status)); } int offset = i * num_sources; oskar_mem_set_alias(pp_st_lon, pp_lon, offset, num_sources, &status); oskar_mem_set_alias(pp_st_lat, pp_lat, offset, num_sources, &status); oskar_mem_set_alias(pp_st_rel_path, pp_rel_path, offset, num_sources, &status); oskar_evaluate_pierce_points(pp_st_lon, pp_st_lat, pp_st_rel_path, x_ecef, y_ecef, z_ecef, screen_height_m, num_sources, hor_x, hor_y, hor_z, &status); } // Loop over stations. if (status != 0) continue; int index = t; // could be = (num_times * f) + t if we have frequency data int num_fields = 3; int num_field_tags = 4; double freq_hz = 0.0; int freq_idx = 0; // Write the header TAGS oskar_binary_write_int(h, GRP, TIME_IDX, index, t, &status); oskar_binary_write_double(h, GRP, FREQ_IDX, index, freq_idx, &status); oskar_binary_write_double(h, GRP, TIME_MJD_UTC, index, t_dump, &status); oskar_binary_write_double(h, GRP, FREQ_HZ, index, freq_hz, &status); oskar_binary_write_int(h, GRP, NUM_FIELDS, index, num_fields, &status); oskar_binary_write_int(h, GRP, NUM_FIELD_TAGS, index, num_field_tags, &status); // Write data TAGS (fields) int field, tagID; field = 0; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_lon, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label1.size()+1, label1.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units.size()+1, units.c_str(), &status); field = 1; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_lat, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label2.size()+1, label2.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units.size()+1, units.c_str(), &status); field = 2; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_rel_path, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label3.size()+1, label3.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units2.size()+1, units2.c_str(), &status); } // Loop over times // Close the OSKAR binary file. oskar_binary_free(h); // clean up memory oskar_mem_free(hor_x, &status); oskar_mem_free(hor_y, &status); oskar_mem_free(hor_z, &status); oskar_mem_free(pp_lon, &status); oskar_mem_free(pp_lat, &status); oskar_mem_free(pp_rel_path, &status); oskar_mem_free(pp_st_lon, &status); oskar_mem_free(pp_st_lat, &status); oskar_mem_free(pp_st_rel_path, &status); oskar_mem_free(dims, &status); oskar_telescope_free(tel, &status); oskar_sky_free(sky, &status); // Check for errors. if (status) oskar_log_error(log, "Run failed: %s.", oskar_get_error_string(status)); oskar_log_free(log); return status; }
void oskar_element_load_scalar(oskar_Element* data, double freq_hz, const char* filename, double closeness, double closeness_inc, int ignore_at_poles, int ignore_below_horizon, int* status) { int i, n = 0, type = OSKAR_DOUBLE; oskar_Splines *scalar_re = 0, *scalar_im = 0; oskar_Mem *theta = 0, *phi = 0, *re = 0, *im = 0, *weight = 0; /* Declare the line buffer. */ char *line = NULL; size_t bufsize = 0; FILE* file; /* Check if safe to proceed. */ if (*status) return; /* Check the data type. */ if (oskar_element_precision(data) != type) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Check the location. */ if (oskar_element_mem_location(data) != OSKAR_CPU) { *status = OSKAR_ERR_BAD_LOCATION; return; } /* Check if this frequency has already been set, and get its index if so. */ n = data->num_freq; for (i = 0; i < n; ++i) { if (fabs(data->freqs_hz[i] - freq_hz) <= freq_hz * DBL_EPSILON) break; } /* Expand arrays to hold data for a new frequency, if needed. */ if (i >= data->num_freq) { i = data->num_freq; oskar_element_resize_freq_data(data, i + 1, status); data->freqs_hz[i] = freq_hz; } /* Get pointers to surface data based on frequency index. */ scalar_re = data->scalar_re[i]; scalar_im = data->scalar_im[i]; /* Open the file. */ file = fopen(filename, "r"); if (!file) { *status = OSKAR_ERR_FILE_IO; return; } /* Create local arrays to hold data for fitting. */ theta = oskar_mem_create(type, OSKAR_CPU, 0, status); phi = oskar_mem_create(type, OSKAR_CPU, 0, status); re = oskar_mem_create(type, OSKAR_CPU, 0, status); im = oskar_mem_create(type, OSKAR_CPU, 0, status); weight = oskar_mem_create(type, OSKAR_CPU, 0, status); if (*status) return; /* Loop over and read each line in the file. */ n = 0; while (oskar_getline(&line, &bufsize, file) != OSKAR_ERR_EOF) { double re_, im_; double par[] = {0., 0., 0., 0.}; /* theta, phi, amp, phase (optional) */ void *p_theta = 0, *p_phi = 0, *p_re = 0, *p_im = 0, *p_weight = 0; /* Parse the line, and skip if data were not read correctly. */ if (oskar_string_to_array_d(line, 4, par) < 3) continue; /* Ignore data below horizon if requested. */ if (ignore_below_horizon && par[0] > 90.0) continue; /* Ignore data at poles if requested. */ if (ignore_at_poles) if (par[0] < 1e-6 || par[0] > (180.0 - 1e-6)) continue; /* Convert angular measures to radians. */ par[0] *= DEG2RAD; /* theta */ par[1] *= DEG2RAD; /* phi */ par[3] *= DEG2RAD; /* phase */ /* Ensure enough space in arrays. */ if (n % 100 == 0) { const int size = n + 100; oskar_mem_realloc(theta, size, status); oskar_mem_realloc(phi, size, status); oskar_mem_realloc(re, size, status); oskar_mem_realloc(im, size, status); oskar_mem_realloc(weight, size, status); if (*status) break; } p_theta = oskar_mem_void(theta); p_phi = oskar_mem_void(phi); p_re = oskar_mem_void(re); p_im = oskar_mem_void(im); p_weight = oskar_mem_void(weight); /* Amp,phase to real,imag conversion. */ re_ = par[2] * cos(par[3]); im_ = par[2] * sin(par[3]); /* Store the surface data. */ ((double*)p_theta)[n] = par[0]; ((double*)p_phi)[n] = par[1]; ((double*)p_re)[n] = re_; ((double*)p_im)[n] = im_; ((double*)p_weight)[n] = 1.0; /* Increment array pointer. */ n++; } /* Free the line buffer and close the file. */ free(line); fclose(file); /* Fit splines to the surface data. */ fit_splines(scalar_re, n, theta, phi, re, weight, closeness, closeness_inc, "Scalar [real]", status); fit_splines(scalar_im, n, theta, phi, im, weight, closeness, closeness_inc, "Scalar [imag]", status); /* Store the filename. */ oskar_mem_append_raw(data->filename_scalar[i], filename, OSKAR_CHAR, OSKAR_CPU, 1 + strlen(filename), status); /* Free local arrays. */ oskar_mem_free(theta, status); oskar_mem_free(phi, status); oskar_mem_free(re, status); oskar_mem_free(im, status); oskar_mem_free(weight, status); }
void oskar_imager_read_coords_ms(oskar_Imager* h, const char* filename, int i_file, int num_files, int* percent_done, int* percent_next, int* status) { #ifndef OSKAR_NO_MS oskar_MeasurementSet* ms; oskar_Mem *uvw, *u, *v, *w, *weight, *time_centroid; int num_channels, num_stations, num_baselines, num_pols; int start_row, num_rows; double *uvw_, *u_, *v_, *w_; if (*status) return; /* Read the header. */ ms = oskar_ms_open(filename); if (!ms) { *status = OSKAR_ERR_FILE_IO; return; } num_rows = (int) oskar_ms_num_rows(ms); num_stations = (int) oskar_ms_num_stations(ms); num_baselines = num_stations * (num_stations - 1) / 2; num_pols = (int) oskar_ms_num_pols(ms); num_channels = (int) oskar_ms_num_channels(ms); /* Set visibility meta-data. */ oskar_imager_set_vis_frequency(h, oskar_ms_freq_start_hz(ms), oskar_ms_freq_inc_hz(ms), num_channels); oskar_imager_set_vis_phase_centre(h, oskar_ms_phase_centre_ra_rad(ms) * 180/M_PI, oskar_ms_phase_centre_dec_rad(ms) * 180/M_PI); /* Create arrays. */ uvw = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 3 * num_baselines, status); u = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); v = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); w = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); weight = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, num_baselines * num_pols, status); time_centroid = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); uvw_ = oskar_mem_double(uvw, status); u_ = oskar_mem_double(u, status); v_ = oskar_mem_double(v, status); w_ = oskar_mem_double(w, status); /* Loop over visibility blocks. */ for (start_row = 0; start_row < num_rows; start_row += num_baselines) { int i, block_size; size_t allocated, required; if (*status) break; /* Read coordinates and weights from Measurement Set. */ oskar_timer_resume(h->tmr_read); block_size = num_rows - start_row; if (block_size > num_baselines) block_size = num_baselines; allocated = oskar_mem_length(uvw) * oskar_mem_element_size(oskar_mem_type(uvw)); oskar_ms_read_column(ms, "UVW", start_row, block_size, allocated, oskar_mem_void(uvw), &required, status); allocated = oskar_mem_length(weight) * oskar_mem_element_size(oskar_mem_type(weight)); oskar_ms_read_column(ms, "WEIGHT", start_row, block_size, allocated, oskar_mem_void(weight), &required, status); allocated = oskar_mem_length(time_centroid) * oskar_mem_element_size(oskar_mem_type(time_centroid)); oskar_ms_read_column(ms, "TIME_CENTROID", start_row, block_size, allocated, oskar_mem_void(time_centroid), &required, status); /* Split up baseline coordinates. */ for (i = 0; i < block_size; ++i) { u_[i] = uvw_[3*i + 0]; v_[i] = uvw_[3*i + 1]; w_[i] = uvw_[3*i + 2]; } /* Update the imager with the data. */ oskar_timer_pause(h->tmr_read); oskar_imager_update(h, block_size, 0, num_channels - 1, num_pols, u, v, w, 0, weight, time_centroid, status); *percent_done = (int) round(100.0 * ( (start_row + block_size) / (double)(num_rows * num_files) + i_file / (double)num_files)); if (h->log && percent_next && *percent_done >= *percent_next) { oskar_log_message(h->log, 'S', -2, "%3d%% ...", *percent_done); *percent_next = 10 + 10 * (*percent_done / 10); } } oskar_mem_free(uvw, status); oskar_mem_free(u, status); oskar_mem_free(v, status); oskar_mem_free(w, status); oskar_mem_free(weight, status); oskar_mem_free(time_centroid, status); oskar_ms_close(ms); #else (void) filename; (void) i_file; (void) num_files; (void) percent_done; (void) percent_next; oskar_log_error(h->log, "OSKAR was compiled without Measurement Set support."); *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; #endif }
TEST(imager, grid_sum) { int status = 0, type = OSKAR_DOUBLE; int size = 2048, grid_size = size * size; // Create and set up the imager. oskar_Imager* im = oskar_imager_create(type, &status); oskar_imager_set_grid_kernel(im, "pillbox", 1, 1, &status); oskar_imager_set_fov(im, 5.0); oskar_imager_set_size(im, size, &status); oskar_Mem* grid = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, grid_size, &status); ASSERT_EQ(0, status); // Create visibility data. int num_vis = 10000; oskar_Mem* uu = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* vv = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* ww = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* vis = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, num_vis, &status); oskar_Mem* weight = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_mem_random_gaussian(uu, 0, 1, 2, 3, 100.0, &status); oskar_mem_random_gaussian(vv, 4, 5, 6, 7, 100.0, &status); oskar_mem_set_value_real(vis, 1.0, 0, num_vis, &status); oskar_mem_set_value_real(weight, 1.0, 0, num_vis, &status); // Grid visibility data. double plane_norm = 0.0; oskar_imager_update_plane(im, num_vis, uu, vv, ww, vis, weight, grid, &plane_norm, 0, &status); ASSERT_DOUBLE_EQ((double)num_vis, plane_norm); // Sum the grid. double2* t = oskar_mem_double2(grid, &status); double sum = 0.0; for (int i = 0; i < grid_size; i++) sum += t[i].x; ASSERT_DOUBLE_EQ((double)num_vis, sum); // Finalise the image. oskar_imager_finalise_plane(im, grid, plane_norm, &status); ASSERT_EQ(0, status); #ifdef WRITE_FITS // Get the real part only. if (oskar_mem_precision(grid) == OSKAR_DOUBLE) { double *t = oskar_mem_double(grid, &status); for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j]; } else { float *t = oskar_mem_float(grid, &status); for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j]; } // Save the real part. fitsfile* f; long naxes[2] = {size, size}, firstpix[2] = {1, 1}; fits_create_file(&f, "test_imager_grid_sum.fits", &status); fits_create_img(f, (type == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG), 2, naxes, &status); fits_write_pix(f, (type == OSKAR_DOUBLE ? TDOUBLE : TFLOAT), firstpix, grid_size, oskar_mem_void(grid), &status); fits_close_file(f, &status); #endif // Clean up. oskar_imager_free(im, &status); oskar_mem_free(uu, &status); oskar_mem_free(vv, &status); oskar_mem_free(ww, &status); oskar_mem_free(vis, &status); oskar_mem_free(weight, &status); oskar_mem_free(grid, &status); }
void oskar_vis_block_write_ms(const oskar_VisBlock* blk, const oskar_VisHeader* header, oskar_MeasurementSet* ms, int* status) { const oskar_Mem *in_acorr, *in_xcorr, *in_uu, *in_vv, *in_ww; oskar_Mem *temp_vis = 0, *temp_uu = 0, *temp_vv = 0, *temp_ww = 0; double exposure_sec, interval_sec, t_start_mjd, t_start_sec; double ra_rad, dec_rad, ref_freq_hz; unsigned int a1, a2, num_baseln_in, num_baseln_out, num_channels; unsigned int num_pols_in, num_pols_out, num_stations, num_times, b, c, t; unsigned int i, i_out, prec, start_time_index, start_chan_index; unsigned int have_autocorr, have_crosscorr; const void *xcorr, *acorr; void* out; /* Check if safe to proceed. */ if (*status) return; /* Pull data from visibility structures. */ num_pols_out = oskar_ms_num_pols(ms); num_pols_in = oskar_vis_block_num_pols(blk); num_stations = oskar_vis_block_num_stations(blk); num_baseln_in = oskar_vis_block_num_baselines(blk); num_channels = oskar_vis_block_num_channels(blk); num_times = oskar_vis_block_num_times(blk); in_acorr = oskar_vis_block_auto_correlations_const(blk); in_xcorr = oskar_vis_block_cross_correlations_const(blk); in_uu = oskar_vis_block_baseline_uu_metres_const(blk); in_vv = oskar_vis_block_baseline_vv_metres_const(blk); in_ww = oskar_vis_block_baseline_ww_metres_const(blk); have_autocorr = oskar_vis_block_has_auto_correlations(blk); have_crosscorr = oskar_vis_block_has_cross_correlations(blk); start_time_index = oskar_vis_block_start_time_index(blk); start_chan_index = oskar_vis_block_start_channel_index(blk); ra_rad = oskar_vis_header_phase_centre_ra_deg(header) * D2R; dec_rad = oskar_vis_header_phase_centre_dec_deg(header) * D2R; exposure_sec = oskar_vis_header_time_average_sec(header); interval_sec = oskar_vis_header_time_inc_sec(header); t_start_mjd = oskar_vis_header_time_start_mjd_utc(header); ref_freq_hz = oskar_vis_header_freq_start_hz(header); prec = oskar_mem_precision(in_xcorr); t_start_sec = t_start_mjd * 86400.0 + interval_sec * (start_time_index + 0.5); /* Check that there is something to write. */ if (!have_autocorr && !have_crosscorr) return; /* Get number of output baselines. */ num_baseln_out = num_baseln_in; if (have_autocorr) num_baseln_out += num_stations; /* Check polarisation dimension consistency: * num_pols_in can be less than num_pols_out, but not vice-versa. */ if (num_pols_in > num_pols_out) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Check the dimensions match. */ if (oskar_ms_num_pols(ms) != num_pols_out || oskar_ms_num_stations(ms) != num_stations) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Check the reference frequencies match. */ if (fabs(oskar_ms_ref_freq_hz(ms) - ref_freq_hz) > 1e-10) { *status = OSKAR_ERR_VALUE_MISMATCH; return; } /* Check the phase centres are the same. */ if (fabs(oskar_ms_phase_centre_ra_rad(ms) - ra_rad) > 1e-10 || fabs(oskar_ms_phase_centre_dec_rad(ms) - dec_rad) > 1e-10) { *status = OSKAR_ERR_VALUE_MISMATCH; return; } /* Add visibilities and u,v,w coordinates. */ temp_vis = oskar_mem_create(prec | OSKAR_COMPLEX, OSKAR_CPU, num_baseln_out * num_channels * num_pols_out, status); temp_uu = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); temp_vv = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); temp_ww = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); xcorr = oskar_mem_void_const(in_xcorr); acorr = oskar_mem_void_const(in_acorr); out = oskar_mem_void(temp_vis); if (prec == OSKAR_DOUBLE) { const double *uu_in, *vv_in, *ww_in; double *uu_out, *vv_out, *ww_out; uu_in = oskar_mem_double_const(in_uu, status); vv_in = oskar_mem_double_const(in_vv, status); ww_in = oskar_mem_double_const(in_ww, status); uu_out = oskar_mem_double(temp_uu, status); vv_out = oskar_mem_double(temp_vv, status); ww_out = oskar_mem_double(temp_ww, status); for (t = 0; t < num_times; ++t) { /* Construct the baseline coordinates for the given time. */ int start_row = (start_time_index + t) * num_baseln_out; for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1) { if (have_autocorr) { uu_out[i_out] = 0.0; vv_out[i_out] = 0.0; ww_out[i_out] = 0.0; ++i_out; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out) { i = num_baseln_in * t + b; uu_out[i_out] = uu_in[i]; vv_out[i_out] = vv_in[i]; ww_out[i_out] = ww_in[i]; } } } for (c = 0, i_out = 0; c < num_channels; ++c) { /* Construct amplitude data for the given time and channel. */ if (num_pols_in == 4) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((double4c*)out)[i_out++] = ((const double4c*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((double4c*)out)[i_out++] = ((const double4c*)xcorr)[i]; } } } } else if (num_pols_in == 1 && num_pols_out == 1) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((double2*)out)[i_out++] = ((const double2*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((double2*)out)[i_out++] = ((const double2*)xcorr)[i]; } } } } else { double2 vis_amp, *out_; out_ = (double2*)out; for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; vis_amp = ((const double2*)acorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; vis_amp = ((const double2*)xcorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } } } } } oskar_ms_write_coords_d(ms, start_row, num_baseln_out, uu_out, vv_out, ww_out, exposure_sec, interval_sec, t_start_sec + (t * interval_sec)); oskar_ms_write_vis_d(ms, start_row, start_chan_index, num_channels, num_baseln_out, (const double*)out); } } else if (prec == OSKAR_SINGLE) { const float *uu_in, *vv_in, *ww_in; float *uu_out, *vv_out, *ww_out; uu_in = oskar_mem_float_const(in_uu, status); vv_in = oskar_mem_float_const(in_vv, status); ww_in = oskar_mem_float_const(in_ww, status); uu_out = oskar_mem_float(temp_uu, status); vv_out = oskar_mem_float(temp_vv, status); ww_out = oskar_mem_float(temp_ww, status); for (t = 0; t < num_times; ++t) { /* Construct the baseline coordinates for the given time. */ int start_row = (start_time_index + t) * num_baseln_out; for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1) { if (have_autocorr) { uu_out[i_out] = 0.0; vv_out[i_out] = 0.0; ww_out[i_out] = 0.0; ++i_out; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out) { i = num_baseln_in * t + b; uu_out[i_out] = uu_in[i]; vv_out[i_out] = vv_in[i]; ww_out[i_out] = ww_in[i]; } } } for (c = 0, i_out = 0; c < num_channels; ++c) { /* Construct amplitude data for the given time and channel. */ if (num_pols_in == 4) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((float4c*)out)[i_out++] = ((const float4c*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((float4c*)out)[i_out++] = ((const float4c*)xcorr)[i]; } } } } else if (num_pols_in == 1 && num_pols_out == 1) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((float2*)out)[i_out++] = ((const float2*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((float2*)out)[i_out++] = ((const float2*)xcorr)[i]; } } } } else { float2 vis_amp, *out_; out_ = (float2*)out; for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; vis_amp = ((const float2*)acorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; vis_amp = ((const float2*)xcorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } } } } } oskar_ms_write_coords_f(ms, start_row, num_baseln_out, uu_out, vv_out, ww_out, exposure_sec, interval_sec, t_start_sec + (t * interval_sec)); oskar_ms_write_vis_f(ms, start_row, start_chan_index, num_channels, num_baseln_out, (const float*)out); } } else { *status = OSKAR_ERR_BAD_DATA_TYPE; } /* Cleanup. */ oskar_mem_free(temp_vis, status); oskar_mem_free(temp_uu, status); oskar_mem_free(temp_vv, status); oskar_mem_free(temp_ww, status); }
void oskar_element_load_cst(oskar_Element* data, oskar_Log* log, int port, double freq_hz, const char* filename, double closeness, double closeness_inc, int ignore_at_poles, int ignore_below_horizon, int* status) { int i, n = 0, type = OSKAR_DOUBLE; size_t fname_len; oskar_Splines *data_h_re = 0, *data_h_im = 0; oskar_Splines *data_v_re = 0, *data_v_im = 0; oskar_Mem *theta, *phi, *h_re, *h_im, *v_re, *v_im, *weight; /* Declare the line buffer. */ char *line = 0, *dbi = 0, *ludwig3 = 0; size_t bufsize = 0; FILE* file; /* Check if safe to proceed. */ if (*status) return; /* Check port number. */ if (port != 0 && port != 1 && port != 2) { *status = OSKAR_ERR_INVALID_ARGUMENT; return; } /* Check the data type. */ if (oskar_element_precision(data) != type) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Check the location. */ if (oskar_element_mem_location(data) != OSKAR_CPU) { *status = OSKAR_ERR_BAD_LOCATION; return; } /* Check if this frequency has already been set, and get its index if so. */ n = data->num_freq; for (i = 0; i < n; ++i) { if (fabs(data->freqs_hz[i] - freq_hz) <= freq_hz * DBL_EPSILON) break; } /* Expand arrays to hold data for a new frequency, if needed. */ if (i >= data->num_freq) { i = data->num_freq; oskar_element_resize_freq_data(data, i + 1, status); data->freqs_hz[i] = freq_hz; } /* Get pointers to surface data based on port number and frequency index. */ if (port == 1 || port == 0) { data_h_re = oskar_element_x_h_re(data, i); data_h_im = oskar_element_x_h_im(data, i); data_v_re = oskar_element_x_v_re(data, i); data_v_im = oskar_element_x_v_im(data, i); } else if (port == 2) { data_h_re = oskar_element_y_h_re(data, i); data_h_im = oskar_element_y_h_im(data, i); data_v_re = oskar_element_y_v_re(data, i); data_v_im = oskar_element_y_v_im(data, i); } /* Open the file. */ fname_len = 1 + strlen(filename); file = fopen(filename, "r"); if (!file) { *status = OSKAR_ERR_FILE_IO; return; } /* Read the first line to check units and coordinate system. */ if (oskar_getline(&line, &bufsize, file) < 0) { *status = OSKAR_ERR_FILE_IO; free(line); fclose(file); return; } /* Check for presence of "dBi". */ dbi = strstr(line, "dBi"); /* Check for data in Ludwig-3 polarisation system. */ ludwig3 = strstr(line, "Horiz"); /* Create local arrays to hold data for fitting. */ theta = oskar_mem_create(type, OSKAR_CPU, 0, status); phi = oskar_mem_create(type, OSKAR_CPU, 0, status); h_re = oskar_mem_create(type, OSKAR_CPU, 0, status); h_im = oskar_mem_create(type, OSKAR_CPU, 0, status); v_re = oskar_mem_create(type, OSKAR_CPU, 0, status); v_im = oskar_mem_create(type, OSKAR_CPU, 0, status); weight = oskar_mem_create(type, OSKAR_CPU, 0, status); if (*status) return; /* Loop over and read each line in the file. */ n = 0; while (oskar_getline(&line, &bufsize, file) != OSKAR_ERR_EOF) { double t = 0., p = 0., abs_theta_horiz, phase_theta_horiz; double abs_phi_verti, phase_phi_verti; double theta_horiz_re, theta_horiz_im, phi_verti_re, phi_verti_im; double h_re_, h_im_, v_re_, v_im_; void *p_theta = 0, *p_phi = 0, *p_h_re = 0, *p_h_im = 0, *p_v_re = 0; void *p_v_im = 0, *p_weight = 0; /* Parse the line, and skip if data were not read correctly. */ if (sscanf(line, "%lf %lf %*f %lf %lf %lf %lf %*f", &t, &p, &abs_theta_horiz, &phase_theta_horiz, &abs_phi_verti, &phase_phi_verti) != 6) continue; /* Ignore data below horizon if requested. */ if (ignore_below_horizon && t > 90.0) continue; /* Ignore data at poles if requested. */ if (ignore_at_poles) if (t < 1e-6 || t > (180.0 - 1e-6)) continue; /* Convert angular measures to radians. */ t *= DEG2RAD; p *= DEG2RAD; phase_theta_horiz *= DEG2RAD; phase_phi_verti *= DEG2RAD; /* Ensure enough space in arrays. */ if (n % 100 == 0) { int size; size = n + 100; oskar_mem_realloc(theta, size, status); oskar_mem_realloc(phi, size, status); oskar_mem_realloc(h_re, size, status); oskar_mem_realloc(h_im, size, status); oskar_mem_realloc(v_re, size, status); oskar_mem_realloc(v_im, size, status); oskar_mem_realloc(weight, size, status); if (*status) break; } p_theta = oskar_mem_void(theta); p_phi = oskar_mem_void(phi); p_h_re = oskar_mem_void(h_re); p_h_im = oskar_mem_void(h_im); p_v_re = oskar_mem_void(v_re); p_v_im = oskar_mem_void(v_im); p_weight = oskar_mem_void(weight); /* Convert decibel to linear scale if necessary. */ if (dbi) { abs_theta_horiz = pow(10.0, abs_theta_horiz / 10.0); abs_phi_verti = pow(10.0, abs_phi_verti / 10.0); } /* Amp,phase to real,imag conversion. */ theta_horiz_re = abs_theta_horiz * cos(phase_theta_horiz); theta_horiz_im = abs_theta_horiz * sin(phase_theta_horiz); phi_verti_re = abs_phi_verti * cos(phase_phi_verti); phi_verti_im = abs_phi_verti * sin(phase_phi_verti); /* Convert to Ludwig-3 polarisation system if required. */ if (ludwig3) { /* Already in Ludwig-3: No conversion required. */ h_re_ = theta_horiz_re; h_im_ = theta_horiz_im; v_re_ = phi_verti_re; v_im_ = phi_verti_im; } else { /* Convert from theta/phi to Ludwig-3. */ double cos_p, sin_p; sin_p = sin(p); cos_p = cos(p); h_re_ = theta_horiz_re * cos_p - phi_verti_re * sin_p; h_im_ = theta_horiz_im * cos_p - phi_verti_im * sin_p; v_re_ = theta_horiz_re * sin_p + phi_verti_re * cos_p; v_im_ = theta_horiz_im * sin_p + phi_verti_im * cos_p; } /* Store the surface data in Ludwig-3 format. */ ((double*)p_theta)[n] = t; ((double*)p_phi)[n] = p; ((double*)p_h_re)[n] = h_re_; ((double*)p_h_im)[n] = h_im_; ((double*)p_v_re)[n] = v_re_; ((double*)p_v_im)[n] = v_im_; ((double*)p_weight)[n] = 1.0; /* Increment array pointer. */ n++; } /* Free the line buffer and close the file. */ free(line); fclose(file); /* Fit splines to the surface data. */ fit_splines(log, data_h_re, n, theta, phi, h_re, weight, closeness, closeness_inc, "H [real]", status); fit_splines(log, data_h_im, n, theta, phi, h_im, weight, closeness, closeness_inc, "H [imag]", status); fit_splines(log, data_v_re, n, theta, phi, v_re, weight, closeness, closeness_inc, "V [real]", status); fit_splines(log, data_v_im, n, theta, phi, v_im, weight, closeness, closeness_inc, "V [imag]", status); /* Store the filename. */ if (port == 0) { oskar_mem_append_raw(data->filename_x[i], filename, OSKAR_CHAR, OSKAR_CPU, fname_len, status); oskar_mem_append_raw(data->filename_y[i], filename, OSKAR_CHAR, OSKAR_CPU, fname_len, status); } else if (port == 1) { oskar_mem_append_raw(data->filename_x[i], filename, OSKAR_CHAR, OSKAR_CPU, fname_len, status); } else if (port == 2) { oskar_mem_append_raw(data->filename_y[i], filename, OSKAR_CHAR, OSKAR_CPU, fname_len, status); } /* Copy X to Y if both ports are the same. */ if (port == 0) { oskar_splines_copy(data->y_h_re[i], data->x_h_re[i], status); oskar_splines_copy(data->y_h_im[i], data->x_h_im[i], status); oskar_splines_copy(data->y_v_re[i], data->x_v_re[i], status); oskar_splines_copy(data->y_v_im[i], data->x_v_im[i], status); } /* Free local arrays. */ oskar_mem_free(theta, status); oskar_mem_free(phi, status); oskar_mem_free(h_re, status); oskar_mem_free(h_im, status); oskar_mem_free(v_re, status); oskar_mem_free(v_im, status); oskar_mem_free(weight, status); }