riCOM_cpp
This repository contains the C++ implementation of the riCOM (Real Time Centre Of Mass) algorithm for 4D Scanning electron microscopy.
Functions
main.cpp File Reference
#include <string>
#include "Ricom.h"
#include "Camera.h"
Include dependency graph for main.cpp:

Go to the source code of this file.

Functions

int run_cli (int argc, char *argv[], Ricom *ricom, CAMERA::Default_configurations &hardware_configurations)
 
int run_gui (Ricom *ricom, CAMERA::Default_configurations &hardware_configurations)
 
void log2file (Ricom *ricom)
 
std::string get_os ()
 
int main (int argc, char *argv[])
 

Function Documentation

◆ get_os()

std::string get_os ( )

Definition at line 59 of file main.cpp.

59 {return "Unknown"};

◆ log2file()

void log2file ( Ricom ricom)

Definition at line 83 of file main.cpp.

84 {
85  if (freopen("ricom.log", "a", stdout) == NULL)
86  {
87  std::cout << "Error redirecting output to log file" << std::endl;
88  }
89  if (freopen("ricom.log", "a", stderr) == NULL)
90  {
91  std::cout << "Error redirecting error output to log file" << std::endl;
92  }
93  ricom->b_print2file = true;
94  auto t = std::time(nullptr);
95  auto tm = *std::localtime(&t);
96  std::cout << std::endl;
97  std::cout << "Ricom version " << version << " started at " << std::put_time(&tm, "%d/%m/%Y %H:%M:%S") << std::endl;
98  std::cout << "OS: " << get_os() << std::endl;
99 }
bool b_print2file
Definition: Ricom.h:220
std::string get_os()
Definition: main.cpp:59

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 62 of file main.cpp.

63 {
64 
65  Ricom ricom;
66  CAMERA::Default_configurations hardware_configurations;
67 
68  if (argc == 1)
69  {
70 #ifdef _WIN32
71  FreeConsole();
72 #endif
73  log2file(&ricom);
74  return run_gui(&ricom, hardware_configurations);
75  }
76  else
77  {
78  return run_cli(argc, argv, &ricom, hardware_configurations);
79  }
80 }
Definition: Ricom.h:152
int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configurations)
Definition: RunGUI.cpp:68
int run_cli(int argc, char *argv[], Ricom *ricom, CAMERA::Default_configurations &hardware_configurations)
Definition: RunCLI.cpp:21
void log2file(Ricom *ricom)
Definition: main.cpp:83

◆ run_cli()

int run_cli ( int  argc,
char *  argv[],
Ricom ricom,
CAMERA::Default_configurations hardware_configurations 
)

Definition at line 21 of file RunCLI.cpp.

