lamino.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #include <stdlib.h>
  2. #include <ufo/ufo.h>
  3. typedef struct {
  4. gchar *radios;
  5. gchar *darks;
  6. gchar *flats;
  7. gchar *output;
  8. gint width;
  9. gint height;
  10. guint num_radios;
  11. guint num_darks;
  12. gdouble theta;
  13. gdouble tau;
  14. gdouble psi;
  15. gdouble px;
  16. gdouble py;
  17. gdouble px_variation;
  18. gdouble v_origin[3];
  19. guint v_size[3];
  20. } Params;
  21. const int COLOR_RED = 31;
  22. const int COLOR_GREEN = 32;
  23. const int COLOR_YELLOW = 33;
  24. static void
  25. check (GError *error)
  26. {
  27. if (error != NULL) {
  28. if (error->message != NULL)
  29. g_printerr ("%s", error->message);
  30. exit (1);
  31. }
  32. }
  33. static UfoTaskNode *
  34. make_task (UfoPluginManager *pm, const gchar *name)
  35. {
  36. GError *error = NULL;
  37. UfoTaskNode *task;
  38. task = ufo_plugin_manager_get_task (pm, name, &error);
  39. check (error);
  40. return task;
  41. }
  42. static guint
  43. next_power_of_two (guint32 x)
  44. {
  45. --x;
  46. x |= x >> 1;
  47. x |= x >> 2;
  48. x |= x >> 4;
  49. x |= x >> 8;
  50. x |= x >> 16;
  51. return x + 1;
  52. }
  53. static void
  54. colored_print (gint color, const gchar *fmt, va_list args)
  55. {
  56. gchar *s;
  57. s = g_strdup_vprintf (fmt, args);
  58. g_print ("%c[%d;%dm%s%c[%dm", 0x1B, 1, color, s, 0x1b, 0);
  59. g_free (s);
  60. }
  61. static void
  62. warn (const gchar *fmt, ...)
  63. {
  64. va_list args;
  65. va_start (args, fmt);
  66. colored_print (COLOR_YELLOW, fmt, args);
  67. va_end (args);
  68. }
  69. static void
  70. err (const gchar *fmt, ...)
  71. {
  72. va_list args;
  73. va_start (args, fmt);
  74. colored_print (COLOR_RED, fmt, args);
  75. va_end (args);
  76. }
  77. static void
  78. info (const gchar *fmt, ...)
  79. {
  80. va_list args;
  81. gchar *s;
  82. va_start (args, fmt);
  83. g_print ("%c[%d;%dm>%c[%dm ", 0x1B, 1, COLOR_GREEN, 0x1b, 0);
  84. s = g_strdup_vprintf (fmt, args);
  85. g_print ("%s", s);
  86. va_end (args);
  87. g_free (s);
  88. }
  89. static void
  90. print_dots (gpointer user)
  91. {
  92. static int n = 0;
  93. if ((n++ % 10) == 0)
  94. g_print (".");
  95. }
  96. static void
  97. run_reconstruction (Params *params)
  98. {
  99. guint xl, xr, yt, yb;
  100. guint padded_width;
  101. guint padded_height;
  102. gdouble theta_rad;
  103. gdouble angle_step;
  104. guint fwidth;
  105. gdouble time = 0.0;
  106. UfoPluginManager *pm = NULL;
  107. UfoTaskGraph *graph = NULL;
  108. UfoBaseScheduler *sched = NULL;
  109. UfoTaskNode *radio_reader = NULL;
  110. UfoTaskNode *dark_reader = NULL;
  111. UfoTaskNode *flat_reader = NULL;
  112. UfoTaskNode *ffc = NULL;
  113. UfoTaskNode *pad = NULL;
  114. UfoTaskNode *ramp = NULL;
  115. UfoTaskNode *fft1 = NULL;
  116. UfoTaskNode *fft2 = NULL;
  117. UfoTaskNode *ifft = NULL;
  118. UfoTaskNode *conv = NULL;
  119. UfoTaskNode *reco = NULL;
  120. UfoTaskNode *writer = NULL;
  121. GError *error = NULL;
  122. pm = ufo_plugin_manager_new (NULL);
  123. graph = UFO_TASK_GRAPH (ufo_task_graph_new ());
  124. radio_reader = make_task (pm, "reader");
  125. pad = make_task (pm, "padding-2d");
  126. ramp = make_task (pm, "lamino-ramp");
  127. fft1 = make_task (pm, "fft");
  128. fft2 = make_task (pm, "fft");
  129. ifft = make_task (pm, "ifft");
  130. conv = make_task (pm, "lamino-conv");
  131. reco = make_task (pm, "lamino-bp");
  132. writer = make_task (pm, "writer");
  133. g_object_set (radio_reader,
  134. "path", params->radios,
  135. "end", params->num_radios - 1,
  136. NULL);
  137. g_object_set (fft1, "dimensions", 2, NULL);
  138. g_object_set (fft2, "dimensions", 2, NULL);
  139. g_object_set (ifft, "dimensions", 2, NULL);
  140. fwidth = ((guint) params->px) * 2;
  141. padded_width = next_power_of_two (fwidth) * 2;
  142. padded_height = next_power_of_two ((guint32) params->height + 1);
  143. xl = params->px - params->width / 2;
  144. xr = padded_width - params->width - xl;
  145. yt = params->py - params->height / 2;
  146. yb = padded_height - params->height - yt;
  147. angle_step = (G_PI * 2.0) / params->num_radios;
  148. theta_rad = params->theta / 360. * G_PI * 2;
  149. info ("Axis: x=%.1f y=%.1f variation=%.1f\n",
  150. params->px, params->py, params->px_variation);
  151. info ("Lamino: theta=%.3f tau=%.3f step=%.5f fwidth=%d\n",
  152. theta_rad, params->tau, angle_step, fwidth);
  153. info ("Padding: size=[%d %d] (xl=%d xr=%d yt=%d yb=%d)\n",
  154. padded_width, padded_height, xl, xr, yt, yb);
  155. info ("Volume: origin=[%.1f %.1f %.1f] size=[%d %d %d]\n",
  156. params->v_origin[0], params->v_origin[1], params->v_origin[2],
  157. params->v_size[0], params->v_size[1], params->v_size[2]);
  158. g_object_set (pad,
  159. "xl", xl, "xr", xr,
  160. "yt", yt, "yb", yb,
  161. "mode", "brep",
  162. NULL);
  163. g_object_set (ramp,
  164. "width", padded_width,
  165. "height", padded_height,
  166. "theta", theta_rad,
  167. "tau", params->tau,
  168. "fwidth", fwidth,
  169. NULL);
  170. g_object_set (reco,
  171. "angle-step", angle_step,
  172. "theta", theta_rad,
  173. "psi", params->psi,
  174. "proj-ox", params->px,
  175. "proj-oy", params->py,
  176. "proj-ox-variation", params->px_variation,
  177. "vol-ox", params->v_size[0] / 2 + params->v_origin[0],
  178. "vol-oy", params->v_size[1] / 2 + params->v_origin[1],
  179. "vol-oz", params->v_size[2] / 2 + params->v_origin[2],
  180. "vol-sx", params->v_size[0],
  181. "vol-sy", params->v_size[1],
  182. "vol-sz", params->v_size[2],
  183. NULL);
  184. g_object_set (writer,
  185. "filename", params->output,
  186. NULL);
  187. if (params->darks != NULL && params->flats != NULL) {
  188. flat_reader = make_task (pm, "reader");
  189. dark_reader = make_task (pm, "reader");
  190. ffc = make_task (pm, "flat-field-correction");
  191. g_object_set (flat_reader, "path", params->flats, NULL);
  192. g_object_set (dark_reader, "path", params->darks, NULL);
  193. ufo_task_graph_connect_nodes_full (graph, radio_reader, ffc, 0);
  194. ufo_task_graph_connect_nodes_full (graph, dark_reader, ffc, 1);
  195. ufo_task_graph_connect_nodes_full (graph, flat_reader, ffc, 2);
  196. ufo_task_graph_connect_nodes (graph, ffc, pad);
  197. }
  198. else {
  199. warn ("> No flat/dark field correction\n");
  200. ufo_task_graph_connect_nodes (graph, radio_reader, pad);
  201. }
  202. ufo_task_graph_connect_nodes (graph, pad, fft1);
  203. ufo_task_graph_connect_nodes (graph, ramp, fft2);
  204. ufo_task_graph_connect_nodes_full (graph, fft1, conv, 0);
  205. ufo_task_graph_connect_nodes_full (graph, fft2, conv, 1);
  206. ufo_task_graph_connect_nodes (graph, conv, ifft);
  207. ufo_task_graph_connect_nodes (graph, ifft, reco);
  208. ufo_task_graph_connect_nodes (graph, reco, writer);
  209. g_signal_connect (reco, "processed", G_CALLBACK (print_dots), NULL);
  210. sched = UFO_BASE_SCHEDULER (ufo_scheduler_new (NULL, NULL));
  211. ufo_base_scheduler_run (sched, graph, &error);
  212. check (error);
  213. g_object_get (sched, "time", &time, NULL);
  214. g_print ("\n");
  215. info("Finished in %3.3fs\n", time);
  216. g_object_unref (pm);
  217. g_object_unref (graph);
  218. g_object_unref (sched);
  219. g_object_unref (radio_reader);
  220. g_object_unref (pad);
  221. g_object_unref (fft1);
  222. g_object_unref (fft2);
  223. /* g_object_unref (conv); */
  224. g_object_unref (reco);
  225. g_object_unref (writer);
  226. if (params->darks != NULL && params->flats != NULL) {
  227. g_object_unref (ffc);
  228. g_object_unref (flat_reader);
  229. g_object_unref (dark_reader);
  230. }
  231. }
  232. static void
  233. parse_params (Params *params, int argc, char **argv)
  234. {
  235. GOptionContext *context;
  236. GError *error = NULL;
  237. GOptionEntry entries[] = {
  238. { "width", 0, 0, G_OPTION_ARG_INT, &params->width, "Width", "" },
  239. { "height", 0, 0, G_OPTION_ARG_INT, &params->height, "Height", "" },
  240. { "num-radios", 0, 0, G_OPTION_ARG_INT, &params->num_radios, "Number of radios", "" },
  241. { "num-darks", 0, 0, G_OPTION_ARG_INT, &params->num_darks, "Number of darks", "" },
  242. { "radios", 0, 0, G_OPTION_ARG_STRING, &params->radios, "Radios", "" },
  243. { "darks", 0, 0, G_OPTION_ARG_STRING, &params->darks, "Darks", "" },
  244. { "flats", 0, 0, G_OPTION_ARG_STRING, &params->flats, "Flats", "" },
  245. { "output", 0, 0, G_OPTION_ARG_STRING, &params->output, "Output", "" },
  246. { "theta", 0, 0, G_OPTION_ARG_DOUBLE, &params->theta, "Tilt (theta)", "" },
  247. { "tau", 0, 0, G_OPTION_ARG_DOUBLE, &params->tau, "Pixel size (theta)", "" },
  248. { "psi", 0, 0, G_OPTION_ARG_DOUBLE, &params->psi, "Misalignment (psi)", "" },
  249. { "px", 0, 0, G_OPTION_ARG_DOUBLE, &params->px, "X coordinate of axis", "" },
  250. { "py", 0, 0, G_OPTION_ARG_DOUBLE, &params->py, "Y coordinate of axis", "" },
  251. { "px-variation", 0, 0, G_OPTION_ARG_DOUBLE, &params->px_variation, "X axis variation", "" },
  252. { "vx", 0, 0, G_OPTION_ARG_DOUBLE, &params->v_origin[0], "X coordinate of box origin", "" },
  253. { "vy", 0, 0, G_OPTION_ARG_DOUBLE, &params->v_origin[1], "Y coordinate of box origin", "" },
  254. { "vz", 0, 0, G_OPTION_ARG_DOUBLE, &params->v_origin[2], "Z coordinate of box origin", "" },
  255. { "vw", 0, 0, G_OPTION_ARG_INT, &params->v_size[0], "Width of box", "" },
  256. { "vh", 0, 0, G_OPTION_ARG_INT, &params->v_size[1], "Height of box", "" },
  257. { "vd", 0, 0, G_OPTION_ARG_INT, &params->v_size[2], "Depth of box", "" },
  258. { NULL }
  259. };
  260. context = g_option_context_new ("- test tree model performance");
  261. g_option_context_add_main_entries (context, entries, NULL);
  262. if (!g_option_context_parse (context, &argc, &argv, &error)) {
  263. g_print ("option parsing failed: %s\n", error->message);
  264. exit (1);
  265. }
  266. if (params->width == 0 || params->height == 0 || params->num_radios == 0 ||
  267. params->radios == NULL ||
  268. params->theta == G_MAXDOUBLE ||
  269. params->px == G_MAXDOUBLE || params->py == G_MAXDOUBLE) {
  270. err ("Parameters missing.\n\n");
  271. g_print ("%s\n", g_option_context_get_help (context, TRUE, NULL));
  272. exit (1);
  273. }
  274. g_option_context_free (context);
  275. }
  276. int
  277. main (int argc, char **argv)
  278. {
  279. Params params = {
  280. .radios = NULL,
  281. .darks = NULL,
  282. .flats = NULL,
  283. .output = "volume-%i.tif",
  284. .width = 0,
  285. .height = 0,
  286. .num_radios = 0,
  287. .num_darks = 1,
  288. .theta = G_MAXDOUBLE,
  289. .tau = 1.0,
  290. .psi = 0.0,
  291. .px = G_MAXDOUBLE,
  292. .py = G_MAXDOUBLE,
  293. .px_variation = 0.0,
  294. .v_size = {256, 256, 256},
  295. .v_origin = {0.0, 0.0, 0.0},
  296. };
  297. #if !(GLIB_CHECK_VERSION (2, 36, 0))
  298. g_type_init ();
  299. #endif
  300. parse_params (&params, argc, argv);
  301. run_reconstruction (&params);
  302. return 0;
  303. }