Browse Source

Support different parameters to vary along z-axis

namely z, x-center, lamino-angle.
Tomas Farago 9 years ago
parent
commit
871a191d81
1 changed files with 130 additions and 30 deletions
  1. 130 30
      src/ufo-anka-backproject-task.c

+ 130 - 30
src/ufo-anka-backproject-task.c

@@ -48,6 +48,12 @@
  *
  */
 
+typedef enum {
+    PARAM_Z,
+    PARAM_CENTER,
+    PARAM_LAMINO
+} Param;
+
 struct _UfoAnkaBackprojectTaskPrivate {
     /* private */
     gboolean generated;
@@ -68,7 +74,7 @@ struct _UfoAnkaBackprojectTaskPrivate {
     /* properties */
     GValueArray *x_region;
     GValueArray *y_region;
-    GValueArray *z_region;
+    GValueArray *region;
     GValueArray *center;
     GValueArray *projection_offset;
     float sines[BURST], cosines[BURST];
@@ -76,6 +82,8 @@ struct _UfoAnkaBackprojectTaskPrivate {
     gfloat overall_angle;
     gfloat tomo_angle;
     gfloat lamino_angle;
+    gfloat z;
+    Param parameter;
 };
 
 static void ufo_task_interface_init (UfoTaskIface *iface);
@@ -90,13 +98,15 @@ enum {
     PROP_0,
     PROP_X_REGION,
     PROP_Y_REGION,
-    PROP_Z_REGION,
+    PROP_Z,
+    PROP_REGION,
     PROP_PROJECTION_OFFSET,
     PROP_CENTER,
     PROP_NUM_PROJECTIONS,
     PROP_OVERALL_ANGLE,
     PROP_TOMO_ANGLE,
     PROP_LAMINO_ANGLE,
+    PROP_PARAMETER,
     N_PROPERTIES
 };
 
@@ -150,7 +160,7 @@ determine_x_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_e
  */
 static void
 determine_y_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_extrema,
-                     GValueArray *z_extrema, gfloat tomo_angle, gfloat lamino_angle,
+                     gfloat z_extrema[2], gfloat tomo_angle, gfloat lamino_angle,
                      gfloat y_center)
 {
     gfloat sin_tomo, cos_tomo, sin_lamino, cos_lamino;
@@ -174,8 +184,8 @@ determine_y_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_e
 
     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;
+    extrema[0] = extrema[0] * cos_lamino + z_extrema[0] * sin_lamino + y_center;
+    extrema[1] = extrema[1] * cos_lamino + z_extrema[1] * sin_lamino + y_center + 1;
 }
 
 /**
@@ -239,7 +249,7 @@ determine_x_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extre
  * [0, projection height).
  */
 static void
-determine_y_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, GValueArray *z_extrema,
+determine_y_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat z_extrema[2],
                     gfloat tomo_angle, gfloat lamino_angle, gfloat y_center, gint height)
 {
     gfloat extrema[2];
@@ -340,7 +350,7 @@ ufo_anka_backproject_task_setup (UfoTask *task,
     UfoAnkaBackprojectTaskPrivate *priv;
     cl_int cl_error;
     gint i;
-    gchar vector_kernel_name[30];
+    gchar vector_kernel_name[30], *kernel_filename;
 
     if (!g_sprintf (vector_kernel_name, "backproject_burst_%d", BURST)) {
         g_warning ("Error making burst kernel name");
@@ -348,9 +358,23 @@ ufo_anka_backproject_task_setup (UfoTask *task,
 
     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",
+    switch (priv->parameter) {
+        case PARAM_Z:
+            kernel_filename = g_strdup ("z_kernel.cl");
+            break;
+        case PARAM_CENTER:
+            kernel_filename = g_strdup ("center_kernel.cl");
+            break;
+        case PARAM_LAMINO:
+            kernel_filename = g_strdup ("lamino_kernel.cl");
+            break;
+        default:
+            g_warning ("Unkown varying parameter");
+            break;
+    }
+    priv->vector_kernel = ufo_resources_get_kernel (resources, kernel_filename,
                                                     vector_kernel_name, error);
-    priv->scalar_kernel = ufo_resources_get_kernel (resources, "ankabackprojectburst.cl",
+    priv->scalar_kernel = ufo_resources_get_kernel (resources, kernel_filename,
                                                     "backproject_burst_1", error);
     priv->sampler = clCreateSampler (priv->context,
                                      (cl_bool) FALSE,
@@ -379,6 +403,8 @@ ufo_anka_backproject_task_setup (UfoTask *task,
         case 16: priv->table_size = sizeof (cl_float16); break;
         default: g_warning ("Unsupported vector size"); break;
     }
+
+    g_free (kernel_filename);
 }
 
 static void
@@ -387,17 +413,24 @@ ufo_anka_backproject_task_get_requisition (UfoTask *task,
                                            UfoRequisition *requisition)
 {
     UfoAnkaBackprojectTaskPrivate *priv;
+    gfloat start, stop, step;
 
     priv = UFO_ANKA_BACKPROJECT_TASK_GET_PRIVATE (task);
+    start = EXTRACT_FLOAT (priv->region, 0);
+    stop = EXTRACT_FLOAT (priv->region, 1);
+    step = EXTRACT_FLOAT (priv->region, 2);
 
     if (!priv->num_projections) {
         g_warning ("Number of projections has not been set");
     }
+    if (step == 0.0f) {
+        g_warning ("Step in region is 0");
+    }
 
     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);
+    requisition->dims[2] = (gint) ceil ((stop - start) / step);
 }
 
 static guint
@@ -446,7 +479,7 @@ ufo_anka_backproject_task_process (UfoTask *task,
     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;
+    gfloat x_region[2], y_region[2], z_region[2], x_center[2], z_ends[2], lamino_angles[2], y_center, sin_lamino, cos_lamino;
     gint x_copy_region[2], y_copy_region[2];
     cl_kernel kernel;
     cl_command_queue cmd_queue;
@@ -487,20 +520,38 @@ ufo_anka_backproject_task_process (UfoTask *task,
     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);
+    if (priv->parameter == PARAM_Z) {
+        z_ends[0] = z_region[0] = EXTRACT_FLOAT (priv->region, 0);
+        z_region[1] = EXTRACT_FLOAT (priv->region, 2);
+        z_ends[1] = EXTRACT_FLOAT (priv->region, 1);
+    } else {
+        z_ends[0] = priv->z;
+        z_ends[1] = priv->z + 1.0f;
+    }
+    if (priv->parameter == PARAM_CENTER) {
+        x_center[0] = EXTRACT_FLOAT (priv->region, 0) - EXTRACT_INT (priv->projection_offset, 0);
+        x_center[1] = EXTRACT_FLOAT (priv->region, 2);
+    } else {
+        x_center[0] = x_center[1] = EXTRACT_FLOAT (priv->center, 0) - EXTRACT_INT (priv->projection_offset, 0);
+    }
+    y_center = EXTRACT_FLOAT (priv->center, 1) - EXTRACT_INT (priv->projection_offset, 1);
+    if (priv->parameter == PARAM_LAMINO) {
+        lamino_angles[0] = EXTRACT_FLOAT (priv->region, 0);
+        lamino_angles[1] = EXTRACT_FLOAT (priv->region, 2);
+    } else {
+        lamino_angles[0] = lamino_angles[1] = priv->lamino_angle;
+    }
     sin_lamino = sinf (priv->lamino_angle);
     cos_lamino = cosf (priv->lamino_angle);
     scalar = priv->count >= priv->num_projections / BURST * BURST ? 1 : 0;
 
     /* If COPY_PROJECTION_REGION is True we copy only the part necessary  */
     /* for a given tomographic and laminographic angle */
-    if (COPY_PROJECTION_REGION) {
+    /* TODO: Extend the region determination to be able to handle PARAM_LAMINO */
+    if (COPY_PROJECTION_REGION && priv->parameter != PARAM_LAMINO) {
         determine_x_region (x_copy_region, priv->x_region, priv->y_region, tomo_angle,
                             EXTRACT_FLOAT (priv->center, 0), in_req.dims[0]);
-        determine_y_region (y_copy_region, priv->x_region, priv->y_region, priv->z_region,
+        determine_y_region (y_copy_region, priv->x_region, priv->y_region, z_ends,
                             tomo_angle, priv->lamino_angle, EXTRACT_FLOAT (priv->center, 1),
                             in_req.dims[1]);
         origin[0] = x_copy_region[0];
@@ -559,10 +610,12 @@ ufo_anka_backproject_task_process (UfoTask *task,
         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_center));
+        UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (kernel, i++, sizeof (cl_float), (cl_float *) &y_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_float2), lamino_angles));
         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));
@@ -605,7 +658,7 @@ ufo_anka_backproject_task_finalize (GObject *object)
     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->region);
     g_value_array_free (priv->projection_offset);
     g_value_array_free (priv->center);
 
@@ -667,9 +720,13 @@ ufo_anka_backproject_task_set_property (GObject *object,
             array = (GValueArray *) g_value_get_boxed (value);
             set_region (array, &priv->y_region);
             break;
-        case PROP_Z_REGION:
+        case PROP_Z:
+            priv->z = g_value_get_float (value);
+            break;
+        case PROP_REGION:
             array = (GValueArray *) g_value_get_boxed (value);
-            set_region (array, &priv->z_region);
+            g_value_array_free (priv->region);
+            priv->region = g_value_array_copy (array);
             break;
         case PROP_PROJECTION_OFFSET:
             array = (GValueArray *) g_value_get_boxed (value);
@@ -693,6 +750,15 @@ ufo_anka_backproject_task_set_property (GObject *object,
         case PROP_LAMINO_ANGLE:
             priv->lamino_angle = g_value_get_float (value);
             break;
+        case PROP_PARAMETER:
+            if (!g_strcmp0 (g_value_get_string (value), "z")) {
+                priv->parameter = PARAM_Z;
+            } else if (!g_strcmp0 (g_value_get_string (value), "x-center")) {
+                priv->parameter = PARAM_CENTER;
+            } else if (!g_strcmp0 (g_value_get_string (value), "lamino-angle")) {
+                priv->parameter = PARAM_LAMINO;
+            }
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
             break;
@@ -714,8 +780,11 @@ ufo_anka_backproject_task_get_property (GObject *object,
         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);
+        case PROP_Z:
+            g_value_set_float (value, priv->z);
+            break;
+        case PROP_REGION:
+            g_value_set_boxed (value, priv->region);
             break;
         case PROP_PROJECTION_OFFSET:
             g_value_set_boxed (value, priv->projection_offset);
@@ -735,6 +804,19 @@ ufo_anka_backproject_task_get_property (GObject *object,
         case PROP_LAMINO_ANGLE:
             g_value_set_float (value, priv->lamino_angle);
             break;
+        case PROP_PARAMETER:
+            switch (priv->parameter) {
+                case PARAM_Z:
+                    g_value_set_string (value, "z");
+                    break;
+                case PARAM_CENTER:
+                    g_value_set_string (value, "x-center");
+                    break;
+                case PARAM_LAMINO:
+                    g_value_set_string (value, "lamino-angle");
+                    break;
+            }
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
             break;
@@ -785,11 +867,20 @@ ufo_anka_backproject_task_class_init (UfoAnkaBackprojectTaskClass *klass)
                                   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,
+    properties[PROP_Z] =
+        g_param_spec_float ("z",
+                            "Z coordinate of the reconstructed slice",
+                            "Z coordinate of the reconstructed slice",
+                            -G_MAXFLOAT,
+                            G_MAXFLOAT,
+                            0.0f,
+                            G_PARAM_READWRITE);
+
+    properties[PROP_REGION] =
+        g_param_spec_value_array ("region",
+                                  "Region for the parameter along z-axis as (from, to, step)",
+                                  "Region for the parameter along z-axis as (from, to, step)",
+                                  float_region_vals,
                                   G_PARAM_READWRITE);
 
     properties[PROP_PROJECTION_OFFSET] =
@@ -844,6 +935,13 @@ ufo_anka_backproject_task_class_init (UfoAnkaBackprojectTaskClass *klass)
                             0.0f,
                             G_PARAM_READWRITE);
 
+    properties[PROP_PARAMETER] =
+        g_param_spec_string ("parameter",
+                             "Which paramter will be varied along the z-axis",
+                             "Which paramter will be varied along the z-axis, from \"z\", \"x-center\", \"lamino-angle\"",
+                             "z",
+                             G_PARAM_READWRITE);
+
     for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++)
         g_object_class_install_property (oclass, i, properties[i]);
 
@@ -867,14 +965,15 @@ ufo_anka_backproject_task_init(UfoAnkaBackprojectTask *self)
     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->region = g_value_array_new (3);
+    self->priv->z = 0.0f;
     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);
+        g_value_array_insert (self->priv->region, i, &float_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);
@@ -885,6 +984,7 @@ ufo_anka_backproject_task_init(UfoAnkaBackprojectTask *self)
     self->priv->overall_angle = G_PI;
     self->priv->tomo_angle = -G_MAXFLOAT;
     self->priv->lamino_angle = 0.0f;
+    self->priv->parameter = PARAM_Z;
     self->priv->count = 0;
     self->priv->generated = FALSE;
 }