22 {
23  ricom->b_plot_cbed = false;
24  std::string save_img = "";
25  std::string save_dat = "";
26 
27  // command line arguments
28  for (int i = 1; i < argc; i++)
29  {
30  if (i + 1 != argc)
31  {
32  // Set filename to read from .mib file
33  if (strcmp(argv[i], "-filename") == 0)
34  {
35  ricom->camera = hardware_configurations[ricom->select_mode_by_file(argv[i + 1])];
36  i++;
37  }
38  // Set IP of camera for TCP connection
39  if (strcmp(argv[i], "-ip") == 0)
40  {
41  ricom->socket.ip = argv[i + 1];
42  ricom->mode = RICOM::TCP;
43  i++;
44  }
45  // Set port data-read port of camera
46  if (strcmp(argv[i], "-port") == 0)
47  {
48  ricom->socket.port = std::stoi(argv[i + 1]);
49  ricom->mode = RICOM::TCP;
50  i++;
51  }
52  // Set width of image
53  if (strcmp(argv[i], "-nx") == 0)
54  {
55  ricom->nx = std::stoi(argv[i + 1]);
56  i++;
57  }
58  // Set height of image
59  if (strcmp(argv[i], "-ny") == 0)
60  {
61  ricom->ny = std::stoi(argv[i + 1]);
62  i++;
63  }
64  // Set width of camera
65  if (strcmp(argv[i], "-cam_nx") == 0)
66  {
67  ricom->camera.nx_cam = std::stoi(argv[i + 1]);
68  ricom->offset[0] = ((float)ricom->camera.nx_cam - 1) / 2;
69  i++;
70  }
71  // Set height of camera
72  if (strcmp(argv[i], "-cam_ny") == 0)
73  {
74  ricom->camera.ny_cam = std::stoi(argv[i + 1]);
75  ricom->offset[1] = ((float)ricom->camera.ny_cam - 1) / 2;
76  i++;
77  }
78  // Set skip per row
79  if (strcmp(argv[i], "-skipr") == 0)
80  {
81  ricom->skip_row = std::stoi(argv[i + 1]);
82  i++;
83  }
84  // Set skip per image
85  if (strcmp(argv[i], "-skipi") == 0)
86  {
87  ricom->skip_img = std::stoi(argv[i + 1]);
88  i++;
89  }
90  // Set kernel size
91  if (strcmp(argv[i], "-k") == 0)
92  {
93  ricom->kernel.kernel_size = std::stoi(argv[i + 1]);
94  i++;
95  }
96  // Set CBED Rotation
97  if (strcmp(argv[i], "-r") == 0)
98  {
99  ricom->kernel.rotation = std::stof(argv[i + 1]);
100  i++;
101  }
102  // Set CBED center offset
103  if (strcmp(argv[i], "-offset") == 0)
104  {
105  ricom->offset[0] = std::stof(argv[i + 1]);
106  i++;
107  ricom->offset[1] = std::stof(argv[i + 1]);
108  i++;
109  }
110  // Set CBED center offset
111  if (strcmp(argv[i], "-update_offset") == 0)
112  {
113  ricom->update_offset = (bool)std::stoi(argv[i + 1]);
114  i++;
115  }
116  // Set STEM radii
117  if (strcmp(argv[i], "-radius") == 0)
118  {
119  ricom->b_vSTEM = true;
120  ricom->detector.radius[0] = std::stof(argv[i + 1]);
121  i++;
122  ricom->detector.radius[1] = std::stof(argv[i + 1]);
123  i++;
124  }
125  // Set kernel filter
126  if (strcmp(argv[i], "-f") == 0)
127  {
128  ricom->kernel.b_filter = true;
129  ricom->kernel.kernel_filter_frequency[0] = std::stoi(argv[i + 1]);
130  i++;
131  ricom->kernel.kernel_filter_frequency[1] = std::stoi(argv[i + 1]);
132  i++;
133  }
134  // Set depth of pixel for raw mode
135  if (strcmp(argv[i], "-depth") == 0)
136  {
137  ricom->camera.depth = std::stoi(argv[i + 1]);
138  ricom->camera.model = CAMERA::MERLIN;
139  i++;
140  }
141  // Set number of repetitions
142  if (strcmp(argv[i], "-rep") == 0)
143  {
144  ricom->rep = std::stoi(argv[i + 1]);
145  i++;
146  }
147  // Set Dwell Time
148  if (strcmp(argv[i], "-dwell_time") == 0)
149  {
150  ricom->camera.dwell_time = std::stof(argv[i + 1]);
151  ricom->camera.model = CAMERA::TIMEPIX;
152  i++;
153  }
154  // Set Number of threads
155  if (strcmp(argv[i], "-threads") == 0)
156  {
157  ricom->n_threads = std::stoi(argv[i + 1]);
158  i++;
159  }
160  // Set Number queue size
161  if (strcmp(argv[i], "-queue_size") == 0)
162  {
163  ricom->queue_size = std::stoi(argv[i + 1]);
164  i++;
165  }
166  // Set redraw interval in ms
167  if (strcmp(argv[i], "-redraw_interval") == 0)
168  {
169  ricom->redraw_interval = std::stoi(argv[i + 1]);
170  ricom->b_plot2SDL = true;
171  i++;
172  }
173  // Set path to save reconstruction image
174  if (strcmp(argv[i], "-save_img_path") == 0)
175  {
176  save_img = argv[i + 1];
177  ricom->b_plot2SDL = true;
178  i++;
179  }
180  // Set path to save reconstruction data
181  if (strcmp(argv[i], "-save_data_path") == 0)
182  {
183  save_dat = argv[i + 1];
184  i++;
185  }
186  // plot electric field
187  if (strcmp(argv[i], "-plot_e_field") == 0)
188  {
189  ricom->b_e_mag = (bool)std::stoi(argv[i + 1]);
190  i++;
191  }
192  }
193  }
194 
195  if (ricom->b_plot2SDL)
196  {
197  std::vector<SdlImageWindow> image_windows;
198  std::thread run_thread;
199  run_thread = std::thread(RICOM::run_ricom, ricom, ricom->mode);
200  while (ricom->srf_ricom == NULL)
201  {
202  SDL_Delay(ricom->redraw_interval);
203  }
204 
205  run_thread.detach();
206 
207  // // Initializing SDL
208  SDL_DisplayMode DM; // To get the current display size
209  SDL_Event event; // Event variable
210 
211  SDL_Init(SDL_INIT_EVERYTHING);
212  SDL_GetCurrentDisplayMode(0, &DM);
213  float scale = (std::min)(((float)DM.w) / ricom->nx, ((float)DM.h) / ricom->ny) * 0.8;
214  bool b_redraw = false;
215  image_windows.push_back(SdlImageWindow("riCOM", ricom->srf_ricom, ricom->nx, ricom->ny, scale));
216  if (ricom->b_vSTEM)
217  {
218  image_windows.push_back(SdlImageWindow("vSTEM", ricom->srf_stem, ricom->nx, ricom->ny, scale));
219  }
220  if (ricom->b_e_mag)
221  {
222  image_windows.push_back(SdlImageWindow("E-Field", ricom->srf_e_mag, ricom->nx, ricom->ny, scale));
223  }
224 
225  bool b_open_window = true;
226  while (b_open_window)
227  {
228  if (ricom->p_prog_mon != nullptr)
229  {
230  if (ricom->p_prog_mon->report_set_public)
231  {
232  b_redraw = true;
233  ricom->p_prog_mon->report_set_public = false;
234  }
235  else
236  {
237  b_redraw = true;
238  }
239  }
240 
241  if (b_redraw)
242  {
243  for (auto &wnd : image_windows)
244  {
245  wnd.update_image();
246  }
247  }
248 
249  while (SDL_PollEvent(&event))
250  {
251  if (event.type == SDL_QUIT ||
252  (event.type == SDL_WINDOWEVENT &&
253  event.window.event == SDL_WINDOWEVENT_CLOSE))
254  {
255  ricom->rc_quit = true;
256  SDL_Delay(ricom->redraw_interval);
257  b_open_window = false;
258  }
259  }
260  }
261  }
262  else
263  {
264  RICOM::run_ricom(ricom, ricom->mode);
265  }
266  if (save_dat != "")
267  {
268  save_numpy(&save_dat, ricom->nx, ricom->ny, &ricom->ricom_data);
269  std::cout << "riCOM reconstruction data saved as " + save_dat << std::endl;
270  }
271  if (save_img != "")
272  {
273  save_image(&save_img, ricom->srf_ricom);
274  std::cout << "riCOM reconstruction image saved as " + save_img << std::endl;
275  }
276  return 0;
277 }
void save_numpy(std::string *path, int nx, int ny, std::vector< T > *data)
Definition: GuiUtils.cpp:17
void save_image(std::string *path, SDL_Surface *sdl_srf)
Definition: GuiUtils.cpp:30
Camera_model model
Definition: Camera.h:43
std::atomic< bool > report_set_public
std::array< float, 2 > radius
Definition: Ricom.h:128
bool b_filter
Definition: Ricom.h:57
float rotation
Definition: Ricom.h:61
std::array< int, 2 > kernel_filter_frequency
Definition: Ricom.h:58
int kernel_size
Definition: Ricom.h:56
int skip_img
Definition: Ricom.h:249
SocketConnector socket
Definition: Ricom.h:216
int redraw_interval
Definition: Ricom.h:221
int n_threads
Definition: Ricom.h:252
int rep
Definition: Ricom.h:246
bool update_offset
Definition: Ricom.h:225
bool b_plot2SDL
Definition: Ricom.h:229
std::vector< float > ricom_data
Definition: Ricom.h:238
SDL_Surface * srf_e_mag
Definition: Ricom.h:269
RICOM::modes mode
Definition: Ricom.h:219
int nx
Definition: Ricom.h:243
Ricom_detector detector
Definition: Ricom.h:232
bool rc_quit
Definition: Ricom.h:261
int queue_size
Definition: Ricom.h:254
bool b_e_mag
Definition: Ricom.h:227
SDL_Surface * srf_ricom
Definition: Ricom.h:263
ProgressMonitor * p_prog_mon
Definition: Ricom.h:223
enum CAMERA::Camera_model select_mode_by_file(const char *filename)
Definition: Ricom.cpp:1062
bool b_plot_cbed
Definition: Ricom.h:228
SDL_Surface * srf_stem
Definition: Ricom.h:265
CAMERA::Camera_BASE camera
Definition: Ricom.h:218
int skip_row
Definition: Ricom.h:248
bool b_vSTEM
Definition: Ricom.h:226
int ny
Definition: Ricom.h:244
std::array< float, 2 > offset
Definition: Ricom.h:234
Ricom_kernel kernel
Definition: Ricom.h:233
std::string ip
@ TIMEPIX
Definition: Camera.h:30
@ MERLIN
Definition: Camera.h:29
@ TCP
Definition: Ricom.h:145
void run_ricom(Ricom *r, RICOM::modes mode)
Definition: Ricom.cpp:1081

◆ run_gui()

int run_gui ( Ricom ricom,
CAMERA::Default_configurations hardware_configurations 
)

Definition at line 68 of file RunGUI.cpp.

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