riCOM_cpp
This repository contains the C++ implementation of the riCOM (Real Time Centre Of Mass) algorithm for 4D Scanning electron microscopy.
Macros | Functions
RunGUI.cpp File Reference
#include <string>
#include <thread>
#include <iostream>
#include <complex>
#include <map>
#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_opengl3.h"
#include "imgui_stdlib.h"
#include "imgui_internal.h"
#include "imfilebrowser.h"
#include "ini.h"
#include "ImGuiINI.hpp"
#include "Ricom.h"
#include "fonts.h"
#include "GuiUtils.h"
#include "ImGuiImageWindow.h"
Include dependency graph for RunGUI.cpp:

Go to the source code of this file.

Macros

#define MINI_CASE_SENSITIVE
 
#define GENERIC_WINDOW(name)   (generic_windows_f.find(name)->second)
 
#define GENERIC_WINDOW_C(name)   (generic_windows_c.find(name)->second)
 

Functions

template<typename T >
void update_views (std::map< std::string, ImGuiImageWindow< T >> &generic_windows_f, Ricom *ricom, bool b_restarted, bool trigger, bool b_redraw)
 
void bind_tex (SDL_Surface *srf, GLuint tex_id)
 
int run_gui (Ricom *ricom)
 

Macro Definition Documentation

◆ GENERIC_WINDOW

#define GENERIC_WINDOW (   name)    (generic_windows_f.find(name)->second)

Definition at line 55 of file RunGUI.cpp.

◆ GENERIC_WINDOW_C

#define GENERIC_WINDOW_C (   name)    (generic_windows_c.find(name)->second)

Definition at line 56 of file RunGUI.cpp.

◆ MINI_CASE_SENSITIVE

#define MINI_CASE_SENSITIVE

Definition at line 45 of file RunGUI.cpp.

Function Documentation

◆ bind_tex()

void bind_tex ( SDL_Surface *  srf,
GLuint  tex_id 
)
inline

Definition at line 713 of file RunGUI.cpp.

714 {
715  glBindTexture(GL_TEXTURE_2D, (tex_id));
716  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, srf->w, srf->h, 0,
717  GL_BGRA, GL_UNSIGNED_BYTE, srf->pixels);
718 }

◆ run_gui()

int run_gui ( Ricom ricom)

Definition at line 67 of file RunGUI.cpp.

