123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- /*
- * Copyright (C) 2011-2014 Karlsruhe Institute of Technology
- *
- * This file is part of Ufo.
- *
- * This library is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include <glib.h>
- #include <glib/gprintf.h>
- #ifdef __APPLE__
- #include <OpenCL/cl.h>
- #else
- #include <CL/cl.h>
- #endif
- #include "ufo-anka-backproject-task.h"
- /* Copy only neccessary projection region */
- /* TODO: make this a parameter? */
- #define COPY_PROJECTION_REGION 1
- #define EXTRACT_INT(region, index) g_value_get_int (g_value_array_get_nth ((region), (index)))
- #define EXTRACT_FLOAT(region, index) g_value_get_float (g_value_array_get_nth ((region), (index)))
- #define REGION_SIZE(region) ((EXTRACT_INT ((region), 2)) == 0) ? 0 : \
- ((EXTRACT_INT ((region), 1) - EXTRACT_INT ((region), 0) - 1) /\
- EXTRACT_INT ((region), 2) + 1)
- #define PAD_TO_DIVIDE(dividend, divisor) ((dividend) + (divisor) - (dividend) % (divisor))
- /**
- * SECTION:ufo-anka-backproject-task
- * @Short_description: Backproject projection by projection
- * @Title: anka_backproject
- *
- */
- struct _UfoAnkaBackprojectTaskPrivate {
- /* private */
- gboolean generated;
- guint count;
- /* sine and cosine table size based on BURST */
- gsize table_size;
- /* OpenCL */
- cl_context context;
- cl_kernel vector_kernel;
- cl_kernel scalar_kernel;
- cl_sampler sampler;
- /* Buffered images for invoking backprojection on BURST projections at once.
- * We potentially don't need to copy the last image and can use the one from
- * framework directly but it seems to have no performance effects. */
- cl_mem images[BURST];
- /* properties */
- GValueArray *x_region;
- GValueArray *y_region;
- GValueArray *z_region;
- GValueArray *center;
- GValueArray *projection_offset;
- float sines[BURST], cosines[BURST];
- guint num_projections;
- gfloat overall_angle;
- gfloat tomo_angle;
- gfloat lamino_angle;
- };
- static void ufo_task_interface_init (UfoTaskIface *iface);
- G_DEFINE_TYPE_WITH_CODE (UfoAnkaBackprojectTask, ufo_anka_backproject_task, UFO_TYPE_TASK_NODE,
- G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK,
- ufo_task_interface_init))
- #define UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_ANKA_BACKPROJECT_TASK, UfoAnkaBackprojectTaskPrivate))
- enum {
- PROP_0,
- PROP_X_REGION,
- PROP_Y_REGION,
- PROP_Z_REGION,
- PROP_PROJECTION_OFFSET,
- PROP_CENTER,
- PROP_NUM_PROJECTIONS,
- PROP_OVERALL_ANGLE,
- PROP_TOMO_ANGLE,
- PROP_LAMINO_ANGLE,
- N_PROPERTIES
- };
- static GParamSpec *properties[N_PROPERTIES] = { NULL, };
- static inline void
- swap (gint *first, gint *second) {
- gint tmp;
- tmp = *first;
- *first = *second;
- *second = tmp;
- }
- /**
- * Determine the left and right column to read from a projection at a given
- * tomographic angle.
- */
- static void
- determine_x_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_extrema,
- gfloat tomo_angle, gfloat x_center)
- {
- gfloat sin_tomo, cos_tomo;
- gint x_min, x_max, y_min, y_max;
- sin_tomo = sin (tomo_angle);
- cos_tomo = cos (tomo_angle);
- x_min = EXTRACT_INT (x_extrema, 0);
- /* The interval is right-opened when OpenCL indices for both x and y are generated, */
- /* so the last index doesn't count */
- x_max = EXTRACT_INT (x_extrema, 1) - 1;
- y_min = EXTRACT_INT (y_extrema, 0);
- y_max = EXTRACT_INT (y_extrema, 1) - 1;
- if (sin_tomo < 0) {
- swap (&y_min, &y_max);
- }
- if (cos_tomo < 0) {
- swap (&x_min, &x_max);
- }
- extrema[0] = cos_tomo * x_min + sin_tomo * y_min + x_center;
- /* +1 because extrema[1] will be accessed by interpolation
- * but the region in copying is right-open */
- extrema[1] = cos_tomo * x_max + sin_tomo * y_max + x_center + 1;
- }
- /**
- * Determine the top and bottom row to read from a projection at given
- * tomographic and laminographic angles.
- */
- static void
- determine_y_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_extrema,
- GValueArray *z_extrema, gfloat tomo_angle, gfloat lamino_angle,
- gfloat y_center)
- {
- gfloat sin_tomo, cos_tomo, sin_lamino, cos_lamino;
- gint x_min, x_max, y_min, y_max;
- sin_tomo = sin (tomo_angle);
- cos_tomo = cos (tomo_angle);
- sin_lamino = sin (lamino_angle);
- cos_lamino = cos (lamino_angle);
- x_min = EXTRACT_INT (x_extrema, 0);
- x_max = EXTRACT_INT (x_extrema, 1) - 1;
- y_min = EXTRACT_INT (y_extrema, 0);
- y_max = EXTRACT_INT (y_extrema, 1) - 1;
- if (sin_tomo < 0) {
- swap (&x_min, &x_max);
- }
- if (cos_tomo > 0) {
- swap (&y_min, &y_max);
- }
- extrema[0] = sin_tomo * x_min - cos_tomo * y_min;
- extrema[1] = sin_tomo * x_max - cos_tomo * y_max;
- extrema[0] = extrema[0] * cos_lamino + EXTRACT_INT (z_extrema, 0) * sin_lamino + y_center;
- extrema[1] = extrema[1] * cos_lamino + EXTRACT_INT (z_extrema, 1) * sin_lamino + y_center + 1;
- }
- /**
- * clip:
- * @result: resulting clipped extrema
- * @extrema: (min, max)
- * @maximum: projection width or height
- *
- * Clip extrema to an allowed interval [0, projection width/height)
- */
- static void
- clip (gint result[2], gfloat extrema[2], gint maximum)
- {
- result[0] = (gint) floorf (extrema[0]);
- result[1] = (gint) ceilf (extrema[1]);
- if (result[0] < 0) {
- result[0] = 0;
- }
- if (result[0] > maximum) {
- result[0] = maximum;
- }
- if (result[1] < 0) {
- result[1] = 0;
- }
- if (result[1] > maximum) {
- result[1] = maximum;
- }
- if (result[0] == result[1]) {
- if (result[1] < maximum) {
- result[1]++;
- } else if (result[0] > 0) {
- result[0]--;
- } else {
- g_warning ("Cannot extend");
- }
- } else if (result[0] > result[1]) {
- g_warning ("Invalid extrema: minimum larger than maximum");
- }
- }
- /**
- * Determine the left and right column to read from a projection at a given
- * tomographic angle. The result is bound to [0, projection width)
- */
- static void
- determine_x_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat tomo_angle,
- gfloat x_center, gint width)
- {
- gfloat extrema[2];
- determine_x_extrema (extrema, x_extrema, y_extrema, tomo_angle, x_center);
- clip (result, extrema, width);
- }
- /**
- * Determine the top and bottom column to read from a projection at given
- * tomographic and laminographic angles. The result is bound to
- * [0, projection height).
- */
- static void
- determine_y_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, GValueArray *z_extrema,
- gfloat tomo_angle, gfloat lamino_angle, gfloat y_center, gint height)
- {
- gfloat extrema[2];
- determine_y_extrema (extrema, x_extrema, y_extrema, z_extrema, tomo_angle,
- lamino_angle, y_center);
- clip (result, extrema, height);
- }
- static void
- set_region (GValueArray *src, GValueArray **dst)
- {
- if (EXTRACT_INT (src, 0) > EXTRACT_INT (src, 1)) {
- g_log ("Ufo", G_LOG_LEVEL_CRITICAL,
- "Error <%s:%i>: Invalid region [\"from\", \"to\", \"step\"]: [%d, %d, %d], "\
- "\"from\" has to be less than or equal to \"to\"",
- __FILE__, __LINE__,
- EXTRACT_INT (src, 0), EXTRACT_INT (src, 1), EXTRACT_INT (src, 2));
- }
- else {
- g_value_array_free (*dst);
- *dst = g_value_array_copy (src);
- }
- }
- UfoNode *
- ufo_anka_backproject_task_new (void)
- {
- return UFO_NODE (g_object_new (UFO_TYPE_ANKA_BACKPROJECT_TASK, NULL));
- }
- static void
- ufo_anka_backproject_task_setup (UfoTask *task,
- UfoResources *resources,
- GError **error)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- cl_int cl_error;
- gint i;
- gchar vector_kernel_name[30];
- if (!g_sprintf (vector_kernel_name, "backproject_burst_%d", BURST)) {
- g_warning ("Error making burst kernel name");
- }
- priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (task);
- priv->context = ufo_resources_get_context (resources);
- priv->vector_kernel = ufo_resources_get_kernel (resources, "ankabackprojectburst.cl",
- vector_kernel_name, error);
- priv->scalar_kernel = ufo_resources_get_kernel (resources, "ankabackprojectburst.cl",
- "backproject_burst_1", error);
- priv->sampler = clCreateSampler (priv->context,
- (cl_bool) FALSE,
- CL_ADDRESS_CLAMP,
- CL_FILTER_LINEAR,
- &cl_error);
- UFO_RESOURCES_CHECK_CLERR (clRetainContext (priv->context));
- UFO_RESOURCES_CHECK_CLERR (cl_error);
- if (priv->vector_kernel) {
- UFO_RESOURCES_CHECK_CLERR (clRetainKernel (priv->vector_kernel));
- }
- if (priv->scalar_kernel) {
- UFO_RESOURCES_CHECK_CLERR (clRetainKernel (priv->scalar_kernel));
- }
- for (i = 0; i < BURST; i++) {
- priv->images[i] = NULL;
- }
- switch (BURST) {
- case 1: priv->table_size = sizeof (cl_float); break;
- case 2: priv->table_size = sizeof (cl_float2); break;
- case 4: priv->table_size = sizeof (cl_float4); break;
- case 8: priv->table_size = sizeof (cl_float8); break;
- case 16: priv->table_size = sizeof (cl_float16); break;
- default: g_warning ("Unsupported vector size"); break;
- }
- }
- static void
- ufo_anka_backproject_task_get_requisition (UfoTask *task,
- UfoBuffer **inputs,
- UfoRequisition *requisition)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (task);
- if (!priv->num_projections) {
- g_warning ("Number of projections has not been set");
- }
- requisition->n_dims = 3;
- requisition->dims[0] = REGION_SIZE (priv->x_region);
- requisition->dims[1] = REGION_SIZE (priv->y_region);
- requisition->dims[2] = REGION_SIZE (priv->z_region);
- }
- static guint
- ufo_anka_backproject_task_get_num_inputs (UfoTask *task)
- {
- return 1;
- }
- static guint
- ufo_anka_backproject_task_get_num_dimensions (UfoTask *task,
- guint input)
- {
- g_return_val_if_fail (input == 0, 0);
- return 3;
- }
- static gboolean
- ufo_anka_backproject_task_equal_real (UfoNode *n1,
- UfoNode *n2)
- {
- g_return_val_if_fail (UFO_IS_ANKA_BACKPROJECT_TASK (n1) && UFO_IS_ANKA_BACKPROJECT_TASK (n2), FALSE);
- return UFO_ANKA_BACKPROJECT_TASK (n1)->priv->vector_kernel == UFO_ANKA_BACKPROJECT_TASK (n2)->priv->vector_kernel;
- }
- static UfoTaskMode
- ufo_anka_backproject_task_get_mode (UfoTask *task)
- {
- return UFO_TASK_MODE_REDUCTOR | UFO_TASK_MODE_GPU;
- }
- static gboolean
- ufo_anka_backproject_task_process (UfoTask *task,
- UfoBuffer **inputs,
- UfoBuffer *output,
- UfoRequisition *requisition)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- UfoGpuNode *node;
- UfoProfiler *profiler;
- gfloat tomo_angle, *sines, *cosines;
- gint i, index;
- gint cumulate;
- gsize table_size;
- gboolean scalar;
- /* regions stripped off the "to" value */
- gfloat x_region[2], y_region[2], z_region[2], center[2], sin_lamino, cos_lamino;
- gint x_copy_region[2], y_copy_region[2];
- cl_kernel kernel;
- cl_command_queue cmd_queue;
- cl_mem image;
- cl_mem out_mem;
- cl_int cl_error;
- /* image creation and copying */
- size_t im_width, im_height;
- cl_image_format image_fmt;
- size_t origin[3];
- size_t region[3];
- /* keep the warp size satisfied but make sure the local grid is localized
- * around a point in 3D for efficient caching */
- const gint real_size[4] = {requisition->dims[0], requisition->dims[1], requisition->dims[2], 0};
- const gsize local_work_size[] = {16, 8, 8};
- gsize global_work_size[3];
- global_work_size[0] = requisition->dims[0] % local_work_size[0] ?
- PAD_TO_DIVIDE (requisition->dims[0], local_work_size[0]) :
- requisition->dims[0];
- global_work_size[1] = requisition->dims[1] % local_work_size[1] ?
- PAD_TO_DIVIDE (requisition->dims[1], local_work_size[1]) :
- requisition->dims[1];
- global_work_size[2] = requisition->dims[2] % local_work_size[2] ?
- PAD_TO_DIVIDE (requisition->dims[2], local_work_size[2]) :
- requisition->dims[2];
- priv = UFO_ANKA_BACKPROJECT_TASK (task)->priv;
- node = UFO_GPU_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task)));
- cmd_queue = ufo_gpu_node_get_cmd_queue (node);
- out_mem = ufo_buffer_get_device_array (output, cmd_queue);
- /* TODO: Get host/buffer/image depending on where the data *currently* resides. */
- /* This Must be made available in UFO core first. */
- image = ufo_buffer_get_device_image (inputs[0], cmd_queue);
- index = priv->count % BURST;
- tomo_angle = priv->tomo_angle > -G_MAXFLOAT ? priv->tomo_angle :
- priv->overall_angle * priv->count / priv->num_projections;
- priv->sines[index] = sin (tomo_angle);
- priv->cosines[index] = cos (tomo_angle);
- x_region[0] = (gfloat) EXTRACT_INT (priv->x_region, 0);
- x_region[1] = (gfloat) EXTRACT_INT (priv->x_region, 2);
- y_region[0] = (gfloat) EXTRACT_INT (priv->y_region, 0);
- y_region[1] = (gfloat) EXTRACT_INT (priv->y_region, 2);
- z_region[0] = (gfloat) EXTRACT_INT (priv->z_region, 0);
- z_region[1] = (gfloat) EXTRACT_INT (priv->z_region, 2);
- center[0] = EXTRACT_FLOAT (priv->center, 0) - EXTRACT_INT (priv->projection_offset, 0);
- center[1] = EXTRACT_FLOAT (priv->center, 1) - EXTRACT_INT (priv->projection_offset, 1);
- sin_lamino = sinf (priv->lamino_angle);
- cos_lamino = cosf (priv->lamino_angle);
- scalar = priv->count >= priv->num_projections / BURST * BURST ? 1 : 0;
- /* copy the image for further usage once BURST images arrived */
- clGetImageInfo (image, CL_IMAGE_WIDTH, sizeof (size_t), &im_width, NULL);
- clGetImageInfo (image, CL_IMAGE_HEIGHT, sizeof (size_t), &im_height, NULL);
- /* If COPY_PROJECTION_REGION is True we copy only the part necessary */
- /* for a given tomographic and laminographic angle */
- if (COPY_PROJECTION_REGION) {
- determine_x_region (x_copy_region, priv->x_region, priv->y_region, tomo_angle,
- EXTRACT_FLOAT (priv->center, 0), im_width);
- determine_y_region (y_copy_region, priv->x_region, priv->y_region, priv->z_region,
- tomo_angle, priv->lamino_angle, EXTRACT_FLOAT (priv->center, 1),
- im_height);
- origin[0] = x_copy_region[0];
- origin[1] = y_copy_region[0];
- origin[2] = 0;
- region[0] = x_copy_region[1] - x_copy_region[0];
- region[1] = y_copy_region[1] - y_copy_region[0];
- } else {
- origin[0] = origin[1] = origin[2] = 0;
- region[0] = im_width;
- region[1] = im_height;
- }
- region[2] = 1;
- if (priv->images[index] == NULL) {
- clGetImageInfo (image, CL_IMAGE_FORMAT, sizeof (cl_image_format), &image_fmt, NULL);
- /* TODO: what with the "other" API? */
- priv->images[index] = clCreateImage2D (priv->context,
- CL_MEM_READ_ONLY,
- &image_fmt,
- im_width,
- im_height,
- 0,
- NULL,
- &cl_error);
- UFO_RESOURCES_CHECK_CLERR (cl_error);
- }
- UFO_RESOURCES_CHECK_CLERR (clEnqueueCopyImage (cmd_queue,
- image,
- priv->images[index],
- origin,
- origin,
- region,
- 0,
- NULL,
- NULL));
- if (scalar) {
- kernel = priv->scalar_kernel;
- cumulate = priv->count;
- table_size = sizeof (cl_float);
- sines = &priv->sines[index];
- cosines = &priv->cosines[index];
- i = 1;
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, 0, sizeof (cl_mem), &priv->images[index]));
- } else {
- kernel = priv->vector_kernel;
- cumulate = priv->count + 1 == BURST ? 0 : 1;
- table_size = priv->table_size;
- sines = priv->sines;
- cosines = priv->cosines;
- i = BURST;
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, index, sizeof (cl_mem), &priv->images[index]));
- }
- if (scalar || index == BURST - 1) {
- /* Execute the kernel after BURST images have arrived, i.e. we use more
- * projections at one invocation, so the number of read/writes to the
- * result is reduced by a factor of BURST. If there are not enough
- * projecttions left, execute the scalar kernel */
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_mem), &out_mem));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_sampler), &priv->sampler));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_int3), real_size));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float2), center));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float2), x_region));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float2), y_region));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float2), z_region));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float), &sin_lamino));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float), &cos_lamino));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, table_size, sines));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, table_size, cosines));
- UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i, sizeof (cl_int), (cl_int *) &cumulate));
- profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task));
- ufo_profiler_call (profiler, cmd_queue, kernel, 3, global_work_size, local_work_size);
- }
- priv->count++;
- return TRUE;
- }
- static gboolean
- ufo_anka_backproject_task_generate (UfoTask *task,
- UfoBuffer *output,
- UfoRequisition *requisition)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (task);
- if (priv->generated) {
- return FALSE;
- }
- priv->generated = TRUE;
- return TRUE;
- }
- static void
- ufo_anka_backproject_task_finalize (GObject *object)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- gint i;
- priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (object);
- g_value_array_free (priv->x_region);
- g_value_array_free (priv->y_region);
- g_value_array_free (priv->z_region);
- g_value_array_free (priv->projection_offset);
- g_value_array_free (priv->center);
- if (priv->vector_kernel) {
- UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->vector_kernel));
- priv->vector_kernel = NULL;
- }
- if (priv->scalar_kernel) {
- UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->scalar_kernel));
- priv->scalar_kernel = NULL;
- }
- if (priv->context) {
- UFO_RESOURCES_CHECK_CLERR (clReleaseContext (priv->context));
- priv->context = NULL;
- }
- if (priv->sampler) {
- UFO_RESOURCES_CHECK_CLERR (clReleaseSampler (priv->sampler));
- priv->sampler = NULL;
- }
- for (i = 0; i < BURST; i++) {
- if (priv->images[i] != NULL) {
- UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->images[i]));
- priv->images[i] = NULL;
- }
- }
- G_OBJECT_CLASS (ufo_anka_backproject_task_parent_class)->finalize (object);
- }
- static void
- ufo_task_interface_init (UfoTaskIface *iface)
- {
- iface->setup = ufo_anka_backproject_task_setup;
- iface->get_requisition = ufo_anka_backproject_task_get_requisition;
- iface->get_num_inputs = ufo_anka_backproject_task_get_num_inputs;
- iface->get_num_dimensions = ufo_anka_backproject_task_get_num_dimensions;
- iface->get_mode = ufo_anka_backproject_task_get_mode;
- iface->process = ufo_anka_backproject_task_process;
- iface->generate = ufo_anka_backproject_task_generate;
- }
- static void
- ufo_anka_backproject_task_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
- {
- UfoAnkaBackprojectTaskPrivate *priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (object);
- GValueArray *array;
- switch (property_id) {
- case PROP_X_REGION:
- array = (GValueArray *) g_value_get_boxed (value);
- set_region (array, &priv->x_region);
- break;
- case PROP_Y_REGION:
- array = (GValueArray *) g_value_get_boxed (value);
- set_region (array, &priv->y_region);
- break;
- case PROP_Z_REGION:
- array = (GValueArray *) g_value_get_boxed (value);
- set_region (array, &priv->z_region);
- break;
- case PROP_PROJECTION_OFFSET:
- array = (GValueArray *) g_value_get_boxed (value);
- g_value_array_free (priv->projection_offset);
- priv->projection_offset = g_value_array_copy (array);
- break;
- case PROP_CENTER:
- array = (GValueArray *) g_value_get_boxed (value);
- g_value_array_free (priv->center);
- priv->center = g_value_array_copy (array);
- break;
- case PROP_NUM_PROJECTIONS:
- priv->num_projections = g_value_get_uint (value);
- break;
- case PROP_OVERALL_ANGLE:
- priv->overall_angle = g_value_get_float (value);
- break;
- case PROP_TOMO_ANGLE:
- priv->tomo_angle = g_value_get_float (value);
- break;
- case PROP_LAMINO_ANGLE:
- priv->lamino_angle = g_value_get_float (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
- }
- static void
- ufo_anka_backproject_task_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
- {
- UfoAnkaBackprojectTaskPrivate *priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (object);
- switch (property_id) {
- case PROP_X_REGION:
- g_value_set_boxed (value, priv->x_region);
- break;
- case PROP_Y_REGION:
- g_value_set_boxed (value, priv->y_region);
- break;
- case PROP_Z_REGION:
- g_value_set_boxed (value, priv->z_region);
- break;
- case PROP_PROJECTION_OFFSET:
- g_value_set_boxed (value, priv->projection_offset);
- break;
- case PROP_CENTER:
- g_value_set_boxed (value, priv->center);
- break;
- case PROP_NUM_PROJECTIONS:
- g_value_set_uint (value, priv->num_projections);
- break;
- case PROP_OVERALL_ANGLE:
- g_value_set_float (value, priv->overall_angle);
- break;
- case PROP_TOMO_ANGLE:
- g_value_set_float (value, priv->tomo_angle);
- break;
- case PROP_LAMINO_ANGLE:
- g_value_set_float (value, priv->lamino_angle);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
- }
- static void
- ufo_anka_backproject_task_class_init (UfoAnkaBackprojectTaskClass *klass)
- {
- GObjectClass *oclass;
- UfoNodeClass *node_class;
-
- oclass = G_OBJECT_CLASS (klass);
- node_class = UFO_NODE_CLASS (klass);
- oclass->finalize = ufo_anka_backproject_task_finalize;
- oclass->set_property = ufo_anka_backproject_task_set_property;
- oclass->get_property = ufo_anka_backproject_task_get_property;
- GParamSpec *region_vals = g_param_spec_int ("region_values",
- "Region values",
- "Elements in regions",
- G_MININT,
- G_MAXINT,
- (gint) 0,
- G_PARAM_READWRITE);
- GParamSpec *float_region_vals = g_param_spec_float ("float_region_values",
- "Float Region values",
- "Elements in float regions",
- -G_MAXFLOAT,
- G_MAXFLOAT,
- 0.0f,
- G_PARAM_READWRITE);
- properties[PROP_X_REGION] =
- g_param_spec_value_array ("x-region",
- "X region for reconstruction as (from, to, step)",
- "X region for reconstruction as (from, to, step)",
- region_vals,
- G_PARAM_READWRITE);
- properties[PROP_Y_REGION] =
- g_param_spec_value_array ("y-region",
- "Y region for reconstruction as (from, to, step)",
- "Y region for reconstruction as (from, to, step)",
- region_vals,
- G_PARAM_READWRITE);
- properties[PROP_Z_REGION] =
- g_param_spec_value_array ("z-region",
- "Z region for reconstruction as (from, to, step)",
- "Z region for reconstruction as (from, to, step)",
- region_vals,
- G_PARAM_READWRITE);
- properties[PROP_PROJECTION_OFFSET] =
- g_param_spec_value_array ("projection-offset",
- "Offset to projection data as (x, y)",
- "Offset to projection data as (x, y) for the case input data \
- is cropped to the necessary range of interest",
- region_vals,
- G_PARAM_READWRITE);
- properties[PROP_CENTER] =
- g_param_spec_value_array ("center",
- "Center of the volume with respect to projections (x, y)",
- "Center of the volume with respect to projections (x, y), (rotation axes)",
- float_region_vals,
- G_PARAM_READWRITE);
- properties[PROP_OVERALL_ANGLE] =
- g_param_spec_float ("overall-angle",
- "Angle covered by all projections",
- "Angle covered by all projections (can be negative for negative steps "
- "in case only num-projections is specified",
- -G_MAXFLOAT,
- G_MAXFLOAT,
- G_PI,
- G_PARAM_READWRITE);
- properties[PROP_NUM_PROJECTIONS] =
- g_param_spec_uint ("num-projections",
- "Number of projections",
- "Number of projections",
- 0,
- 16384,
- 0,
- G_PARAM_READWRITE);
- properties[PROP_TOMO_ANGLE] =
- g_param_spec_float ("tomo-angle",
- "Tomographic rotation angle in radians",
- "Tomographic rotation angle in radians (used for acquiring projections)",
- -G_MAXFLOAT,
- G_MAXFLOAT,
- 0.0f,
- G_PARAM_READWRITE);
- properties[PROP_LAMINO_ANGLE] =
- g_param_spec_float ("lamino-angle",
- "Absolute laminogrpahic angle in radians",
- "Absolute laminogrpahic angle in radians determining the sample tilt",
- 0.0f,
- (float) G_PI / 2,
- 0.0f,
- G_PARAM_READWRITE);
- for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++)
- g_object_class_install_property (oclass, i, properties[i]);
- node_class->equal = ufo_anka_backproject_task_equal_real;
- g_type_class_add_private (klass, sizeof(UfoAnkaBackprojectTaskPrivate));
- }
- static void
- ufo_anka_backproject_task_init(UfoAnkaBackprojectTask *self)
- {
- UfoAnkaBackprojectTaskPrivate *priv;
- self->priv = priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE(self);
- guint i;
- GValue int_zero = G_VALUE_INIT;
- GValue float_zero = G_VALUE_INIT;
- g_value_init (&int_zero, G_TYPE_INT);
- g_value_init (&float_zero, G_TYPE_FLOAT);
- g_value_set_int (&int_zero, 0);
- g_value_set_float (&float_zero, 0.0f);
- self->priv->x_region = g_value_array_new (3);
- self->priv->y_region = g_value_array_new (3);
- self->priv->z_region = g_value_array_new (3);
- self->priv->projection_offset = g_value_array_new (2);
- self->priv->center = g_value_array_new (2);
- for (i = 0; i < 3; i++) {
- g_value_array_insert (self->priv->x_region, i, &int_zero);
- g_value_array_insert (self->priv->y_region, i, &int_zero);
- g_value_array_insert (self->priv->z_region, i, &int_zero);
- if (i < 2) {
- g_value_array_insert (self->priv->projection_offset, i, &int_zero);
- g_value_array_insert (self->priv->center, i, &float_zero);
- }
- }
- self->priv->num_projections = 0;
- self->priv->overall_angle = G_PI;
- self->priv->tomo_angle = -G_MAXFLOAT;
- self->priv->lamino_angle = 0.0f;
- self->priv->count = 0;
- self->priv->generated = FALSE;
- }
|