riCOM_cpp
This repository contains the C++ implementation of the riCOM (Real Time Centre Of Mass) algorithm for 4D Scanning electron microscopy.
Ricom.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2021 Thomas Friedrich, Chu-Ping Yu,
2  * University of Antwerp - All Rights Reserved.
3  * You may use, distribute and modify
4  * this code under the terms of the GPL3 license.
5  * You should have received a copy of the GPL3 license with
6  * this file. If not, please visit:
7  * https://www.gnu.org/licenses/gpl-3.0.en.html
8  *
9  * Authors:
10  * Thomas Friedrich <thomas.friedrich@uantwerpen.be>
11  * Chu-Ping Yu <chu-ping.yu@uantwerpen.be>
12  */
13 
14 #include "Ricom.h"
15 
17 // RICOM Kernel class method implementations //
19 
20 // Compute the kernel
22 {
23  float rot_rad = M_PI * rotation / 180;
24  float cos_rot = cos(rot_rad);
25  float sin_rot = sin(rot_rad);
26 
27  k_width_sym = kernel_size * 2 + 1;
29  kernel_x.assign(k_area, 0);
30  kernel_y.assign(k_area, 0);
31 
32  for (int iy = 0; iy < k_width_sym; iy++)
33  {
34  int iy_e = (iy + 1) * k_width_sym - 1;
35  for (int ix = 0; ix < k_width_sym; ix++)
36  {
37  int ix_s = ix - kernel_size;
38  int iy_s = iy - kernel_size;
39  float d = ix_s * ix_s + iy_s * iy_s;
40  int ix_e = k_area - iy_e + ix - 1;
41 
42  if (d > 0)
43  {
44  float ix_sd = (ix_s / d);
45  float iy_sd = (iy_s / d);
46  kernel_x[ix_e] = cos_rot * ix_sd - sin_rot * iy_sd;
47  kernel_y[ix_e] = sin_rot * ix_sd + cos_rot * iy_sd;
48  }
49  else
50  {
51  kernel_y[ix_e] = 0;
52  kernel_x[ix_e] = 0;
53  }
54  }
55  }
56 
57  // Add filter
58  if (b_filter)
59  {
62  }
63 }
64 
65 // Compute the filter
67 {
68  kernel_filter.assign(k_area, 0);
69  float lb = pow(kernel_filter_frequency[0], 2);
70  float ub = pow(kernel_filter_frequency[1], 2);
71 
72  for (int iy = 0; iy < k_width_sym; iy++)
73  {
74  for (int ix = 0; ix < k_width_sym; ix++)
75  {
76  float dist = pow(ix - kernel_size, 2) + pow(iy - kernel_size, 2);
77  int ic = iy * k_width_sym + ix;
78  if (dist <= ub && dist > lb)
79  {
80  kernel_filter[ic] = 1;
81  }
82  }
83  }
84 }
85 
86 // Applies the filter to the kernel
88 {
89  FFT2D fft2d(k_width_sym, k_width_sym);
90  std::vector<std::complex<float>> x2c = FFT2D::r2c(kernel_x);
91  std::vector<std::complex<float>> y2c = FFT2D::r2c(kernel_y);
92  fft2d.fft(x2c, x2c);
93  fft2d.fft(y2c, y2c);
94  for (int id = 0; id < k_area; id++)
95  {
96  if (kernel_filter[id] == 0.0f)
97  {
98  x2c[id] = {0, 0};
99  y2c[id] = {0, 0};
100  }
101  }
102  fft2d.ifft(x2c, x2c);
103  fft2d.ifft(y2c, y2c);
104  for (int id = 0; id < k_area; id++)
105  {
106  kernel_x[id] = x2c[id].real();
107  kernel_y[id] = y2c[id].real();
108  }
109 }
110 
112 {
113  f_approx.resize(nx_im);
114  float f_max = 0;
115  float k = kernel_size * 2;
116  for (size_t i = 0; i < nx_im; i++)
117  {
118  float x = 2 * i * M_PI;
119  f_approx[i] = (nx_im / x) * (1 - cos(k / 2 * (x / nx_im)));
120  if (f_approx[i] > f_max)
121  {
122  f_max = f_approx[i];
123  }
124  }
125  std::for_each(f_approx.begin(), f_approx.end(), [f_max](float &x)
126  { x /= f_max; });
127 }
128 
130 {
131  // Creating SDL Surface (holding the ricom image in CPU memory)
132  srf_kx = SDL_CreateRGBSurface(0, k_width_sym, k_width_sym, 32, 0, 0, 0, 0);
133  if (srf_kx == NULL)
134  {
135  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
136  }
137  srf_ky = SDL_CreateRGBSurface(0, k_width_sym, k_width_sym, 32, 0, 0, 0, 0);
138  if (srf_ky == NULL)
139  {
140  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
141  }
142  // determine location index of value in memory
143  std::pair kx_min_max = std::minmax_element(kernel_x.begin(), kernel_x.end());
144  std::pair ky_min_max = std::minmax_element(kernel_y.begin(), kernel_y.end());
145  // Update pixel at location
146 
147  for (int y = 0; y < k_width_sym; y++)
148  {
149  int ic = y * k_width_sym;
150  for (int x = 0; x < k_width_sym; x++)
151  {
152  float valx = (kernel_x[ic + x] - kx_min_max.first[0]) / (kx_min_max.second[0] - kx_min_max.first[0]);
153  SDL_Utils::draw_pixel(srf_kx, x, y, valx, 5);
154  float valy = (kernel_y[ic + x] - ky_min_max.first[0]) / (ky_min_max.second[0] - ky_min_max.first[0]);
155  SDL_Utils::draw_pixel(srf_ky, x, y, valy, 5);
156  }
157  }
158 }
159 // Computer detector distance map relative to a given centre (offset) for vSTEM
160 void Ricom_detector::compute_detector(int nx_cam, int ny_cam, std::array<float, 2> &offset)
161 {
162 
163  radius2[0] = pow(radius[0], 2);
164  radius2[1] = pow(radius[1], 2);
165  float d2;
166  id_list.clear();
167  id_list.reserve(nx_cam * ny_cam);
168 
169  for (int iy = 0; iy < ny_cam; iy++)
170  {
171  for (int ix = 0; ix < nx_cam; ix++)
172  {
173  d2 = pow((float)ix - offset[0], 2) + pow((float)iy - offset[1], 2);
174  if (d2 > radius2[0] && d2 <= radius2[1])
175  {
176  id_list.push_back(iy * nx_cam + ix);
177  }
178  }
179  }
180 }
181 
182 
184 // SDL plotting //
186 void Ricom::init_surface()
187 {
188  // Creating SDL Surface (holding the ricom image in CPU memory)
189  srf_ricom = SDL_CreateRGBSurface(0, nx, ny, 32, 0, 0, 0, 0);
190  if (srf_ricom == NULL)
191  {
192  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
193  exit(EXIT_FAILURE);
194  }
195  // SDL surface for STEM image
196  srf_stem = SDL_CreateRGBSurface(0, nx, ny, 32, 0, 0, 0, 0);
197  if (srf_stem == NULL)
198  {
199  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
200  exit(EXIT_FAILURE);
201  }
202  // SDL surface for STEM image
203  srf_e_mag = SDL_CreateRGBSurface(0, nx, ny, 32, 0, 0, 0, 0);
204  if (srf_e_mag == NULL)
205  {
206  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
207  exit(EXIT_FAILURE);
208  }
209  // SDL surface for CBED image
210  cbed_log.assign(n_cam * n_cam, 0.0);
211  srf_cbed = SDL_CreateRGBSurface(0, n_cam, n_cam, 32, 0, 0, 0, 0);
212  if (srf_cbed == NULL)
213  {
214  std::cout << "Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
215  exit(EXIT_FAILURE);
216  }
217 }
218 
220 // RICOM class method implementations //
222 Ricom::Ricom() : stem_max(-FLT_MAX), stem_min(FLT_MAX),
223  e_mag_max(-FLT_MAX), e_mag_min(FLT_MAX),
224  ricom_max(-FLT_MAX), ricom_min(FLT_MAX),
225  cbed_log(),
226  ricom_mutex(), stem_mutex(), counter_mutex(), e_field_mutex(),
227  socket(), file_path(""),
228  camera(),
229  mode(0),
230  b_print2file(false),
231  redraw_interval(50),
232  last_y(0),
233  p_prog_mon(nullptr),
234  b_busy(false),
235  update_offset(true),
236  b_ricom(false),
237  b_airpi(false),
238  b_vSTEM(false),
239  b_e_mag(false),
240  b_plot_cbed(true),
241  b_plot2SDL(false), b_recompute_detector(false),
242  b_recompute_kernel(false), detector(),
243  kernel(),
244  offset{128, 128}, com_public{0.0, 0.0},
245  comx_image(), comy_image(),
246  ricom_image(),
247  stem_image(),
248  nx(1024), ny(1024), nxy(0),
249  rep(1), fr_total(0),
250  skip_row(1), skip_img(0),
251  n_threads(1), queue_size(64),
252  fr_freq(0.0), fr_count(0.0), fr_count_total(0.0),
253  rescale_ricom(false), rescale_stem(false),
254  rc_quit(false),
255  srf_ricom(NULL), ricom_cmap(9),
256  srf_stem(NULL), stem_cmap(9),
257  srf_cbed(NULL), cbed_cmap(5),
258  srf_e_mag(NULL), e_mag_cmap(12)
259 {
260  n_threads_max = std::thread::hardware_concurrency();
261 }
262 
264 
265 // Redraws the entire ricom image
267 {
268  std::lock_guard<std::mutex> lock(ricom_mutex);
269  for (int y = 0; y < ny; y++)
270  {
271  for (int x = 0; x < nx; x++)
272  {
273  set_ricom_pixel(x, y);
274  }
275  }
276 }
277 
278 // Redraws the ricom image from line y0 to line ye
279 void Ricom::draw_ricom_image(int y0, int ye)
280 {
281  std::lock_guard<std::mutex> lock(ricom_mutex);
282  if (y0 < (kernel.kernel_size+2)) {
283  ricom_min = 0;
284  ricom_max = 0;
285  }
286 
287  for (int y = y0; y <= ye; y++)
288  {
289  for (int x = 0; x < nx; x++)
290  {
291  set_ricom_pixel(x, y);
292  }
293  }
294 }
295 
296 // set pixel in ricom image srf_ricom at location idx, idy to value corresponding
297 // value in ricom_image array
298 void Ricom::set_ricom_pixel(int idx, int idy)
299 {
300  // determine location index of value in memory
301 
302  int idr = idy * nx + idx;
303  if (ricom_image[idr] < ricom_min) {ricom_min = ricom_image[idr];}
304  if (ricom_image[idr] > ricom_max) {ricom_max = ricom_image[idr];}
305 
306  float val = (ricom_image[idr] - ricom_min) / ((ricom_max - ricom_min));
307 
308  // Update pixel at location
309  SDL_Utils::draw_pixel(srf_ricom, idx, idy, val, ricom_cmap);
310 }
311 
312 // Redraws the entire stem image
314 {
315  std::lock_guard<std::mutex> lock(stem_mutex);
316  for (int y = 0; y < ny; y++)
317  {
318  for (int x = 0; x < nx; x++)
319  {
320  set_stem_pixel(x, y);
321  }
322  }
323 }
324 
325 // Redraws the stem image from line y0 to line ye
326 void Ricom::draw_stem_image(int y0, int ye)
327 {
328  if (y0==0) {
329  stem_min = stem_image[y0*nx];
330  stem_max = stem_image[y0*nx];
331  }
332 
333  std::lock_guard<std::mutex> lock(stem_mutex);
334  for (int y = y0; y <= ye; y++)
335  {
336  for (int x = 0; x < nx; x++)
337  {
338  set_stem_pixel(x, y);
339  }
340  }
341 }
342 
343 void Ricom::draw_e_field_image(int y0, int ye)
344 {
345  std::lock_guard<std::mutex> lock(e_field_mutex);
346  int idr;
347  for (int y = y0; y <= ye; y++)
348  {
349  for (int x = 0; x < nx; x++)
350  {
351  set_e_field_pixel(x, y);
352  idr = y * nx + x;
353  }
354  }
355 }
356 
358 {
359  std::lock_guard<std::mutex> lock(e_field_mutex);
360  for (int y = 0; y < ny; y++)
361  {
362  for (int x = 0; x < nx; x++)
363  {
364  set_e_field_pixel(x, y);
365  }
366  }
367 }
368 
369 // set pixel in stem image srf_stem at location idx, idy to value corresponding
370 // value in stem_image array
371 void Ricom::set_stem_pixel(size_t idx, size_t idy)
372 {
373  // determine location index of value in memory
374  int idr = idy * nx + idx;
375 
376  if (stem_image[idr] < stem_min) {stem_min = stem_image[idr];}
377  if (stem_image[idr] > stem_max) {stem_max = stem_image[idr];}
378 
379  float val = (stem_image[idr] - stem_min) / (stem_max - stem_min);
380 
381  // Update pixel at location
382  SDL_Utils::draw_pixel(srf_stem, idx, idy, val, stem_cmap);
383 }
384 
385 // set pixel in stem image srf_stem at location idx, idy to value corresponding
386 // value in stem_image array
387 void Ricom::set_e_field_pixel(size_t idx, size_t idy)
388 {
389  // determine location index of value in memory
390  int idr = idy * nx + idx;
391  float mag = (abs(e_field_data[idr]) - e_mag_min) / (e_mag_max - e_mag_min);
392  float ang = arg(e_field_data[idr]);
393 
394  // Update pixel at location
395  SDL_Utils::draw_pixel(srf_e_mag, idx, idy, ang, mag, e_mag_cmap);
396 }
397 
398 
399 // Rescales the images according to updated min and max values
400 // and recomputes the Kernel if settings changed
401 inline void Ricom::rescales_recomputes()
402 {
404  {
406  b_recompute_detector = false;
407  }
408  if (b_recompute_kernel)
409  {
411  b_recompute_kernel = false;
412  }
413 
414  if (rescale_ricom)
415  {
416  rescale_ricom = false;
417  };
418  if (b_vSTEM)
419  {
420  if (rescale_stem)
421  {
422  rescale_stem = false;
423  };
424  };
425 
426  if (b_e_mag)
427  {
428  if (rescale_e_mag)
429  {
430  rescale_e_mag = false;
431  };
432  };
433 }
434 
435 // Compute electric field magnitude
436 void Ricom::compute_electric_field(std::array<float, 2> &com_xy, size_t id)
437 {
438  float e_mag = std::hypot(com_xy[0] - offset[0], com_xy[1] - offset[1]);
439  float e_ang = atan2(com_xy[0] - offset[0], com_xy[1] - offset[1]);
440  if (e_mag > e_mag_max)
441  {
442  e_mag_max = e_mag;
443  rescale_e_mag = true;
444  }
445  if (e_mag < e_mag_min)
446  {
447  e_mag_min = e_mag;
448  rescale_e_mag = true;
449  }
450  e_field_data[id] = std::polar(e_mag, e_ang);
451 }
452 
453 template <typename T>
454 void Ricom::update_surfaces(int iy, std::vector<T> &frame)
455 {
456  if (b_plot2SDL)
457  {
458  // draw_ricom_image((std::max)(0, last_y - kernel.kernel_size), (std::min)(iy + kernel.kernel_size, ny - 1));
459  draw_ricom_image((std::max)(0, last_y % ny - kernel.kernel_size - 1), iy);
460  if (b_vSTEM)
461  {
462  draw_stem_image(iy, iy+1);
463  }
464  if (b_e_mag)
465  {
466  draw_e_field_image(iy, iy+1);
467  }
468  }
469 }
470 
472 {
473  // Start Thread Pool
474  BoundedThreadPool pool;
475  if (n_threads > 1)
476  pool.init(n_threads, queue_size);
477 
478  frame_id_plot_cbed[0] = 0;
479  frame_id_plot_cbed[2] = 0;
480 
481  size_t img_num = 0;
482  size_t first_frame = img_num * nxy;
483  size_t end_frame = (img_num + 1) * nxy;
484  size_t fr_total_u = (size_t)fr_total;
485 
487  p_prog_mon = &prog_mon;
488 
489  reinit_vectors_limits();
490 
491  while (processor_line != -1)
492  {
493  line_processor(
494  img_num,
495  first_frame,
496  end_frame,
497  p_prog_mon,
498  fr_total_u,
499  &pool
500  );
501  }
502  p_prog_mon = nullptr;
503 }
504 
505 void Ricom::line_processor(
506  size_t &img_num,
507  size_t &first_frame,
508  size_t &end_frame,
509  ProgressMonitor *prog_mon,
510  size_t &fr_total_u,
511  BoundedThreadPool *pool
512 )
513 {
514  int idxx = 0;
515  // process newly finished lines, if there are any
516  if ((int)(prog_mon->fr_count / nx) < preprocessor_line)
517  {
518  processor_line = (int)(prog_mon->fr_count) / nx;
519  if (processor_line%ny==0)
520  id_image = processor_line / ny % 2;
521  idxx = (int)(prog_mon->fr_count) % nxy;
522  *prog_mon += nx;
523 
524  std::array<float, 2> com_xy = {0.0, 0.0};
525  std::array<float, 2> com_xy_sum = {0.0, 0.0};
526  for (size_t i = 0; i < (size_t)nx; i++)
527  {
528  int idxx_p_i = idxx + i;
529  if ((idxx_p_i >= 0) | (nx > 1))
530  {
531  if (dose_data[id_image][idxx_p_i] == 0)
532  {
533  comx_image[idxx_p_i] = offset[0];
534  comy_image[idxx_p_i] = offset[1];
535  }
536  else
537  {
538  comx_image[idxx_p_i] = sumx_data[id_image][idxx_p_i] / dose_data[id_image][idxx_p_i];
539  comy_image[idxx_p_i] = sumy_data[id_image][idxx_p_i] / dose_data[id_image][idxx_p_i];
540  }
541  com_xy_sum[0] += comx_image[idxx_p_i];
542  com_xy_sum[1] += comy_image[idxx_p_i];
543  }
544  if (b_vSTEM)
545  stem_image[idxx_p_i] = (float)stem_data[id_image][idxx_p_i];
546  if (b_e_mag)
547  {
548  com_xy[0] = comx_image[idxx_p_i];
549  com_xy[1] = comy_image[idxx_p_i];
550  compute_electric_field(com_xy, idxx_p_i);
551  }
552  }
553 
554  if (n_threads > 1)
555  {
556  if (b_ricom)
557  pool->push_task([=]{ icom_group_classical(idxx); });
558  }
559  else
560  {
561  if (b_ricom)
562  icom_group_classical(idxx);
563  }
564  // end of line handler
565  int update_line = idxx / nx - kernel.kernel_size*2;
566  if ((prog_mon->report_set) && (update_line)>0)
567  {
568  fr_freq = prog_mon->fr_freq;
569  rescales_recomputes();
570  for (int i = 0; i < 2; i++)
571  {
572  com_public[i] = com_xy_sum[i] / nx;
573  com_xy_sum[i] = 0;
574  }
575  prog_mon->reset_flags();
576  }
577  }
578 
579  // end of image handler
580 
581  if (prog_mon->fr_count >= end_frame)
582 
583  {
584  if (b_continuous) {
585  prog_mon->fr_total += nxy;
586  fr_total_u += nxy;
587  }
588  if (prog_mon->fr_count != fr_total_u)
589  {
590  img_num++;
591  first_frame = img_num * nxy;
592  end_frame = (img_num + 1) * nxy;
593  }
594  if (update_offset)
595  {
596  offset[0] = com_public[0];
597  offset[1] = com_public[1];
598  }
599  }
600 
601  // end of recon handler
602  if (((prog_mon->fr_count >= fr_total_u) && (!b_continuous)) || rc_quit)
603  {
604  pool->wait_for_completion();
605  p_prog_mon = nullptr;
606  b_cumulative = false;
607  b_continuous = false;
608  processor_line = -1;
609  }
610 }
611 
612 
613 
614 void Ricom::icom_group_classical(int idxx)
615 {
616  int idk;
617  int idc;
618  int id;
619  int idr_x;
620  int idr_delay;
621  int k_bias = kernel.k_width_sym * (kernel.kernel_size + 1);
622 
623  if (((idxx / nx - 2*kernel.kernel_size) >= 0))
624  {
625  for (int i_line = 0, idr_delay = idxx - kernel.kernel_size * nx;
626  i_line < nx;
627  i_line++, idr_delay++)
628  { ricom_image[idr_delay]=0; }
629 
630 
631  for (int iy = -kernel.kernel_size; iy <= kernel.kernel_size; iy++)
632  {
633  for (int i_line = 0, idr_delay = idxx - kernel.kernel_size * nx;
634  i_line < nx;
635  i_line++, idr_delay++)
636  {
637  idc = idr_delay + iy * nx;
638  idr_x = idr_delay % nx;
639  idk = (kernel.kernel_size + iy) * kernel.k_width_sym;
640  for (int ix = -kernel.kernel_size; ix <= kernel.kernel_size; ix++)
641  {
642  if (((idr_x + ix) >= 0) & ((idr_x + ix) < nx))
643  {
644  // ricom_image[idr] += ((comx_image[idc + ix] - offset[0]) * -kernel.kernel_x[idk] +
645  // (comy_image[idc + ix] - offset[1]) * -kernel.kernel_y[idk]);
646 
647  ricom_image[idr_delay] += ((comx_image[idc + ix] - offset[0]) * -kernel.kernel_x[idk] +
648  (comy_image[idc + ix] - offset[1]) * -kernel.kernel_y[idk]);
649  }
650  ++idk;
651  }
652  }
653  }
654  last_y = (idxx / nx - kernel.kernel_size);
655  fr_count = idxx;
656  }
657 
658 }
659 
660 // Entrance function for Ricom_reconstructinon
661 void Ricom::run(int mode)
662 {
663  this->mode = mode;
664  reset();
665  b_busy = true;
666 
667  // Run camera dependent pipeline
668  switch (camera)
669  {
670  // Merlin not implemented
671  case RICOM::ADVAPIX:
672  {
673  using namespace ADVAPIX_ADDITIONAL;
674  ADVAPIX<EVENT, BUFFER_SIZE, N_BUFFER> cam(
675  nx,
676  ny,
677  n_cam,
678  dt,
679  b_vSTEM,
680  b_ricom,
681  b_e_mag,
682  b_airpi,
683  &b_cumulative,
684  &detector.radius2,
685  &offset,
686  &dose_data,
687  &sumx_data,
688  &sumy_data,
689  &stem_data,
690  &frame,
693  mode,
694  file_path,
695  &socket
696  );
697  cam.run();
698  process_data();
699  cam.terminate();
700  break;
701  }
702  case RICOM::CHEETAH:
703  {
704  using namespace CHEETAH_ADDITIONAL;
705  CHEETAH<EVENT, BUFFER_SIZE, N_BUFFER> cam(
706  nx,
707  ny,
708  n_cam,
709  dt,
710  b_vSTEM,
711  b_ricom,
712  b_e_mag,
713  b_airpi,
714  &b_cumulative,
715  &detector.radius2,
716  &offset,
717  &dose_data,
718  &sumx_data,
719  &sumy_data,
720  &stem_data,
721  &frame,
724  mode,
725  file_path,
726  &socket
727  );
728  cam.run();
729  process_data();
730  cam.terminate();
731  break;
732  }
733  }
734 
735 
736  // std::this_thread::sleep_for(std::chrono::milliseconds(10*1000));
737 
738 
739  // close the reading and preprocess threads ??
740 
741  b_busy = false;
742  std::cout << std::endl
743  << "Reconstruction finished successfully." << std::endl;
744 }
745 
746 // Helper functions
747 void Ricom::reset_limits()
748 {
749  // ricom_max = -FLT_MAX;
750  // ricom_min = FLT_MAX;
751  ricom_max = 0;
752  ricom_min = 0;
753  stem_max = -FLT_MAX;
754  stem_min = FLT_MAX;
755 }
756 
757 void Ricom::reinit_vectors_limits()
758 {
759  std::fill(ricom_image.begin(), ricom_image.end(), 0);
760  std::fill(stem_image.begin(), stem_image.end(), 0);
761  std::fill(comx_image.begin(), comx_image.end(), 0);
762  std::fill(comy_image.begin(), comy_image.end(), 0);
763  last_y = 0;
764  reset_limits();
765 }
766 
768 {
769  rc_quit = false;
770  fr_freq = 0;
771  reinit_vectors_limits();
772 
773  // Initializations
774  nxy = nx * ny;
775  id_image = 0;
776  fr_total = nxy * rep;
777  fr_count = 0;
778  init_surface();
779 
780  // Imaging tools
781  switch (camera)
782  {
783  case RICOM::ADVAPIX:
784  {
785  n_cam = 256;
786  break;
787  }
788  case RICOM::CHEETAH:
789  {
790  n_cam = 512;
791  break;
792  }
793  }
794  // offset[0] = n_cam / 2;
795  // offset[1] = n_cam / 2;
798 
799  // Allocate memory for image arrays
800  stem_image.assign(nxy, 0);
801  ricom_image.assign(nxy, 0);
802  comx_image.assign(nxy, 0);
803  comy_image.assign(nxy, 0);
804  for (int i=0; i<2; i++)
805  {
806  dose_data[i].assign(nxy, 0);
807  sumx_data[i].assign(nxy, 0);
808  sumy_data[i].assign(nxy, 0);
809  stem_data[i].assign(nxy, 0);
810  }
811  frame.assign(n_cam * n_cam, 0);
812  airpi_image.assign(nxy, 0); // not correct, airpi_image size will be larger due to super resolution
813 
814  // Data Processing Progress
815  processor_line = 0;
816  preprocessor_line = 0;
817 
818 }
void init(int n_threads, int limit)
void push_task(const T &task)
std::atomic< bool > report_set
std::atomic< size_t > fr_count
std::array< float, 2 > radius2
Definition: Ricom.h:132
std::array< float, 2 > radius
Definition: Ricom.h:131
std::vector< int > id_list
Definition: Ricom.h:133
void compute_detector(int nx_cam, int ny_cam, std::array< float, 2 > &offset)
Definition: Ricom.cpp:160
int k_area
Definition: Ricom.h:63
void include_filter()
Definition: Ricom.cpp:87
std::vector< float > kernel_x
Definition: Ricom.h:65
SDL_Surface * srf_kx
Definition: Ricom.h:69
void compute_kernel()
Definition: Ricom.cpp:21
std::vector< float > kernel_y
Definition: Ricom.h:66
int k_width_sym
Definition: Ricom.h:62
void draw_surfaces()
Definition: Ricom.cpp:129
bool b_filter
Definition: Ricom.h:60
std::vector< float > f_approx
Definition: Ricom.h:68
void approximate_frequencies(size_t n_im)
Definition: Ricom.cpp:111
float rotation
Definition: Ricom.h:64
SDL_Surface * srf_ky
Definition: Ricom.h:70
std::array< int, 2 > kernel_filter_frequency
Definition: Ricom.h:61
std::vector< float > kernel_filter
Definition: Ricom.h:67
void compute_filter()
Definition: Ricom.cpp:66
int kernel_size
Definition: Ricom.h:59
std::vector< float > stem_image
Definition: Ricom.h:248
std::vector< size_t > frame
Definition: Ricom.h:254
std::vector< float > comy_image
Definition: Ricom.h:246
void run(int mode)
Definition: Ricom.cpp:661
std::vector< size_t > sumy_data[2]
Definition: Ricom.h:252
std::array< float, 2 > com_public
Definition: Ricom.h:244
void process_data()
Definition: Ricom.cpp:471
SocketConnector socket
Definition: Ricom.h:220
int nxy
Definition: Ricom.h:264
int redraw_interval
Definition: Ricom.h:223
bool b_busy
Definition: Ricom.h:226
int mode
Definition: Ricom.h:258
bool b_recompute_detector
Definition: Ricom.h:239
int e_mag_cmap
Definition: Ricom.h:294
int n_threads
Definition: Ricom.h:276
int processor_line
Definition: Ricom.h:271
void draw_stem_image()
Definition: Ricom.cpp:313
void draw_e_field_image()
Definition: Ricom.cpp:357
int rep
Definition: Ricom.h:267
bool update_offset
Definition: Ricom.h:227
bool b_plot2SDL
Definition: Ricom.h:238
bool b_airpi
Definition: Ricom.h:236
SDL_Surface * srf_e_mag
Definition: Ricom.h:293
int id_image
Definition: Ricom.h:273
std::atomic< bool > rescale_ricom
Definition: Ricom.h:282
int n_threads_max
Definition: Ricom.h:277
std::vector< float > airpi_image
Definition: Ricom.h:249
float fr_count
Definition: Ricom.h:280
std::vector< float > comx_image
Definition: Ricom.h:245
std::vector< std::complex< float > > e_field_data
Definition: Ricom.h:255
std::string file_path
Definition: Ricom.h:221
int preprocessor_line
Definition: Ricom.h:272
void draw_ricom_image()
Definition: Ricom.cpp:266
int nx
Definition: Ricom.h:262
RICOM::cameras camera
Definition: Ricom.h:259
Ricom_detector detector
Definition: Ricom.h:241
bool rc_quit
Definition: Ricom.h:285
int queue_size
Definition: Ricom.h:278
std::vector< size_t > sumx_data[2]
Definition: Ricom.h:251
bool b_e_mag
Definition: Ricom.h:234
std::vector< size_t > stem_data[2]
Definition: Ricom.h:253
SDL_Surface * srf_ricom
Definition: Ricom.h:287
SDL_Surface * srf_cbed
Definition: Ricom.h:291
int fr_total
Definition: Ricom.h:268
ProgressMonitor * p_prog_mon
Definition: Ricom.h:225
int ricom_cmap
Definition: Ricom.h:288
void reset()
Definition: Ricom.cpp:767
float fr_freq
Definition: Ricom.h:279
SDL_Surface * srf_stem
Definition: Ricom.h:289
Ricom()
Definition: Ricom.cpp:222
bool b_recompute_kernel
Definition: Ricom.h:240
std::vector< size_t > dose_data[2]
Definition: Ricom.h:250
std::array< std::atomic< size_t >, 3 > frame_id_plot_cbed
Definition: Ricom.h:231
std::vector< float > ricom_image
Definition: Ricom.h:247
bool b_continuous
Definition: Ricom.h:228
std::atomic< int > last_y
Definition: Ricom.h:224
bool b_cumulative
Definition: Ricom.h:229
int n_cam
Definition: Ricom.h:265
std::atomic< bool > rescale_e_mag
Definition: Ricom.h:284
bool b_ricom
Definition: Ricom.h:235
bool b_vSTEM
Definition: Ricom.h:233
int ny
Definition: Ricom.h:263
int dt
Definition: Ricom.h:266
~Ricom()
Definition: Ricom.cpp:263
bool b_print2file
Definition: Ricom.h:222
std::array< float, 2 > offset
Definition: Ricom.h:243
std::atomic< bool > rescale_stem
Definition: Ricom.h:283
int stem_cmap
Definition: Ricom.h:290
Ricom_kernel kernel
Definition: Ricom.h:242
@ ADVAPIX
Definition: Ricom.h:148
@ CHEETAH
Definition: Ricom.h:149
void draw_pixel(SDL_Surface *surface, int x, int y, float val, int col_map)
Definition: GuiUtils.cpp:97