Ejemplo n.º 1
0
void oskar_mem_read_element(const oskar_Mem* mem, size_t index,
        void* out, int* status)
{
    if (*status) return;
    const size_t bytes = oskar_mem_element_size(mem->type);
    const size_t offset = bytes * index;
    if (mem->location == OSKAR_CPU)
    {
        const char* from = ((const char*) mem->data) + offset;
        memcpy(out, (const void*)from, bytes);
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        const char* from = ((const char*) mem->data) + offset;
        cudaMemcpy(out, (const void*)from, bytes, cudaMemcpyDeviceToHost);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (mem->location & OSKAR_CL)
    {
#ifdef OSKAR_HAVE_OPENCL
        const cl_int error = clEnqueueReadBuffer(oskar_device_queue_cl(),
                mem->buffer, CL_TRUE, offset, bytes, out, 0, NULL, NULL);
        if (error != CL_SUCCESS)
            *status = OSKAR_ERR_MEMORY_COPY_FAILURE;
#else
        *status = OSKAR_ERR_OPENCL_NOT_AVAILABLE;
#endif
    }
    else
        *status = OSKAR_ERR_BAD_LOCATION;
}
Ejemplo n.º 2
0
void oskar_mem_clear_contents(oskar_Mem* mem, int* status)
{
    size_t size;

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

    /* Compute the size. */
    size = mem->num_elements * oskar_mem_element_size(mem->type);

    /* Clear the memory. */
    if (mem->location == OSKAR_CPU)
    {
        memset(mem->data, 0, size);
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemset(mem->data, 0, size);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
Ejemplo n.º 3
0
int oskar_mem_different(const oskar_Mem* one, const oskar_Mem* two,
        size_t num_elements, int* status)
{
    size_t bytes_to_check;

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

    /* Check that both arrays exist. */
    if ((!one && two) || (one && !two)) return OSKAR_TRUE;

    /* If neither array exists, return false. */
    if (!one && !two) return OSKAR_FALSE;

    /* Check the data types. */
    if (one->type != two->type) return OSKAR_TRUE;

    /* Check the number of elements. */
    if (num_elements == 0 || num_elements > one->num_elements)
        num_elements = one->num_elements;
    if (num_elements > two->num_elements)
        return OSKAR_TRUE;
    bytes_to_check = num_elements * oskar_mem_element_size(one->type);

    /* Check data location. */
    if (one->location == OSKAR_CPU && two->location == OSKAR_CPU)
        return (memcmp(one->data, two->data, bytes_to_check) != 0);

    /* Data checks are only supported in CPU memory. */
    *status = OSKAR_ERR_BAD_LOCATION;
    return OSKAR_TRUE;
}
Ejemplo n.º 4
0
oskar_Mem* oskar_mem_create_alias(const oskar_Mem* src, size_t offset,
        size_t num_elements, int* status)
{
    oskar_Mem* mem = 0;

    /* Create the structure, initialised with all bits zero. */
    mem = (oskar_Mem*) calloc(1, sizeof(oskar_Mem));
    if (!mem)
    {
        *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
        return 0;
    }

    /* Initialise meta-data.
     * (This must happen regardless of the status code.) */
    mem->owner = 0; /* Structure does not own the memory. */
    if (src)
    {
        size_t offset_bytes;
        offset_bytes = offset * oskar_mem_element_size(src->type);
        mem->type = src->type;
        mem->location = src->location;
        mem->num_elements = num_elements;
        mem->data = (void*)(((char*)(src->data)) + offset_bytes);
    }

    /* Return a handle the new structure .*/
    return mem;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
void oskar_mem_clear_contents(oskar_Mem* mem, int* status)
{
    size_t size;

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

    /* Compute the size. */
    size = mem->num_elements * oskar_mem_element_size(mem->type);

    /* Clear the memory. */
    if (mem->location == OSKAR_CPU)
    {
        memset(mem->data, 0, size);
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemset(mem->data, 0, size);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (mem->location & OSKAR_CL)
    {
#ifdef OSKAR_HAVE_OPENCL
        cl_event event;
        cl_int error;
        char zero = '\0';
        error = clEnqueueFillBuffer(oskar_cl_command_queue(),
                mem->buffer, &zero, sizeof(char), 0, size, 0, NULL, &event);
        clWaitForEvents(1, &event); /* This is required. */
        if (error != CL_SUCCESS)
        {
            fprintf(stderr, "clEnqueueFillBuffer() error (%d)\n", error);
            *status = OSKAR_ERR_INVALID_ARGUMENT;
        }
#else
        *status = OSKAR_ERR_OPENCL_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
Ejemplo n.º 8
0
void oskar_imager_trim_image(oskar_Mem* plane,
        int plane_size, int image_size, int* status)
{
    int i, num_cells, size_diff;
    if (*status) return;

    /* Get the real part only, if the plane is complex. */
    if (oskar_mem_is_complex(plane))
    {
        num_cells = plane_size * plane_size;
        if (oskar_mem_precision(plane) == OSKAR_DOUBLE)
        {
            double *t = oskar_mem_double(plane, status);
            for (i = 0; i < num_cells; ++i) t[i] = t[2 * i];
        }
        else
        {
            float *t = oskar_mem_float(plane, status);
            for (i = 0; i < num_cells; ++i) t[i] = t[2 * i];
        }
    }

    /* Trim to required image size. */
    size_diff = plane_size - image_size;
    if (size_diff > 0)
    {
        char *ptr;
        size_t in = 0, out = 0, copy_len = 0, element_size = 0;
        ptr = oskar_mem_char(plane);
        element_size = oskar_mem_element_size(oskar_mem_precision(plane));
        copy_len = element_size * image_size;
        in = element_size * (size_diff / 2) * (plane_size + 1);
        for (i = 0; i < image_size; ++i)
        {
            /* Use memmove() instead of memcpy() to allow for overlap. */
            memmove(ptr + out, ptr + in, copy_len);
            in += plane_size * element_size;
            out += copy_len;
        }
    }
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
void oskar_mem_set_alias(oskar_Mem* mem, const oskar_Mem* src, size_t offset,
        size_t num_elements, int* status)
{
    size_t element_size = 0, offset_bytes = 0;

    /* The destination structure must not own its memory.
     * The structure must have been created using oskar_mem_create_alias*(),
     * so the owner flag must be set to false. */
    if (mem->owner)
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Check that the new pointer will be valid. */
    if (offset + num_elements > src->num_elements)
    {
        *status = OSKAR_ERR_OUT_OF_RANGE;
        return;
    }

    /* Get the element size. */
    element_size = oskar_mem_element_size(src->type);
    if (element_size == 0)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* Compute the offset for the new pointer. */
    offset_bytes = offset * element_size;

    /* Set meta-data. */
    mem->type = src->type;
    mem->location = src->location;
    mem->num_elements = num_elements;
    mem->data = (void*)((char*)(src->data) + offset_bytes);
}
Ejemplo n.º 11
0
void oskar_mem_realloc(oskar_Mem* mem, size_t num_elements, int* status)
{
    size_t element_size, new_size, old_size;

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

    /* Check if the structure owns the memory it points to. */
    if (mem->owner == 0)
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Get size of new and old memory blocks. */
    element_size = oskar_mem_element_size(mem->type);
    if (element_size == 0)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    new_size = num_elements * element_size;
    old_size = mem->num_elements * element_size;

    /* Do nothing if new size and old size are the same. */
    if (new_size == old_size)
        return;

    /* Check memory location. */
    if (mem->location == OSKAR_CPU)
    {
        /* Reallocate the memory. */
        void* mem_new = NULL;
        mem_new = realloc(mem->data, new_size);
        if (!mem_new && (new_size > 0))
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Initialise the new memory if it's larger than the old block. */
        if (new_size > old_size)
            memset((char*)mem_new + old_size, 0, new_size - old_size);

        /* Set the new meta-data. */
        mem->data = (new_size > 0) ? mem_new : 0;
        mem->num_elements = num_elements;
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        /* Allocate and initialise a new block of memory. */
        int cuda_error = 0;
        size_t copy_size;
        void* mem_new = NULL;
        if (new_size > 0)
        {
            cuda_error = cudaMalloc(&mem_new, new_size);
            if (cuda_error)
            {
                *status = cuda_error;
                return;
            }
            if (!mem_new)
            {
                *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
                return;
            }
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            cuda_error = cudaMemcpy(mem_new, mem->data, copy_size,
                    cudaMemcpyDeviceToDevice);
        }
        if (cuda_error)
        {
            *status = cuda_error;
            return;
        }

        /* Free the old block. */
        cudaFree(mem->data);
        oskar_device_check_error(status);

        /* Set the new meta-data. */
        mem->data = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
Ejemplo n.º 12
0
void oskar_mem_realloc(oskar_Mem* mem, size_t num_elements, int* status)
{
    size_t element_size, new_size, old_size;

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

    /* Check if the structure owns the memory it points to. */
    if (mem->owner == 0)
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Get size of new and old memory blocks. */
    element_size = oskar_mem_element_size(mem->type);
    if (element_size == 0)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    new_size = num_elements * element_size;
    old_size = mem->num_elements * element_size;

    /* Do nothing if new size and old size are the same. */
    if (new_size == old_size)
        return;

    /* Check memory location. */
    if (mem->location == OSKAR_CPU)
    {
        /* Reallocate the memory. */
        void* mem_new = NULL;
        mem_new = realloc(mem->data, new_size);
        if (!mem_new && (new_size > 0))
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Initialise the new memory if it's larger than the old block. */
        if (new_size > old_size)
            memset((char*)mem_new + old_size, 0, new_size - old_size);

        /* Set the new meta-data. */
        mem->data = (new_size > 0) ? mem_new : 0;
        mem->num_elements = num_elements;
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        /* Allocate and initialise a new block of memory. */
        int cuda_error = 0;
        size_t copy_size;
        void* mem_new = NULL;
        if (new_size > 0)
        {
            cuda_error = cudaMalloc(&mem_new, new_size);
            if (cuda_error)
            {
                *status = cuda_error;
                return;
            }
            if (!mem_new)
            {
                *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
                return;
            }
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            cuda_error = cudaMemcpy(mem_new, mem->data, copy_size,
                    cudaMemcpyDeviceToDevice);
        }
        if (cuda_error)
        {
            *status = cuda_error;
            return;
        }

        /* Free the old block. */
        cudaFree(mem->data);
        oskar_device_check_error(status);

        /* Set the new meta-data. */
        mem->data = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (mem->location & OSKAR_CL)
    {
#ifdef OSKAR_HAVE_OPENCL
        /* Allocate and initialise a new block of memory. */
        cl_int error = 0;
        size_t copy_size;
        cl_mem mem_new;
        mem_new = clCreateBuffer(oskar_cl_context(),
                CL_MEM_READ_WRITE, new_size, NULL, &error);
        if (error != CL_SUCCESS)
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            error = clEnqueueCopyBuffer(oskar_cl_command_queue(), mem->buffer,
                    mem_new, 0, 0, copy_size, 0, NULL, NULL);
            if (error != CL_SUCCESS)
            {
                fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
                *status = OSKAR_ERR_MEMORY_COPY_FAILURE;
            }
        }

        /* Free the old buffer. */
        clReleaseMemObject(mem->buffer);

        /* Set the new meta-data. */
        mem->buffer = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_OPENCL_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
Ejemplo n.º 13
0
void oskar_mem_copy_contents(oskar_Mem* dst, const oskar_Mem* src,
        size_t offset_dst, size_t offset_src, size_t num_elements, int* status)
{
    int location_src, location_dst;
    size_t bytes, element_size, start_dst, start_src;
    void *destination;
    const void *source;

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

    /* Return immediately if there is nothing to copy. */
    if (src->data == NULL || src->num_elements == 0 || num_elements == 0)
        return;

    /* Check the data types. */
    if (src->type != dst->type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Check the data dimensions. */
    if (num_elements > src->num_elements ||
            num_elements > (dst->num_elements - offset_dst))
    {
        *status = OSKAR_ERR_OUT_OF_RANGE;
        return;
    }

    /* Get the number of bytes to copy. */
    element_size = oskar_mem_element_size(src->type);
    bytes        = element_size * num_elements;
    start_dst    = element_size * offset_dst;
    start_src    = element_size * offset_src;
    destination  = (void*)((char*)(dst->data) + start_dst);
    source       = (const void*)((const char*)(src->data) + start_src);
    location_src = src->location;
    location_dst = dst->location;

    /* Host to host. */
    if (location_src == OSKAR_CPU && location_dst == OSKAR_CPU)
    {
        memcpy(destination, source, bytes);
        return;
    }

    /* Host to device. */
    else if (location_src == OSKAR_CPU && location_dst == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyHostToDevice);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    /* Device to host. */
    else if (location_src == OSKAR_GPU && location_dst == OSKAR_CPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyDeviceToHost);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    /* Device to device. */
    else if (location_src == OSKAR_GPU && location_dst == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyDeviceToDevice);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    *status = OSKAR_ERR_BAD_LOCATION;
}
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
}