68 {
69  std::thread run_thread;
70  std::thread py_thread;
71  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) // fail here
72  {
73  printf("Error: %s\n", SDL_GetError());
74  return -1;
75  }
76 
77  // Decide GL+GLSL versions
78 #if defined(IMGUI_IMPL_OPENGL_ES2)
79  // GL ES 2.0 + GLSL 100
80  const char *glsl_version = "#version 100";
81  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
82  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
83  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
84  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
85 #elif defined(__APPLE__)
86  // GL 3.2 Core + GLSL 150
87  const char *glsl_version = "#version 150";
88  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
89  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
90  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
91  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
92 #else
93  // GL 3.0 + GLSL 130
94  const char *glsl_version = "#version 130";
95  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
96  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
97  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
98  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
99 #endif
100 
101  // Create window with graphics context
102  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
103  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
104  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
105  SDL_Window *window = SDL_CreateWindow("riCOM", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1200, 800, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
106  if (window == NULL)
107  {
108  std::cout << "Window could not be created! SDL Error: " << SDL_GetError() << std::endl;
109  }
110  SDL_GLContext gl_context = SDL_GL_CreateContext(window);
111  SDL_GL_MakeCurrent(window, gl_context);
112  SDL_GL_SetSwapInterval(1); // Enable vsync
113 
114  // Setup Dear ImGui context
115  IMGUI_CHECKVERSION();
116  ImGui::CreateContext();
117  ImGuiIO &io = ImGui::GetIO();
118  (void)io;
119 
120  mINI::INIFile ini_file("imgui.ini");
121  mINI::INIStructure ini_cfg;
122  ini_file.read(ini_cfg);
123 
124  ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
125  // Setup Platform/Renderer backends
126  ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
127  ImGui_ImplOpenGL3_Init(glsl_version);
128 
129  io.Fonts->AddFontFromMemoryCompressedTTF(KarlaRegular_compressed_data, KarlaRegular_compressed_size, 14.0f);
130  io.Fonts->AddFontFromMemoryCompressedTTF(RobotoMedium_compressed_data, RobotoMedium_compressed_size, 14.0f);
131  io.Fonts->AddFontFromMemoryCompressedTTF(CousineRegular_compressed_data, CousineRegular_compressed_size, 14.0f);
132  io.Fonts->AddFontFromMemoryCompressedTTF(DroidSans_compressed_data, DroidSans_compressed_size, 14.0f);
133  io.Fonts->AddFontFromMemoryCompressedTTF(ProggyClean_compressed_data, ProggyClean_compressed_size, 14.0f);
134  io.Fonts->AddFontFromMemoryCompressedTTF(ProggyTiny_compressed_data, ProggyTiny_compressed_size, 14.0f);
135 
136  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
137  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
138  // Multi-Viewport not yet supported with SDL2
139  // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;// Enable Multi-Viewport / Platform Windows
140 
141  ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
142  ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
143  ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
144  ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
145 
146  ImVec2 menu_bar_size;
147  ImVec2 control_menu_size(200, 800);
148 
149  const size_t n_textures = 16;
150  GLuint uiTextureIDs[n_textures];
151  glGenTextures(n_textures, uiTextureIDs);
152 
153  for (size_t i = 0; i < n_textures; i++)
154  {
155  glBindTexture(GL_TEXTURE_2D, uiTextureIDs[i]);
156  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
157  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
158  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
159  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
160  }
161 
162  // create a file browser instances
163  ImGui::FileBrowser openFileDialog;
164  openFileDialog.SetTitle("Open .mib or .t3p file");
165  openFileDialog.SetTypeFilters({".mib", ".t3p", ".tpx3"});
166  ImGui::FileBrowser saveFileDialog(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir);
167  saveFileDialog.SetTitle("Save image as .png");
168  ImGui::FileBrowser saveDataDialog(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir);
169  saveDataDialog.SetTitle("Save COM data in binary format");
170  std::string filename = "";
171 
172  // Main loop conditional flags
173  bool b_done = false;
174  bool b_acq_open = false;
175  bool b_started = false;
176  bool b_file_selected = false;
177  bool b_restarted = false;
178 
179  // Cheetah Setting (to send to the server)
180  CheetahComm cheetah_comm;
181  ricom->socket.connect_socket();
182 
183 
184  // INI file settings to restore previous session settings
185  // Appearance
186  int font_index = 0;
187  int style_index = 0;
188  ImGuiINI::check_ini_setting(ini_cfg, "Appearance", "CBED Colormap", ricom->cbed_cmap);
189  ImGuiINI::check_ini_setting(ini_cfg, "Appearance", "Font", font_index);
190  ImGuiINI::set_font(font_index);
191  ImGuiINI::check_ini_setting(ini_cfg, "Appearance", "Style", style_index);
192  ImGuiINI::set_style(style_index);
193  // Hardware Settings
194  std::string python_path;
195 #ifdef _WIN32
196  python_path = "py";
197 #else
198  python_path = "python3";
199 #endif
200  ImGuiINI::check_ini_setting(ini_cfg, "Hardware", "Threads", ricom->n_threads);
201  ImGuiINI::check_ini_setting(ini_cfg, "Hardware", "Queue Size", ricom->queue_size);
202  ImGuiINI::check_ini_setting(ini_cfg, "Hardware", "Image Refresh Interval [ms]", ricom->redraw_interval);
203  // Advapix Settings
204  ImGuiINI::check_ini_setting(ini_cfg, "Advapix", "nx/y", ricom->n_cam);
205  // Cheetah Settings
206  ImGuiINI::check_ini_setting(ini_cfg, "Cheetah", "nx/y", ricom->n_cam);
207  ImGuiINI::check_ini_setting(ini_cfg, "Cheetah", "data_port", ricom->socket.port);
208  ImGuiINI::check_ini_setting(ini_cfg, "Cheetah", "ip", ricom->socket.ip);
209 
210  const char *cmaps[] = {"Parula", "Heat", "Jet", "Turbo", "Hot", "Gray", "Magma", "Inferno", "Plasma", "Viridis", "Cividis", "Github", "HSV"};
211  bool b_redraw = false;
212  bool b_trigger_update = false;
213  float menu_split_v = control_menu_size.y * 0.8f;
214 
215  // Initialize Frequency approximation (for plotting only)
216  ricom->kernel.approximate_frequencies((size_t)ricom->nx);
217 
218  // Initialize all possible Windows, so everything is on the stack
219  bool show_com_x = false;
220  bool show_com_y = false;
221  bool ricom_fft = false;
222  bool vstem_fft = false;
223  bool e_field_fft = false;
225  std::map<std::string, ImGuiImageWindow<float>> generic_windows_f;
226  std::map<std::string, ImGuiImageWindow<std::complex<float>>> generic_windows_c;
227  generic_windows_f.emplace("RICOM", ImGuiImageWindow<float>("RICOM", &uiTextureIDs[1], true, 9, common_flags | GIM_Flags::FftButton, &ricom->b_ricom));
228  generic_windows_f.emplace("RICOM-FFT", ImGuiImageWindow<float>("RICOM-FFT", &uiTextureIDs[2], false, 4, common_flags, &ricom_fft));
229  GENERIC_WINDOW("RICOM").fft_window = &GENERIC_WINDOW("RICOM-FFT");
230 
231  generic_windows_f.emplace("vSTEM", ImGuiImageWindow<float>("vSTEM", &uiTextureIDs[3], true, 9, common_flags | GIM_Flags::FftButton, &ricom->b_vSTEM));
232  generic_windows_f.emplace("vSTEM-FFT", ImGuiImageWindow<float>("vSTEM-FFT", &uiTextureIDs[4], false, 4, common_flags, &vstem_fft));
233  GENERIC_WINDOW("vSTEM").fft_window = &GENERIC_WINDOW("vSTEM-FFT");
234 
235  generic_windows_f.emplace("COM-X", ImGuiImageWindow<float>("RICOM-COMX", &uiTextureIDs[5], true, 9, common_flags, &show_com_x));
236  generic_windows_f.emplace("COM-Y", ImGuiImageWindow<float>("RICOM-COMY", &uiTextureIDs[6], true, 9, common_flags, &show_com_y));
237 
238  generic_windows_c.emplace("E-FIELD", ImGuiImageWindow<std::complex<float>>("E-Field", &uiTextureIDs[7], true, 12, common_flags | GIM_Flags::FftButton, &ricom->b_e_mag));
239  generic_windows_f.emplace("E-Field-FFT", ImGuiImageWindow<float>("E-Field-FFT", &uiTextureIDs[8], false, 4, common_flags, &e_field_fft));
240  GENERIC_WINDOW_C("E-FIELD").fft_window = &GENERIC_WINDOW("E-Field-FFT");
241 
242  ricom->kernel.draw_surfaces();
243  bind_tex(ricom->kernel.srf_kx, uiTextureIDs[9]);
244  bind_tex(ricom->kernel.srf_ky, uiTextureIDs[10]);
245 
246  ImGuiID dock_id = 3775;
247  Main_Dock main_dock(dock_id);
248  static int drag_min_pos = 1;
249 
250  // Main loop
251  while (!b_done)
252  {
253  // Poll and handle events (inputs, window resize, etc.)
254  SDL_Event event;
255  while (SDL_PollEvent(&event))
256  {
257  ImGui_ImplSDL2_ProcessEvent(&event);
258  if (event.type == SDL_QUIT)
259  b_done = true;
260  if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
261  b_done = true;
262  }
263 
264  // Start the Dear ImGui frame
265  ImGui_ImplOpenGL3_NewFrame();
266  ImGui_ImplSDL2_NewFrame();
267  ImGui::NewFrame();
268 
269  // Menu
270  if (ImGui::BeginMainMenuBar())
271  {
272  if (ImGui::BeginMenu("Appearance"))
273  {
274  ImGui::Combo("CBED Colormap", &ricom->cbed_cmap, cmaps, IM_ARRAYSIZE(cmaps));
275  ImGuiINI::ShowFontSelector("Font", font_index, ini_cfg);
276  ImGuiINI::ShowStyleSelector("Style", style_index, ini_cfg);
277  ImGui::EndMenu();
278  }
279  if (ImGui::BeginMenu("Hardware Settings"))
280  {
281  ImGui::Text("Plotting");
282  if (ImGui::DragInt("Image Refresh Interval [ms]", &ricom->redraw_interval, 20, 10, 1000))
283  {
284  ini_cfg["Hardware"]["Image Refresh Interval [ms]"] = std::to_string(ricom->redraw_interval);
285  }
286  ImGui::Separator();
287 
288  ImGui::Text("Multithreading");
289  if (ImGui::DragInt("Threads", &ricom->n_threads, 1, 1, *&ricom->n_threads_max))
290  {
291  ini_cfg["Hardware"]["Threads"] = std::to_string(ricom->n_threads);
292  }
293  if (ImGui::DragInt("Queue Size", &ricom->queue_size, 1, 1, 256))
294  {
295  ini_cfg["Hardware"]["Queue Size"] = std::to_string(ricom->queue_size);
296  }
297  ImGui::EndMenu();
298  }
299  if (ImGui::BeginMenu("Imaging Modes"))
300  {
301  if (ImGui::Checkbox("Show riCOM", &ricom->b_ricom))
302  {
303  if (&ricom->b_ricom)
304  {
305  GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_image);
306  }
307  else
308  {
309  *GENERIC_WINDOW("RICOM").pb_open = false;
310  }
311  }
312  if (ImGui::Checkbox("Show CoM-X", &show_com_x))
313  {
314  if (show_com_x)
315  {
316  GENERIC_WINDOW("COM-X").set_data(ricom->nx, ricom->ny, &ricom->comx_image);
317  }
318  else
319  {
320  *GENERIC_WINDOW("COM-X").pb_open = false;
321  }
322  }
323  if (ImGui::Checkbox("Show CoM-Y", &show_com_y))
324  {
325  if (show_com_y)
326  {
327  GENERIC_WINDOW("COM-Y").set_data(ricom->nx, ricom->ny, &ricom->comy_image);
328  }
329  else
330  {
331  *GENERIC_WINDOW("COM-Y").pb_open = false;
332  }
333  }
334  if (ImGui::Checkbox("Show E-Field", &ricom->b_e_mag))
335  {
336  if (ricom->b_e_mag)
337  {
338  GENERIC_WINDOW_C("E-FIELD").set_data(ricom->nx, ricom->ny, &ricom->e_field_data);
339  }
340  else
341  {
342  *GENERIC_WINDOW_C("E-FIELD").pb_open = false;
343  }
344  }
345  if (ImGui::Checkbox("View vSTEM Image", &ricom->b_vSTEM))
346  {
347  if (ricom->b_vSTEM)
348  {
349  GENERIC_WINDOW("vSTEM").set_data(ricom->nx, ricom->ny, &ricom->stem_image);
350  }
351  else
352  {
353  *GENERIC_WINDOW("vSTEM").pb_open = false;
354  }
355  }
356  ImGui::EndMenu();
357  }
358  menu_bar_size = ImGui::GetWindowSize();
359  ImGui::EndMainMenuBar();
360  }
361 
362  const ImGuiViewport *viewport = ImGui::GetMainViewport();
363  if (ricom->p_prog_mon != nullptr)
364  {
365  if (ricom->p_prog_mon->report_set_public)
366  {
367  b_redraw = true;
368  ricom->p_prog_mon->report_set_public = false;
369  }
370  }
371  else
372  {
373  b_redraw = true;
374  }
375 
376  ImVec2 pos = viewport->Pos;
377  pos[1] += menu_bar_size.y;
378  ImGui::SetNextWindowPos(pos);
379 
380  control_menu_size.y = viewport->Size.y - menu_bar_size.y;
381  ImGui::SetNextWindowSize(control_menu_size);
382  ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1));
383 
384  ImGui::Begin("Navigation", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar);
385 
386  bool b_nx_changed = false;
387  ImGui::BeginChild("Controls", ImVec2(0, menu_split_v), false);
388  if (ImGui::CollapsingHeader("General Settings", ImGuiTreeNodeFlags_DefaultOpen))
389  {
390  ImGui::Text("Scan Area");
391  b_nx_changed = ImGui::DragInt("nx", &ricom->nx, 1, 1, SDL_MAX_SINT32);
392  ImGui::DragInt("ny", &ricom->ny, 1, 1, SDL_MAX_SINT32);
393  ImGui::DragInt("Repetitions", &ricom->rep, 1, 1, SDL_MAX_SINT32);
394  ImGui::BeginGroup();
395  ImGui::DragInt("skip row", &ricom->skip_row, 1, 0, SDL_MAX_SINT32);
396  ImGui::DragInt("skip img", &ricom->skip_img, 1, 0, SDL_MAX_SINT32);
397  ImGui::EndGroup();
398  if (ImGui::IsItemHovered())
399  {
400  ImGui::SetTooltip("Adjustments for Flyback time:\n skip row: skip n frames after each scan line\n skip img: skip n frames after each scan (when using repetitions)");
401  }
402 
403  ImGui::Text("CBED Centre");
404  int *max_nx = &ricom->n_cam;
405  bool offset_changed = ImGui::DragFloat2("Centre", &ricom->offset[0], 0.1f, 0.0, (float)*max_nx);
406  if (offset_changed)
407  {
408  ricom->b_recompute_detector = true;
409  ricom->b_recompute_kernel = true;
410  }
411  ImGui::Checkbox("Auto Centering", &ricom->update_offset);
412  }
413 
414  if (ImGui::CollapsingHeader("RICOM Settings", ImGuiTreeNodeFlags_DefaultOpen))
415  {
416  static int filter_max = 8;
417  static bool init_kernel_img = true;
418  bool kernel_changed = ImGui::DragInt("Kernel Size", &ricom->kernel.kernel_size, 1, 1, 300);
419  if (kernel_changed)
420  filter_max = ceil(sqrt(pow(ricom->kernel.kernel_size, 2) * 2));
421  bool rot_changed = ImGui::SliderFloat("Rotation", &ricom->kernel.rotation, 0.0f, 360.0f, "%.1f deg");
422  bool filter_changed = ImGui::Checkbox("Use filter?", &ricom->kernel.b_filter);
423  bool filter_changed2 = ImGui::DragInt2("low / high", &ricom->kernel.kernel_filter_frequency[0], 1, 0, filter_max);
424  if (init_kernel_img || rot_changed || kernel_changed || filter_changed || filter_changed2)
425  {
426  init_kernel_img = false;
427  if (ricom->b_busy)
428  {
429  ricom->b_recompute_kernel = true;
430  }
431  else
432  {
433  ricom->kernel.compute_kernel();
434  }
435  GENERIC_WINDOW("RICOM").reset_min_max();
436  ricom->kernel.draw_surfaces();
437  bind_tex(ricom->kernel.srf_kx, uiTextureIDs[9]);
438  bind_tex(ricom->kernel.srf_ky, uiTextureIDs[10]);
439  }
440  if (kernel_changed || b_nx_changed)
441  {
442  ricom->kernel.approximate_frequencies((size_t)ricom->nx);
443  }
444  float sxk = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y * 3) / 2;
445  ImGui::Image((void *)(intptr_t)uiTextureIDs[9], ImVec2(sxk, sxk), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
446  ImGui::SameLine();
447  ImGui::Image((void *)(intptr_t)uiTextureIDs[10], ImVec2(sxk, sxk), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f));
448  ImGui::PlotLines("Frequencies", ricom->kernel.f_approx.data(), ricom->kernel.f_approx.size(), 0, NULL, 0.0f, 1.0f, ImVec2(0, 50));
449  }
450  if (ricom->b_vSTEM)
451  {
452  if (ImGui::CollapsingHeader("vSTEM Settings", ImGuiTreeNodeFlags_DefaultOpen))
453  {
454  bool inner_changed = ImGui::SliderFloat("Inner Radius", &ricom->detector.radius[0], 0.0f, 182.0f, "%.1f px");
455  bool outer_changed = ImGui::SliderFloat("Outer Radius", &ricom->detector.radius[1], 0.0f, 182.0f, "%.1f px");
456  if (inner_changed || outer_changed)
457  {
458  ricom->b_recompute_detector = true;
459  GENERIC_WINDOW("vSTEM").reset_min_max();
460  }
461  }
462  }
463 
464  if (ImGui::CollapsingHeader("Stream reconstruction", ImGuiTreeNodeFlags_DefaultOpen)){
465 
466  if (ImGui::Button("Preview", ImVec2(-1.0f, 0.0f)))
467  {
468  cheetah_comm.stop();
469  ricom->b_continuous = true;
470  cheetah_comm.tpx3_det_config();
471  cheetah_comm.tpx3_cam_init();
472  cheetah_comm.tpx3_destination();
473 
474  // ricom->socket.connect_socket();
475  // ricom->socket.flush_socket();
476  b_started = true;
477  b_restarted = true;
478  ricom->camera = RICOM::CHEETAH;
479  run_thread = std::thread(&Ricom::run, ricom, 1);
480  run_thread.detach();
481  std::this_thread::sleep_for(std::chrono::milliseconds(500));
482  cheetah_comm.start();
483  // RICOM::run(ricom, RICOM::TCP);
484  // GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_image);
485  }
486 
487  if (ImGui::Button("Acquire", ImVec2(-1.0f, 0.0f)))
488  {
489  cheetah_comm.stop();
490  ricom->b_continuous = false;
491  cheetah_comm.tpx3_det_config();
492  cheetah_comm.tpx3_cam_init();
493  cheetah_comm.tpx3_destination();
494  ricom->camera = RICOM::CHEETAH;
495  run_thread = std::thread(&Ricom::run, ricom, 1);
496  run_thread.detach();
497  std::this_thread::sleep_for(std::chrono::milliseconds(500));
498  cheetah_comm.start();
499  // GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_image);
500  }
501 
502  if (ImGui::Button("Stop", ImVec2(-1.0f, 0.0f)))
503  {
504  cheetah_comm.stop();
505  ricom->rc_quit = true;
506  ricom->b_continuous = false;
507  // b_redraw = true;
508  }
509 
510  ImGui::Checkbox("Cumulative Mode", &ricom->b_cumulative);
511 
512  }
513 
514 
515  if (ImGui::CollapsingHeader("File reconstruction", ImGuiTreeNodeFlags_DefaultOpen))
516  {
517 
518  if (ImGui::Button("Open File", ImVec2(-1.0f, 0.0f)))
519  {
520  openFileDialog.Open();
521  }
522 
523  openFileDialog.Display();
524  if (openFileDialog.HasSelected())
525  {
526  filename = openFileDialog.GetSelected().string();
527  b_file_selected = true;
528  openFileDialog.ClearSelected();
529  ricom->mode = 0;
530  ricom->file_path = filename;
531  }
532  if (b_file_selected)
533  {
534  ImGui::Text("File: %s", filename.c_str());
535 
536  if (std::filesystem::path(filename).extension() == ".t3p")
537  {
538  ricom->camera = RICOM::ADVAPIX;
539  ImGui::DragInt("dwell time", &ricom->dt, 1, 1);
540  }
541  else if (std::filesystem::path(filename).extension() == ".tpx3")
542  ricom->camera = RICOM::CHEETAH;
543 
544  if (ImGui::Button("Run File", ImVec2(-1.0f, 0.0f)))
545  {
546  run_thread = std::thread(&Ricom::run, ricom, 0);
547  b_started = true;
548  b_restarted = true;
549  run_thread.detach();
550  // GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_image);
551  }
552  }
553  }
554  ImGui::EndChild();
555 
556  float panel_h_min = control_menu_size.y * 0.4;
557  float panel_h_max = control_menu_size.y - 32;
558  v_splitter(5, menu_split_v, panel_h_min, panel_h_max, pos.y + ImGui::GetStyle().ItemSpacing.y * 3);
559 
560  ImGui::BeginChild("Progress", ImVec2(0, 0), true, ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar);
561  ImGui::ProgressBar(ricom->fr_count / (ricom->fr_total), ImVec2(-1.0f, 0.0f));
562  ImGui::Text("Speed: %.2f kHz", ricom->fr_freq);
563  if (ImGui::Button("Quit", ImVec2(-1.0f, 0.0f)))
564  {
565  ricom->rc_quit = true;
566  b_redraw = true;
567  }
568 
569  ImGui::Text("COM= %.2f, %.2f", ricom->com_public[0], ricom->com_public[1]);
570 
571  // CBED Plot Area/DockSpace
572  ImGui::DockSpace(1319);
573  static auto first_time = true;
574  if (first_time)
575  {
576  first_time = false;
577  ImGui::DockBuilderRemoveNode(1319); // clear any previous layout
578  ImGui::DockBuilderAddNode(1319, ImGuiDockNodeFlags_DockSpace);
579  ImGui::DockBuilderDockWindow("CBED", 1319);
580  ImGui::DockBuilderFinish(1319);
581  }
582  ImGui::EndChild();
583  control_menu_size = ImGui::GetWindowSize();
584  ImGui::End();
585 
586  main_dock.render(ImVec2(control_menu_size.x, pos.y), ImVec2(viewport->Size.x - control_menu_size.x, viewport->Size.y - menu_bar_size.y));
587 
588  ImGui::Begin("CBED", nullptr, ImGuiWindowFlags_NoScrollbar);
589  ImGui::Checkbox("Plot CBED", &ricom->b_plot_cbed);
590  ImVec2 rem_space = ImGui::GetContentRegionAvail();
591  float tex_wh = (std::min)(rem_space.x, rem_space.y);
592  ImVec2 p = ImGui::GetCursorScreenPos();
593 
594  float com_rel_x = p.x + tex_wh * (ricom->com_public[0] / ricom->n_cam);
595  float com_rel_y = p.y + tex_wh * (ricom->com_public[1] / ricom->n_cam);
596 
597  float centre_x = p.x + tex_wh * (ricom->offset[0] / ricom->n_cam);
598  float centre_y = p.y + tex_wh * (ricom->offset[1] / ricom->n_cam);
599 
600  com_rel_x = (std::max)(p.x, com_rel_x);
601  com_rel_y = (std::max)(p.y, com_rel_y);
602  com_rel_x = (std::min)(p.x + tex_wh, com_rel_x);
603  com_rel_y = (std::min)(p.y + tex_wh, com_rel_y);
604 
605  float cross_width = tex_wh / 15.0f;
606  // if (b_redraw)
607  // {
608  // if (ricom->srf_cbed != NULL)
609  // {
610  // bind_tex(ricom->srf_cbed, uiTextureIDs[0]);
611  // }
612  // }
613  ImGui::Image((ImTextureID)uiTextureIDs[0], ImVec2(tex_wh, tex_wh), uv_min, uv_max, tint_col, border_col);
614  ImGui::GetWindowDrawList()->AddCircle(ImVec2(centre_x, centre_y), tex_wh * 0.03, IM_COL32(255, 255, 255, 255), 256);
615  ImGui::GetWindowDrawList()->AddLine(ImVec2(com_rel_x - cross_width, com_rel_y), ImVec2(com_rel_x + cross_width, com_rel_y), IM_COL32(255, 0, 0, 255), 1.5f);
616  ImGui::GetWindowDrawList()->AddLine(ImVec2(com_rel_x, com_rel_y - cross_width), ImVec2(com_rel_x, com_rel_y + cross_width), IM_COL32(255, 0, 0, 255), 1.5f);
617  if (ricom->b_vSTEM)
618  {
619  ImGui::GetWindowDrawList()->AddCircle(ImVec2(centre_x, centre_y), tex_wh * (ricom->detector.radius[0] / ricom->n_cam), IM_COL32(255, 50, 0, 255), 256);
620  ImGui::GetWindowDrawList()->AddCircle(ImVec2(centre_x, centre_y), tex_wh * (ricom->detector.radius[1] / ricom->n_cam), IM_COL32(255, 150, 0, 255), 256);
621  }
622  ImGui::End();
623 
624  if (b_acq_open)
625  {
626  ImVec2 pos_t = viewport->Pos;
627  pos_t[0] += control_menu_size[0] + 128;
628  pos_t[1] += menu_bar_size[1] + 128;
629  ImGui::SetNextWindowPos(pos_t, ImGuiCond_FirstUseEver);
630  ImVec2 size = {200, 400};
631  ImGui::SetNextWindowSize(size, ImGuiCond_FirstUseEver);
632 
633  ImGui::Begin("Acquisition Header", &b_acq_open);
634  ImGui::BeginChild("Scrolling");
635  ImGui::TextWrapped(ricom->socket.connection_information.data());
636  ImGui::EndChild();
637  ImGui::End();
638  }
639 
640  // Render all generic Image Windows
641  bool trigger = (b_trigger_update != ricom->b_busy) && (ricom->b_busy == false);
642  bool redraw_tick = (ricom->b_busy && b_redraw && b_started);
643  update_views(generic_windows_f, ricom, b_restarted, trigger, redraw_tick);
644  update_views(generic_windows_c, ricom, b_restarted, trigger, redraw_tick);
645 
646  b_restarted = false;
647  b_trigger_update = ricom->b_busy;
648 
649  // Rendering
650  ImGui::Render();
651  glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
652  glClear(GL_COLOR_BUFFER_BIT);
653  ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
654 
655  if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
656  {
657  SDL_Window *backup_current_window = SDL_GL_GetCurrentWindow();
658  SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
659  ImGui::UpdatePlatformWindows();
660  ImGui::RenderPlatformWindowsDefault();
661  SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
662  }
663 
664  SDL_GL_SwapWindow(window);
665 
666  b_redraw = false;
667  }
668 
669  if (run_thread.joinable())
670  run_thread.join();
671  if (py_thread.joinable())
672  py_thread.join();
673 
674  ImGui_ImplOpenGL3_Shutdown();
675  ImGui_ImplSDL2_Shutdown();
676  ImGui::DestroyContext();
677 
678  SDL_GL_DeleteContext(gl_context);
679  SDL_DestroyWindow(window);
680  SDL_Quit();
681 
682  ini_file.write(ini_cfg, true);
683  return 0;
684 }
void v_splitter(float thickness, float &size0, const float &min_h, const float &max_h, const float &offset)
Definition: GuiUtils.cpp:41
GIM_Flags
@ ColormapSelector
void bind_tex(SDL_Surface *srf, GLuint tex_id)
Definition: RunGUI.cpp:713
#define GENERIC_WINDOW_C(name)
Definition: RunGUI.cpp:56
#define GENERIC_WINDOW(name)
Definition: RunGUI.cpp:55
void update_views(std::map< std::string, ImGuiImageWindow< T >> &generic_windows_f, Ricom *ricom, bool b_restarted, bool trigger, bool b_redraw)
Definition: RunGUI.cpp:687
std::atomic< bool > report_set_public
std::array< float, 2 > radius
Definition: Ricom.h:131
SDL_Surface * srf_kx
Definition: Ricom.h:69
void compute_kernel()
Definition: Ricom.cpp:21
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
int kernel_size
Definition: Ricom.h:59
std::vector< float > stem_image
Definition: Ricom.h:248
std::vector< float > comy_image
Definition: Ricom.h:246
int skip_img
Definition: Ricom.h:270
void run(int mode)
Definition: Ricom.cpp:661
std::array< float, 2 > com_public
Definition: Ricom.h:244
SocketConnector socket
Definition: Ricom.h:220
int redraw_interval
Definition: Ricom.h:223
bool b_busy
Definition: Ricom.h:226
int mode
Definition: Ricom.h:258
int cbed_cmap
Definition: Ricom.h:292
bool b_recompute_detector
Definition: Ricom.h:239
int n_threads
Definition: Ricom.h:276
int rep
Definition: Ricom.h:267
bool update_offset
Definition: Ricom.h:227
int n_threads_max
Definition: Ricom.h:277
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 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
bool b_e_mag
Definition: Ricom.h:234
int fr_total
Definition: Ricom.h:268
ProgressMonitor * p_prog_mon
Definition: Ricom.h:225
bool b_plot_cbed
Definition: Ricom.h:230
float fr_freq
Definition: Ricom.h:279
bool b_recompute_kernel
Definition: Ricom.h:240
std::vector< float > ricom_image
Definition: Ricom.h:247
bool b_continuous
Definition: Ricom.h:228
bool b_cumulative
Definition: Ricom.h:229
int skip_row
Definition: Ricom.h:269
int n_cam
Definition: Ricom.h:265
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
std::array< float, 2 > offset
Definition: Ricom.h:243
Ricom_kernel kernel
Definition: Ricom.h:242
std::string connection_information
std::string ip
void check_ini_setting(mINI::INIStructure &ini_cfg, std::string section, std::string key, char *value)
Definition: ImGuiINI.hpp:116
bool ShowFontSelector(const char *label, int &selectedFont, mINI::INIStructure &ini_cfg)
Definition: ImGuiINI.hpp:57
bool ShowStyleSelector(const char *label, int &style_idx, mINI::INIStructure &ini_cfg)
Definition: ImGuiINI.hpp:37
void set_font(int font_idx)
Definition: ImGuiINI.hpp:81
void set_style(int style_idx)
Definition: ImGuiINI.hpp:21
@ ADVAPIX
Definition: Ricom.h:148
@ CHEETAH
Definition: Ricom.h:149

◆ update_views()

template<typename T >
void update_views ( std::map< std::string, ImGuiImageWindow< T >> &  generic_windows_f,
Ricom ricom,
bool  b_restarted,
bool  trigger,
bool  b_redraw 
)
inline

Definition at line 687 of file RunGUI.cpp.

688 {
689  for (auto &wnd : generic_windows_f)
690  {
691  if (wnd.first == "RICOM")
692  {
693  if (b_restarted)
694  {
695  wnd.second.set_nx_ny(ricom->nx, ricom->ny);
696  }
697  wnd.second.render_window(b_redraw, ricom->fr_count, ricom->kernel.kernel_size, trigger);
698  }
699  else
700  {
701  if (*wnd.second.pb_open)
702  {
703  if (b_restarted)
704  {
705  wnd.second.set_nx_ny(ricom->nx, ricom->ny);
706  }
707  wnd.second.render_window(b_redraw, ricom->fr_count, trigger);
708  }
709  }
710  }
711 }