Exemplo n.º 1
0
void oskar_evaluate_element_weights(oskar_Mem* weights,
        oskar_Mem* weights_error, double wavenumber,
        const oskar_Station* station, double x_beam, double y_beam,
        double z_beam, int time_index, int* status)
{
    int num_elements;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Resize weights and weights error work arrays if required. */
    num_elements = oskar_station_num_elements(station);
    if ((int)oskar_mem_length(weights) < num_elements)
        oskar_mem_realloc(weights, num_elements, status);
    if ((int)oskar_mem_length(weights_error) < num_elements)
        oskar_mem_realloc(weights_error, num_elements, status);

    /* Generate DFT weights. */
    oskar_evaluate_element_weights_dft(weights, num_elements, wavenumber,
            oskar_station_element_measured_x_enu_metres_const(station),
            oskar_station_element_measured_y_enu_metres_const(station),
            oskar_station_element_measured_z_enu_metres_const(station),
            x_beam, y_beam, z_beam, status);

    /* Apply time-variable errors. */
    if (oskar_station_apply_element_errors(station))
    {
        /* Generate weights errors. */
        oskar_evaluate_element_weights_errors(num_elements,
                oskar_station_element_gain_const(station),
                oskar_station_element_gain_error_const(station),
                oskar_station_element_phase_offset_rad_const(station),
                oskar_station_element_phase_error_rad_const(station),
                oskar_station_seed_time_variable_errors(station), time_index,
                oskar_station_unique_id(station), weights_error, status);

        /* Modify the weights (complex multiply with error vector). */
        oskar_mem_element_multiply(0, weights, weights_error,
                num_elements, status);
    }

    /* Modify the weights using the provided apodisation values. */
    if (oskar_station_apply_element_weight(station))
    {
        oskar_mem_element_multiply(0, weights,
                oskar_station_element_weight_const(station), num_elements,
                status);
    }
}
Exemplo n.º 2
0
void oskar_telescope_set_noise_freq(oskar_Telescope* model,
        double start_hz, double inc_hz, int num_channels, int* status)
{
    int i;
    oskar_Mem* noise_freq_hz;
    noise_freq_hz = oskar_mem_create(model->precision, OSKAR_CPU,
            num_channels, status);
    if (*status) return;
    if (model->precision == OSKAR_DOUBLE)
    {
        double* f = oskar_mem_double(noise_freq_hz, status);
        for (i = 0; i < num_channels; ++i) f[i] = start_hz + i * inc_hz;
    }
    else
    {
        float* f = oskar_mem_float(noise_freq_hz, status);
        for (i = 0; i < num_channels; ++i) f[i] = start_hz + i * inc_hz;
    }

    /* Set noise frequency for all top-level stations. */
    for (i = 0; i < model->num_stations; ++i)
    {
        oskar_Mem* t;
        t = oskar_station_noise_freq_hz(model->station[i]);
        oskar_mem_realloc(t, num_channels, status);
        oskar_mem_copy(t, noise_freq_hz, status);
    }
    oskar_mem_free(noise_freq_hz, status);
}
Exemplo n.º 3
0
void oskar_imager_update_plane_fft(oskar_Imager* h, int num_vis,
        const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* amps,
        const oskar_Mem* weight, oskar_Mem* plane, double* plane_norm,
        int* status)
{
    int num_cells, num_skipped = 0;
    if (*status) return;
    num_cells = h->grid_size * h->grid_size;
    if (oskar_mem_precision(plane) != h->imager_prec)
        *status = OSKAR_ERR_TYPE_MISMATCH;
    if ((int)oskar_mem_length(plane) < num_cells)
        oskar_mem_realloc(plane, num_cells, status);
    if (*status) return;
    if (h->imager_prec == OSKAR_DOUBLE)
        oskar_grid_simple_d(h->support, h->oversample,
                oskar_mem_double_const(h->conv_func, status), num_vis,
                oskar_mem_double_const(uu, status),
                oskar_mem_double_const(vv, status),
                oskar_mem_double_const(amps, status),
                oskar_mem_double_const(weight, status), h->cellsize_rad,
                h->grid_size, &num_skipped, plane_norm,
                oskar_mem_double(plane, status));
    else
        oskar_grid_simple_f(h->support, h->oversample,
                oskar_mem_double_const(h->conv_func, status), num_vis,
                oskar_mem_float_const(uu, status),
                oskar_mem_float_const(vv, status),
                oskar_mem_float_const(amps, status),
                oskar_mem_float_const(weight, status), h->cellsize_rad,
                h->grid_size, &num_skipped, plane_norm,
                oskar_mem_float(plane, status));
    if (num_skipped > 0)
        printf("WARNING: Skipped %d visibility points.\n", num_skipped);
}
Exemplo n.º 4
0
static void compute_relative_directions(oskar_Mem* l, oskar_Mem* m,
        oskar_Mem* n, int np, const oskar_Mem* x, const oskar_Mem* y,
        const oskar_Mem* z, const oskar_Station* station, double GAST,
        int* status)
{
    double ha0, dec0, lat;
    int pointing_coord_type;

    if (*status) return;

    /* Resize work arrays if needed */
    if ((int)oskar_mem_length(l) < np) oskar_mem_realloc(l, np, status);
    if ((int)oskar_mem_length(m) < np) oskar_mem_realloc(m, np, status);
    if ((int)oskar_mem_length(n) < np) oskar_mem_realloc(n, np, status);
    if (*status) return;

    /* Obtain ra0, dec0 of phase centre */
    lat  = oskar_station_lat_rad(station);
    pointing_coord_type = oskar_station_beam_coord_type(station);
    if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL)
    {
        double ra0;
        ra0  = oskar_station_beam_lon_rad(station);
        ha0  = (GAST + oskar_station_lon_rad(station)) - ra0;
        dec0 = oskar_station_beam_lat_rad(station);
    }
    else if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_AZEL)
    {
        /* TODO convert from az0, el0 to ha0, dec0 */
        ha0 = 0.0;
        dec0 = 0.0;
        *status = OSKAR_FAIL;
        return;
    }
    else
    {
        *status = OSKAR_ERR_SETTINGS_TELESCOPE;
        return;
    }

    /* Convert from ENU to phase-centre-relative directions. */
    oskar_convert_enu_directions_to_relative_directions(
            l, m, n, np, x, y, z, ha0, dec0, lat, status);
}
Exemplo n.º 5
0
void oskar_work_jones_z_resize(oskar_WorkJonesZ* work, int n, int* status)
{
    oskar_mem_realloc(work->hor_x, n, status);
    oskar_mem_realloc(work->hor_y, n, status);
    oskar_mem_realloc(work->hor_z, n, status);
    oskar_mem_realloc(work->pp_lon, n, status);
    oskar_mem_realloc(work->pp_lat, n, status);
    oskar_mem_realloc(work->pp_rel_path, n, status);
    oskar_mem_realloc(work->screen_TEC, n, status);
    oskar_mem_realloc(work->total_TEC, n, status);
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
void oskar_telescope_set_noise_rms(oskar_Telescope* model,
        double start, double end, int* status)
{
    int i, j, num_channels;
    double inc;
    oskar_Station* s;
    oskar_Mem *noise_rms_jy, *h;

    /* Set noise RMS for all top-level stations. */
    if (*status) return;
    for (i = 0; i < model->num_stations; ++i)
    {
        s = model->station[i];
        h = oskar_station_noise_rms_jy(s);
        num_channels = (int)oskar_mem_length(oskar_station_noise_freq_hz(s));
        if (num_channels == 0)
        {
            *status = OSKAR_ERR_OUT_OF_RANGE;
            return;
        }
        oskar_mem_realloc(h, num_channels, status);
        noise_rms_jy = oskar_mem_create(model->precision, OSKAR_CPU,
                num_channels, status);
        inc = (end - start) / (double)num_channels;
        if (model->precision == OSKAR_DOUBLE)
        {
            double* r = oskar_mem_double(noise_rms_jy, status);
            for (j = 0; j < num_channels; ++j) r[j] = start + j * inc;
        }
        else
        {
            float* r = oskar_mem_float(noise_rms_jy, status);
            for (j = 0; j < num_channels; ++j) r[j] = start + j * inc;
        }
        oskar_mem_copy(h, noise_rms_jy, status);
        oskar_mem_free(noise_rms_jy, status);
    }
}
Exemplo n.º 8
0
void oskar_evaluate_station_beam_gaussian(oskar_Mem* beam,
        int num_points, const oskar_Mem* l, const oskar_Mem* m,
        const oskar_Mem* horizon_mask, double fwhm_rad, int* status)
{
    int type, location;
    double fwhm_lm, std;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Get type and check consistency. */
    type = oskar_mem_precision(beam);
    if (type != oskar_mem_type(l) || type != oskar_mem_type(m))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (type != OSKAR_SINGLE && type != OSKAR_DOUBLE)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (!oskar_mem_is_complex(beam))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    if (fwhm_rad == 0.0)
    {
        *status = OSKAR_ERR_SETTINGS_TELESCOPE;
        return;
    }

    /* Get location and check consistency. */
    location = oskar_mem_location(beam);
    if (location != oskar_mem_location(l) ||
            location != oskar_mem_location(m))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Check that length of input arrays are consistent. */
    if ((int)oskar_mem_length(l) < num_points ||
            (int)oskar_mem_length(m) < num_points)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Resize output array if needed. */
    if ((int)oskar_mem_length(beam) < num_points)
        oskar_mem_realloc(beam, num_points, status);

    /* Check if safe to proceed. */
    if (*status) return;

    /* Compute Gaussian standard deviation from FWHM. */
    fwhm_lm = sin(fwhm_rad);
    std = fwhm_lm / (2.0 * sqrt(2.0 * log(2.0)));

    if (type == OSKAR_DOUBLE)
    {
        const double *l_, *m_;
        l_ = oskar_mem_double_const(l, status);
        m_ = oskar_mem_double_const(m, status);

        if (location == OSKAR_CPU)
        {
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_d(oskar_mem_double2(beam, status),
                        num_points, l_, m_, std);
            }
            else
            {
                oskar_gaussian_md(oskar_mem_double4c(beam, status),
                        num_points, l_, m_, std);
            }
        }
        else
        {
#ifdef OSKAR_HAVE_CUDA
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_cuda_d(oskar_mem_double2(beam, status),
                        num_points, l_, m_, std);
            }
            else
            {
                oskar_gaussian_cuda_md(oskar_mem_double4c(beam, status),
                        num_points, l_, m_, std);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
    }
    else /* type == OSKAR_SINGLE */
    {
        const float *l_, *m_;
        l_ = oskar_mem_float_const(l, status);
        m_ = oskar_mem_float_const(m, status);

        if (location == OSKAR_CPU)
        {
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_f(oskar_mem_float2(beam, status), num_points,
                        l_, m_, (float)std);
            }
            else
            {
                oskar_gaussian_mf(oskar_mem_float4c(beam, status), num_points,
                        l_, m_, (float)std);
            }
        }
        else
        {
#ifdef OSKAR_HAVE_CUDA
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_cuda_f(oskar_mem_float2(beam, status),
                        num_points, l_, m_, (float)std);
            }
            else
            {
                oskar_gaussian_cuda_mf(oskar_mem_float4c(beam, status),
                        num_points, l_, m_, (float)std);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
    }

    /* Blank (zero) sources below the horizon. */
    oskar_blank_below_horizon(beam, horizon_mask, num_points, status);
}
void oskar_imager_update_plane_wproj(oskar_Imager* h, size_t num_vis,
        const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww,
        const oskar_Mem* amps, const oskar_Mem* weight, oskar_Mem* plane,
        double* plane_norm, size_t* num_skipped, int* status)
{
    int grid_size;
    size_t num_cells;
    if (*status) return;
    grid_size = oskar_imager_plane_size(h);
    num_cells = grid_size * grid_size;
    if (oskar_mem_precision(plane) != h->imager_prec)
        *status = OSKAR_ERR_TYPE_MISMATCH;
    if (oskar_mem_length(plane) < num_cells)
        oskar_mem_realloc(plane, num_cells, status);
    if (*status) return;
    if (h->imager_prec == OSKAR_DOUBLE)
        oskar_grid_wproj_d(h->num_w_planes,
                oskar_mem_int_const(h->w_support, status),
                h->oversample, h->conv_size_half,
                oskar_mem_double_const(h->w_kernels, status), num_vis,
                oskar_mem_double_const(uu, status),
                oskar_mem_double_const(vv, status),
                oskar_mem_double_const(ww, status),
                oskar_mem_double_const(amps, status),
                oskar_mem_double_const(weight, status),
                h->cellsize_rad, h->w_scale,
                grid_size, num_skipped, plane_norm,
                oskar_mem_double(plane, status));
    else
    {
        char *fname = 0;
#if SAVE_INPUT_DAT || SAVE_OUTPUT_DAT || SAVE_GRID
        fname = (char*) calloc(20 +
                h->input_root ? strlen(h->input_root) : 0, 1);
#endif
#if SAVE_INPUT_DAT
        {
            const float cellsize_rad_tmp = (const float) (h->cellsize_rad);
            const float w_scale_tmp = (const float) (h->w_scale);
            const size_t num_w_planes = (size_t) (h->num_w_planes);
            FILE* f;
            sprintf(fname, "%s_INPUT.dat", h->input_root);
            f = fopen(fname, "wb");
            fwrite(&num_w_planes, sizeof(size_t), 1, f);
            fwrite(oskar_mem_void_const(h->w_support),
                    sizeof(int), num_w_planes, f);
            fwrite(&h->oversample, sizeof(int), 1, f);
            fwrite(&h->conv_size_half, sizeof(int), 1, f);
            fwrite(oskar_mem_void_const(h->w_kernels), 2 * sizeof(float),
                    h->num_w_planes * h->conv_size_half * h->conv_size_half, f);
            fwrite(&num_vis, sizeof(size_t), 1, f);
            fwrite(oskar_mem_void_const(uu), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(vv), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(ww), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(amps), 2 * sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(weight), sizeof(float), num_vis, f);
            fwrite(&cellsize_rad_tmp, sizeof(float), 1, f);
            fwrite(&w_scale_tmp, sizeof(float), 1, f);
            fwrite(&grid_size, sizeof(int), 1, f);
            fclose(f);
        }
#endif
        oskar_grid_wproj_f(h->num_w_planes,
                oskar_mem_int_const(h->w_support, status),
                h->oversample, h->conv_size_half,
                oskar_mem_float_const(h->w_kernels, status), num_vis,
                oskar_mem_float_const(uu, status),
                oskar_mem_float_const(vv, status),
                oskar_mem_float_const(ww, status),
                oskar_mem_float_const(amps, status),
                oskar_mem_float_const(weight, status),
                (float) (h->cellsize_rad), (float) (h->w_scale),
                grid_size, num_skipped, plane_norm,
                oskar_mem_float(plane, status));
#if SAVE_OUTPUT_DAT
        {
            FILE* f;
            sprintf(fname, "%s_OUTPUT.dat", h->input_root);
            f = fopen(fname, "wb");
            fwrite(num_skipped, sizeof(size_t), 1, f);
            fwrite(plane_norm, sizeof(double), 1, f);
            fwrite(&grid_size, sizeof(int), 1, f);
            fwrite(oskar_mem_void_const(plane), 2 * sizeof(float), num_cells, f);
            fclose(f);
        }
#endif
#if SAVE_GRID
        sprintf(fname, "%s_GRID", h->input_root);
        oskar_mem_write_fits_cube(plane, fname,
                grid_size, grid_size, 1, 0, status);
#endif
        free(fname);
    }
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
void oskar_element_evaluate(const oskar_Element* model, oskar_Mem* output,
        double orientation_x, double orientation_y, int num_points,
        const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z,
        double frequency_hz, oskar_Mem* theta, oskar_Mem* phi, int* status)
{
    int element_type, taper_type, freq_id;
    double dipole_length_m;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Check that the output array is complex. */
    if (!oskar_mem_is_complex(output))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* Resize output array if required. */
    if ((int)oskar_mem_length(output) < num_points)
        oskar_mem_realloc(output, num_points, status);

    /* Get the element model properties. */
    element_type    = model->element_type;
    taper_type      = model->taper_type;
    dipole_length_m = model->dipole_length;
    if (model->dipole_length_units == OSKAR_WAVELENGTHS)
        dipole_length_m *= (C_0 / frequency_hz);

    /* Check if element type is isotropic. */
    if (element_type == OSKAR_ELEMENT_TYPE_ISOTROPIC)
        oskar_mem_set_value_real(output, 1.0, 0, 0, status);

    /* Ensure there is enough space in the theta and phi work arrays. */
    if ((int)oskar_mem_length(theta) < num_points)
        oskar_mem_realloc(theta, num_points, status);
    if ((int)oskar_mem_length(phi) < num_points)
        oskar_mem_realloc(phi, num_points, status);

    /* Compute modified theta and phi coordinates for dipole X. */
    oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z,
            M_PI_2 - orientation_x, theta, phi, status);

    /* Evaluate polarised response if output array is matrix type. */
    if (oskar_mem_is_matrix(output))
    {
        /* Check if spline data present for dipole X. */
        if (oskar_element_has_x_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            /* Evaluate spline pattern for dipole X. */
            oskar_splines_evaluate(output, 0, 8, model->x_h_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 1, 8, model->x_h_im[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 2, 8, model->x_v_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 3, 8, model->x_v_im[freq_id],
                    num_points, theta, phi, status);

            /* Convert from Ludwig-3 to spherical representation. */
            oskar_convert_ludwig3_to_theta_phi_components(output, 0, 4,
                    num_points, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole X. */
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 0, 4, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole X. */
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 0, 4, status);
        }

        /* Compute modified theta and phi coordinates for dipole Y. */
        oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z,
                M_PI_2 - orientation_y, theta, phi, status);

        /* Check if spline data present for dipole Y. */
        if (oskar_element_has_y_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            /* Evaluate spline pattern for dipole Y. */
            oskar_splines_evaluate(output, 4, 8, model->y_h_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 5, 8, model->y_h_im[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 6, 8, model->y_v_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 7, 8, model->y_v_im[freq_id],
                    num_points, theta, phi, status);

            /* Convert from Ludwig-3 to spherical representation. */
            oskar_convert_ludwig3_to_theta_phi_components(output, 2, 4,
                    num_points, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole Y. */
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 2, 4, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole Y. */
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 2, 4, status);
        }
    }

    /* Scalar response. */
    else
    {
        /* Check if scalar spline data present. */
        if (oskar_element_has_scalar_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            oskar_splines_evaluate(output, 0, 2, model->scalar_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 1, 2, model->scalar_im[freq_id],
                    num_points, theta, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 0, 1, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 0, 1, status);
        }
    }

    /* Apply element tapering, if specified. */
    if (taper_type == OSKAR_ELEMENT_TAPER_COSINE)
    {
        oskar_apply_element_taper_cosine(output, num_points,
                model->cosine_power, theta, status);
    }
    else if (taper_type == OSKAR_ELEMENT_TAPER_GAUSSIAN)
    {
        oskar_apply_element_taper_gaussian(output, num_points,
                model->gaussian_fwhm_rad, theta, status);
    }
}
Exemplo n.º 12
0
void oskar_beam_pattern_generate_coordinates(oskar_BeamPattern* h,
        int beam_coord_type, int* status)
{
    size_t num_pixels = 0;
    int nside = 0;

    /* Check if safe to proceed. */
    if (*status) return;

    /* If memory is already allocated, do nothing. */
    if (h->x) return;

    /* Calculate number of pixels if possible. */
    if (h->coord_grid_type == 'B') /* Beam image */
    {
        num_pixels = h->width * h->height;
    }
    else if (h->coord_grid_type == 'H') /* Healpix */
    {
        nside = h->nside;
        num_pixels = 12 * nside * nside;
    }
    else if (h->coord_grid_type == 'S') /* Sky model */
        num_pixels = 0;
    else
    {
        *status = OSKAR_ERR_INVALID_ARGUMENT;
        return;
    }

    /* Create output arrays. */
    h->x = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status);
    h->y = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status);
    h->z = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status);

    /* Get equatorial or horizon coordinates. */
    if (h->coord_frame_type == 'E')
    {
        /*
         * Equatorial coordinates.
         */
        switch (h->coord_grid_type)
        {
        case 'B': /* Beam image */
        {
            oskar_evaluate_image_lmn_grid(h->width, h->height,
                    h->fov_deg[0]*(M_PI/180.0), h->fov_deg[1]*(M_PI/180.0), 1,
                    h->x, h->y, h->z, status);
            break;
        }
        case 'H': /* Healpix */
        {
            int num_points, type, i;
            double ra0 = 0.0, dec0 = 0.0;
            oskar_Mem *theta, *phi;

            /* Generate theta and phi from nside. */
            num_points = 12 * nside * nside;
            type = oskar_mem_type(h->x);
            theta = oskar_mem_create(type, OSKAR_CPU, num_points, status);
            phi = oskar_mem_create(type, OSKAR_CPU, num_points, status);
            oskar_convert_healpix_ring_to_theta_phi(nside, theta, phi, status);

            /* Convert theta from polar angle to elevation. */
            if (type == OSKAR_DOUBLE)
            {
                double* theta_ = oskar_mem_double(theta, status);
                for (i = 0; i < num_points; ++i)
                    theta_[i] = 90.0 - theta_[i];
            }
            else if (type == OSKAR_SINGLE)
            {
                float* theta_ = oskar_mem_float(theta, status);
                for (i = 0; i < num_points; ++i)
                    theta_[i] = 90.0f - theta_[i];
            }
            else
            {
                *status = OSKAR_ERR_BAD_DATA_TYPE;
            }

            /* Evaluate beam phase centre coordinates in equatorial frame. */
            if (beam_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL)
            {
                ra0 = oskar_telescope_phase_centre_ra_rad(h->tel);
                dec0 = oskar_telescope_phase_centre_dec_rad(h->tel);
            }
            else if (beam_coord_type == OSKAR_SPHERICAL_TYPE_AZEL)
            {
                /* TODO convert from az0, el0 to ra0, dec0 */
                *status = OSKAR_FAIL;
            }
            else
            {
                *status = OSKAR_ERR_INVALID_ARGUMENT;
            }

            /* Convert equatorial angles to direction cosines in the frame
             * of the beam phase centre. */
            oskar_convert_lon_lat_to_relative_directions(num_points,
                    phi, theta, ra0, dec0, h->x, h->y, h->z, status);

            /* Free memory. */
            oskar_mem_free(theta, status);
            oskar_mem_free(phi, status);
            break;
        }
        case 'S': /* Sky model */
        {
            oskar_Mem *ra, *dec;
            int type = 0, num_points = 0;
            type = oskar_mem_type(h->x);
            ra = oskar_mem_create(type, OSKAR_CPU, 0, status);
            dec = oskar_mem_create(type, OSKAR_CPU, 0, status);
            load_coords(ra, dec, h->sky_model_file, status);
            num_points = oskar_mem_length(ra);
            oskar_mem_realloc(h->x, num_points, status);
            oskar_mem_realloc(h->y, num_points, status);
            oskar_mem_realloc(h->z, num_points, status);
            oskar_convert_lon_lat_to_relative_directions(
                    num_points, ra, dec,
                    oskar_telescope_phase_centre_ra_rad(h->tel),
                    oskar_telescope_phase_centre_dec_rad(h->tel),
                    h->x, h->y, h->z, status);
            oskar_mem_free(ra, status);
            oskar_mem_free(dec, status);
            break;
        }
        default:
            *status = OSKAR_ERR_INVALID_ARGUMENT;
            break;
        };

        /* Set the return values. */
        h->coord_type = OSKAR_RELATIVE_DIRECTIONS;
        h->lon0 = oskar_telescope_phase_centre_ra_rad(h->tel);
        h->lat0 = oskar_telescope_phase_centre_dec_rad(h->tel);
    }
    else if (h->coord_frame_type == 'H')
    {
        /*
         * Horizon coordinates.
         */
        switch (h->coord_grid_type)
        {
        case 'B': /* Beam image */
        {
            /* NOTE: This is for an all-sky image centred on the zenith. */
            oskar_evaluate_image_lmn_grid(h->width, h->height,
                    M_PI, M_PI, 1, h->x, h->y, h->z, status);
            break;
        }
        case 'H': /* Healpix */
        {
            int num_points, type;
            oskar_Mem *theta, *phi;
            num_points = 12 * nside * nside;
            type = oskar_mem_type(h->x);
            theta = oskar_mem_create(type, OSKAR_CPU, num_points, status);
            phi = oskar_mem_create(type, OSKAR_CPU, num_points, status);
            oskar_convert_healpix_ring_to_theta_phi(nside, theta, phi, status);
            oskar_convert_theta_phi_to_enu_directions(num_points,
                    theta, phi, h->x, h->y, h->z, status);
            oskar_mem_free(theta, status);
            oskar_mem_free(phi, status);
            break;
        }
        default:
            *status = OSKAR_ERR_INVALID_ARGUMENT;
            break;
        };

        /* Set the return values. */
        h->coord_type = OSKAR_ENU_DIRECTIONS;
        h->lon0 = 0.0;
        h->lat0 = M_PI / 2.0;
    }
    else
    {
        *status = OSKAR_ERR_INVALID_ARGUMENT;
    }

    /* Set the number of pixels. */
    h->num_pixels = oskar_mem_length(h->x);
}
Exemplo n.º 13
0
static void load_coords(oskar_Mem* lon, oskar_Mem* lat,
        const char* filename, int* status)
{
    int type = 0;
    FILE* file;
    char* line = 0;
    size_t n = 0, bufsize = 0;

    if (*status) return;

    /* Set initial size of coordinate arrays. */
    type = oskar_mem_precision(lon);
    oskar_mem_realloc(lon, 100, status);
    oskar_mem_realloc(lat, 100, status);

    /* Open the file. */
    file = fopen(filename, "r");
    if (!file)
    {
        *status = OSKAR_ERR_FILE_IO;
        return;
    }

    /* Loop over lines in file. */
    while (oskar_getline(&line, &bufsize, file) != OSKAR_ERR_EOF)
    {
        /* Set defaults. */
        /* Longitude, latitude. */
        double par[] = {0., 0.};
        size_t num_param = sizeof(par) / sizeof(double);
        size_t num_required = 2, num_read = 0;

        /* Load coordinates. */
        num_read = oskar_string_to_array_d(line, num_param, par);
        if (num_read < num_required) continue;

        /* Ensure enough space in arrays. */
        if (oskar_mem_length(lon) <= n)
        {
            oskar_mem_realloc(lon, n + 100, status);
            oskar_mem_realloc(lat, n + 100, status);
            if (*status) break;
        }

        /* Store the coordinates. */
        if (type == OSKAR_DOUBLE)
        {
            oskar_mem_double(lon, status)[n] = par[0] * M_PI/180.0;
            oskar_mem_double(lat, status)[n] = par[1] * M_PI/180.0;
        }
        else
        {
            oskar_mem_float(lon, status)[n] = par[0] * M_PI/180.0;
            oskar_mem_float(lat, status)[n] = par[1] * M_PI/180.0;
        }

        ++n;
    }

    /* Resize output arrays to final size. */
    oskar_mem_realloc(lon, n, status);
    oskar_mem_realloc(lat, n, status);

    fclose(file);
    free(line);
}
Exemplo n.º 14
0
void oskar_station_resize(oskar_Station* station, int num_elements,
        int* status)
{
    /* Check if safe to proceed. */
    if (*status) return;

    /* Resize arrays in the model. */
    oskar_mem_realloc(station->element_true_x_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_true_y_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_true_z_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_measured_x_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_measured_y_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_measured_z_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_weight, num_elements, status);
    oskar_mem_realloc(station->element_gain, num_elements, status);
    oskar_mem_realloc(station->element_gain_error, num_elements, status);
    oskar_mem_realloc(station->element_phase_offset_rad, num_elements, status);
    oskar_mem_realloc(station->element_phase_error_rad, num_elements, status);
    oskar_mem_realloc(station->element_x_alpha_cpu, num_elements, status);
    oskar_mem_realloc(station->element_x_beta_cpu, num_elements, status);
    oskar_mem_realloc(station->element_x_gamma_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_alpha_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_beta_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_gamma_cpu, num_elements, status);
    oskar_mem_realloc(station->element_types, num_elements, status);
    oskar_mem_realloc(station->element_types_cpu, num_elements, status);
    oskar_mem_realloc(station->element_mount_types_cpu, num_elements, status);

    /* Initialise any new elements with default values. */
    if (num_elements > station->num_elements)
    {
        int offset, num_new;
        offset = station->num_elements;
        num_new = num_elements - offset;

        /* Must set default element weight, gain and orientation. */
        oskar_mem_set_value_real(station->element_gain,
                1.0, offset, num_new, status);
        oskar_mem_set_value_real(station->element_weight,
                1.0, offset, num_new, status);
        memset(oskar_mem_char(station->element_mount_types_cpu) + offset,
                'F', num_new);
    }

    /* Set the new number of elements. */
    station->num_elements = num_elements;
}
Exemplo n.º 15
0
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);
}