sipm-characterisation 0.1.0
SiPM characterisation for ePIC — IV/DCR/gain, laser, readout, irradiation
Loading...
Searching...
No Matches
database_laser.C
Go to the documentation of this file.
1#pragma once
2
3#include "database.C"
4#include "../utils/general_utility.h"
5#include "../utils/tree_database.h"
6
7namespace database
8{
9 namespace laser
10 {
11 // --- Constants ---
12 // Physics constants
13 const double coarse_to_ns = 3.125; // ns
14 // --- Utility data structures ---
15 // --- Data structure in database reference
16 std::vector<std::string> fields = {"run", "status", "step", "board", "channels"};
17 std::vector<std::string> sub_run_fields = {"channel", "bcrconfig", "opmode", "deltathreshold", "vbias", "directory", "notes"};
18 // --- Tree batabase
20 std::unordered_map<int, std::vector<std::string>> info_database;
21 // --- Possible positions
22 std::vector<std::string> laser_positions = {"empty", "center", "top-left", "top-right", "bottom-left", "bottom-right"};
23 // --- Global variables
24 std::string basedir = "./Data/";
25
26 // --- Declarations ---
27 // --- I/O
28 // --- --- database
29 void read_database(std::string database_input_file);
30 void read_sub_run_database(std::string database_input_file, std::string type = "target");
31 void read_all_sub_runs(std::string target_run_tag);
32 void read_all_sub_runs();
33 // --- --- data
34 void download_run(std::string campaign, std::string target_run_tag = ".");
35 void unzip_sub_run(std::string target_file, std::string target_dir = ".", std::string campaign = "2024-laser-window");
36 void unzip_all_sub_runs(std::string target_run_tag);
37 void update_local_data_repository(std::string current_campaign = "2024-laser-window");
38 // --- Getters
39 std::unordered_map<std::string, std::vector<std::string>> get_run_infos(std::string run);
40 std::unordered_map<std::string, std::vector<std::string>> get_sub_run_infos(std::string sub_run);
41 std::unordered_map<std::string, std::vector<std::string>> get_sub_run_infos(int sub_run_id);
42 std::unordered_map<std::string, std::vector<std::string>> get_sub_run_infos(std::string board, std::string step, std::string channel, std::string vbias, std::string type, std::string position);
43 std::vector<std::pair<int, std::string>> get_all_laser_runs() { return database.get_children(-1, 4, {{3, "laser"}}); }
44 std::vector<std::pair<int, std::string>> get_all_laser_runs(std::string quality);
45 std::vector<std::pair<int, std::string>> get_all_laser_runs(std::string board, std::string step) { return database.get_children(-1, 4, {{3, "laser"}, {2, step}, {1, board}}); }
46 std::pair<int, std::string> get_latest_laser_run(std::string board, std::string step);
47 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> get_sub_runs_infos(std::string run, std::string channel, std::string vbias, std::string type, std::string position);
48 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> get_sub_runs_infos(std::string board, std::string step, std::string channel, std::string vbias, std::string type, std::string position) { return get_sub_runs_infos(get_latest_laser_run(board, step).second, channel, vbias, type, position); }
49 // --- General utilities
50 std::map<std::string, TGraphErrors *> get_graph_sensor_from_channel(std::string run, std::string sensor, std::string type, std::string position, TGraphErrors *(*graph_getter)(std::string, std::string, std::string, std::string));
51 // --- Measurements
52 std::array<std::array<float, 2>, 2> get_sub_run_value(std::string sub_run);
53 std::array<float, 2> get_sub_run_sig(std::string sub_run) { return get_sub_run_value(sub_run)[0]; }
54 std::array<float, 2> get_sub_run_bkg(std::string sub_run) { return get_sub_run_value(sub_run)[1]; }
55 TGraphErrors *get_pPDE_vs_vbias(std::string run, std::string channel, std::string type, std::string position);
56 TGraphErrors *get_bkg_vs_vbias(std::string run, std::string channel, std::string type, std::string position);
57 TGraphErrors *get_pPDE_vs_bkg(std::string run, std::string channel, std::string type, std::string position);
58 std::map<std::string, TGraphErrors *> get_sensor_pPDE_vs_vbias(std::string run, std::string sensor, std::string type, std::string position) { return get_graph_sensor_from_channel(run, sensor, type, position, get_pPDE_vs_vbias); };
59 std::map<std::string, TGraphErrors *> get_sensor_bkg_vs_vbias(std::string run, std::string sensor, std::string type, std::string position) { return get_graph_sensor_from_channel(run, sensor, type, position, get_bkg_vs_vbias); };
60 std::map<std::string, TGraphErrors *> get_sensor_pPDE_vs_bkg(std::string run, std::string sensor, std::string type, std::string position) { return get_graph_sensor_from_channel(run, sensor, type, position, get_pPDE_vs_bkg); };
61 std::map<std::string, TGraphErrors *> get_stability_check(std::vector<std::string> run_list);
62 std::map<std::string, TGraphErrors *> get_stability_check(std::vector<std::pair<int, std::string>> run_list);
63 void show_stability_check(std::vector<std::string> run_list);
64 void show_stability_check(std::vector<std::pair<int, std::string>> run_list);
65 // Implementations
66 // --- I/O
67 // --- --- database
69 {
70 // Start reading the file
71 std::ifstream data_stream(database_input_file);
72 std::string current_line;
73 while (std::getline(data_stream, current_line))
74 {
75 // Skip comment characters
76 if (current_line[0] == '#' || current_line[0] == ' ')
77 continue;
78 // Read database
79 std::stringstream string_in_stream(current_line);
80 std::unordered_map<std::string, std::string> data_by_field;
81 std::string current_data;
82 for (auto current_field : fields)
83 {
86 }
87 // Record quality
88 auto current_entry = database.find_or_create_node(-1, data_by_field["board"], data_by_field["step"], static_cast<std::string>("laser"), data_by_field["run"]);
89 database.find_or_create_node(current_entry, data_by_field["status"]);
90
91 // Record channels
92 std::vector<std::string> channels;
93 for (size_t i = 0; i < data_by_field["channels"].length(); i += 3)
94 {
95 // Extract the two-character group
96 char letter = data_by_field["channels"][i];
97 char symbol = data_by_field["channels"][i + 1];
98 if (symbol == '*')
99 {
100 // Expand when encountering '*'
101 channels.push_back(std::string(1, letter) + '1');
102 channels.push_back(std::string(1, letter) + '2');
103 channels.push_back(std::string(1, letter) + '3');
104 channels.push_back(std::string(1, letter) + '4');
105 }
106 else
107 {
108 // Add the two-character group as is
109 channels.push_back(std::string(1, letter) + symbol);
110 }
111 }
112 for (auto current_channel : channels)
113 info_database[database.find_or_create_node(current_entry, static_cast<std::string>("channels"))].push_back(current_channel);
114 }
115 }
116 void read_sub_run_database(std::string database_input_file, std::string type = "target")
117 {
118 // Start reading the file
119 std::ifstream data_stream(database_input_file);
120 if (!data_stream)
121 return;
122 std::string current_line;
123 while (std::getline(data_stream, current_line))
124 {
125 // Skip comment characters
126 if (current_line[0] == '#' || current_line[0] == ' ')
127 continue;
128 // Read database
129 std::stringstream string_in_stream(current_line);
130 std::unordered_map<std::string, std::string> data_by_field;
131 std::string current_data;
132 for (auto current_field : sub_run_fields)
133 {
136 }
137 // Recover global run and sub_run number
138 std::string global_run_tag = data_by_field["directory"].substr(40, 15);
139 auto run_tags = database.get_name_ids(global_run_tag);
140 if (run_tags.size() == 0)
141 {
142 cerr << "[WARNING][datbase::laser::read_sub_run_database] no run entry in general database, abort loading sub_run" << endl;
143 return;
144 }
145 if (run_tags.size() > 1)
146 {
147 cerr << "[WARNING][datbase::laser::read_sub_run_database] too many run entries in general database, abort loading sub_run" << endl;
148 return;
149 }
151 std::string sub_run_tag = data_by_field["directory"].substr(64, 15);
152 std::string channel = data_by_field["channel"];
153 auto current_entry = database.find_or_create_node(current_entry_father, sub_run_tag);
154 database.find_or_create_node(current_entry, channel);
155 for (auto current_field : sub_run_fields)
157 info_database[database.find_or_create_node(current_entry, static_cast<std::string>("type"))].push_back(type);
158 info_database[database.find_or_create_node(current_entry, static_cast<std::string>("global_run_tag"))].push_back(global_run_tag);
159 }
160 }
162 {
163 // Load the reference sensor
164 read_sub_run_database(basedir + "/" + target_run_tag + "/database.reference.A1.txt", "reference");
165 // Load the target sensors
166 auto run_tags = database.get_name_ids(target_run_tag);
167 if (run_tags.size() == 0)
168 {
169 cerr << "[WARNING][datbase::laser::read_sub_run_database] no run entry in general database, abort loading sub_run" << endl;
170 return;
171 }
172 if (run_tags.size() > 1)
173 {
174 cerr << "[WARNING][datbase::laser::read_sub_run_database] too many run entries in general database, abort loading sub_run" << endl;
175 return;
176 }
177 auto channels_id = database.find_or_create_node(run_tags[0], static_cast<std::string>("channels"));
179 read_sub_run_database(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".txt", "target");
181 read_sub_run_database(basedir + "/" + target_run_tag + "/database.proto." + current_channel + ".txt", "proto");
182 }
189 // --- --- data
190 void download_run(std::string campaign, std::string target_run_tag = ".")
191 {
192 std::system(("mkdir -p " + basedir + "/" + target_run_tag + "/").c_str());
193 // Download the reference sensor
194 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.reference." + "A1" + ".signal.tgz " + basedir + "/" + target_run_tag + "/").c_str());
195 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.reference." + "A1" + ".txt " + basedir + "/" + target_run_tag + "/").c_str());
196 unzip_sub_run(basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".signal.tgz", basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".signal/");
197 read_sub_run_database(basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".txt");
199 for (auto current_channel : current_run["channels"])
200 {
201 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz " + basedir + "/" + target_run_tag + "/").c_str());
202 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.target." + current_channel + ".txt " + basedir + "/" + target_run_tag + "/").c_str());
203 unzip_sub_run(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz", basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal/");
204 read_sub_run_database(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".txt");
205 }
206 }
207 void unzip_sub_run(std::string target_file, std::string target_dir = ".", std::string campaign = "2024-laser-window")
208 {
209 std::system(("mkdir -p " + target_dir).c_str());
210 std::system(("tar -xf " + target_file + " -C " + target_dir).c_str());
211 std::system(("mv " + target_dir + "/home/eic/DATA/" + campaign + "/actual/*/subruns/* " + target_dir).c_str());
212 std::system(("rm -r " + target_dir + "/home").c_str());
213 std::system(("rm " + target_file).c_str());
214 }
216 {
217 // Load the reference sensor
218 unzip_sub_run(basedir + "/" + target_run_tag + "/database.reference." + "A1.signal" + ".tgz", basedir + "/" + target_run_tag + "/database.reference." + "A1.signal/");
219 // Load the target sensors
221 for (auto current_channel : current_run["channels"])
222 unzip_sub_run(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz", basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal/");
223 }
224 void update_local_data_repository(std::string current_campaign = "2024-laser-window")
225 {
229 {
230 if (std::find(all_downloaded_runs.begin(), all_downloaded_runs.end(), current_run.second) != all_downloaded_runs.end())
231 continue;
233 if (!current_run_infos.count("good"))
234 continue;
237 }
238 }
239 // --- Getters
240 std::unordered_map<std::string, std::vector<std::string>> get_run_infos(std::string run)
241 {
242 std::unordered_map<std::string, std::vector<std::string>> result;
243 auto list_of_infos = database.get_children(database.get_name_ids(run)[0]);
244 for (auto current_info : list_of_infos)
246 return result;
247 }
248 std::unordered_map<std::string, std::vector<std::string>> get_sub_run_infos(std::string sub_run)
249 {
250 std::unordered_map<std::string, std::vector<std::string>> result;
251 auto list_of_infos = database.get_children(-1, 6, {{5, sub_run}});
252 for (auto current_info : list_of_infos)
254 return result;
255 }
256 std::unordered_map<std::string, std::vector<std::string>> get_sub_run_infos(int sub_run_id)
257 {
258 std::unordered_map<std::string, std::vector<std::string>> result;
259 auto list_of_infos = database.get_children(sub_run_id);
260 for (auto current_info : list_of_infos)
262 return result;
263 }
264 std::vector<std::pair<int, std::string>> get_all_laser_runs(std::string quality)
265 {
267 std::vector<std::pair<int, std::string>> filtered_run_list;
269 {
271 if (!current_run_infos.count(quality))
272 continue;
274 }
275 return filtered_run_list;
276 }
277 std::pair<int, std::string> get_latest_laser_run(std::string board, std::string step)
278 {
280 std::sort(all_laser_runs.begin(), all_laser_runs.end(),
281 [](const std::pair<int, std::string> &a, const std::pair<int, std::string> &b)
282 { return a.second > b.second; });
283 return all_laser_runs[0];
284 }
285 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> get_sub_runs_infos(std::string run, std::string channel, std::string vbias, std::string type, std::string position)
286 {
287 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> result;
288 auto sub_run_list = database.get_children(database.get_name_ids(run)[0]);
289 for (auto current_sub_run : sub_run_list)
290 {
292 if (current_sub_run_infos.empty())
293 continue;
294 if (channel != current_sub_run_infos["channel"][0])
295 continue;
296 if (vbias != current_sub_run_infos["vbias"][0])
297 continue;
298 if (position != current_sub_run_infos["notes"][0])
299 continue;
300 if (type != current_sub_run_infos["type"][0])
301 continue;
303 }
304 return result;
305 }
306 // --- General utilities
307 std::map<std::string, TGraphErrors *> get_graph_sensor_from_channel(std::string run, std::string sensor, std::string type, std::string position, TGraphErrors *(*graph_getter)(std::string, std::string, std::string, std::string))
308 {
309 std::vector<TGraphErrors *> graphs_buffer;
310 for (auto current_channel : sensor_to_channels[sensor])
313 }
314 // --- Measurements
315 std::array<std::array<float, 2>, 2> get_sub_run_value(std::string sub_run)
316 {
317 std::array<std::array<float, 2>, 2> result; // 2x2 array to store signal and background values and errors
318
319 // Construct the file path based on parameters and open the ROOT file
322 TFile *target_file = new TFile((basedir + "/" + sub_run_infos["global_run_tag"][0] + "/database." + sub_run_infos["type"][0] + "." + sub_run_infos["channel"][0] + ".signal/" + sub_run + "/decoded/signal.root").c_str());
323
324 // Check the file is there
325 if (target_file->IsZombie())
326 return {{{0., 0.}, {0., 0.}}};
327
328 // Retrieve the histogram "hDelta" from the ROOT file
329 auto current_hDelta = (TH1F *)(target_file->Get("hDelta"));
330
331 // Initialize variables to hold errors for background and full signal calculations
333
334 // Compute background values and their errors for two separate regions within the histogram
335 auto bkg_val_1 = current_hDelta->IntegralAndError(19, 35, bkg_err_1); // Background region 1
336 auto bkg_val_2 = current_hDelta->IntegralAndError(67, 83, bkg_err_2); // Background region 2
337
338 // Compute full signal value and error over the main signal region
339 auto full_val = current_hDelta->IntegralAndError(35, 67, full_err);
340
341 // Combine the two background values and calculate the total background error
342 float bkg_val = (bkg_val_1 + bkg_val_2); // Sum of background regions
343 float bkg_err = TMath::Sqrt(bkg_err_1 * bkg_err_1 + bkg_err_2 * bkg_err_2); // Combined background error
344
345 // Calculate the signal value and its error by subtracting background from full signal
346 float sig_val = full_val - bkg_val;
347 float sig_err = TMath::Sqrt(bkg_err * bkg_err + full_err * full_err); // Total error for signal
348
349 // Convert background values and errors to nanoseconds using a scaling factor
350 bkg_val *= 1.e9 / (100 * coarse_to_ns);
351 bkg_err *= 1.e9 / (100 * coarse_to_ns);
352
353 // Clean up by deleting the histogram and the ROOT file object to free memory
354 delete current_hDelta;
355 delete target_file;
356
357 // Store signal and background values and errors in the result array
358 result[0] = {sig_val, sig_err}; // Signal {value, error}
359 result[1] = {bkg_val, bkg_err}; // Background {value, error}
360
361 // Return the result array with signal and background data
362 return result;
363 }
364 TGraphErrors *get_pPDE_vs_vbias(std::string run, std::string channel, std::string type, std::string position)
365 {
366 // Create a new TGraphErrors object to store the graph with error bars
367 auto result = new TGraphErrors();
368
369 // Set the x-axis and y-axis titles for the graph
370 result->GetXaxis()->SetTitle("V_{bias} (V)"); // X-axis: bias voltage (V)
371 result->GetYaxis()->SetTitle("Pseudo-efficiency (%)"); // Y-axis: pseudo-efficiency percentage
372
373 // Retrieve all sub-run identifiers associated with the specified run
374 auto sub_run_list = database.get_children(database.get_name_ids(run)[0]);
375
376 // Loop through each sub-run's data, unpacking sub-run ID and name
378 {
379 // Get information of the current sub-run
381
382 // Skip this sub-run if its position, type, or channel does not match the specified parameters
383 if (current_sub_run_info.empty())
384 continue;
385 if (current_sub_run_info["notes"][0] != position)
386 continue;
387 if (current_sub_run_info["type"][0] != type)
388 continue;
389 if (current_sub_run_info["channel"][0] != channel)
390 continue;
391
392 // Get the current point index in the TGraphErrors (used to add new points)
393 auto iPnt = result->GetN();
394
395 // Convert the "vbias" value from string to double for use as the x-axis value
396 auto x_value = std::stod(current_sub_run_info["vbias"][0]);
397
398 // Retrieve the y-value (pseudo-efficiency) and its associated error for the sub-run
400
401 // Set the x and y values for the current point in the graph
402 result->SetPoint(iPnt, x_value, y_value[0]);
403
404 // Set the y-axis error for the current point in the graph
405 result->SetPointError(iPnt, 0, y_value[1]);
406 }
407 // Return the completed TGraphErrors object with the plotted data and errors
408 return graphutils::average_same_x(result)["ave_err"];
409 }
410 TGraphErrors *get_bkg_vs_vbias(std::string run, std::string channel, std::string type, std::string position)
411 {
412 // Create a new TGraphErrors object to store the graph with error bars
413 auto result = new TGraphErrors();
414
415 // Set the x-axis and y-axis titles for the graph
416 result->GetXaxis()->SetTitle("V_{bias} (V)"); // X-axis: bias voltage (V)
417 result->GetYaxis()->SetTitle("Pseudo-efficiency (%)"); // Y-axis: pseudo-efficiency percentage
418
419 // Retrieve all sub-run identifiers associated with the specified run
420 auto sub_run_list = database.get_children(database.get_name_ids(run)[0]);
421
422 // Loop through each sub-run's data, unpacking sub-run ID and name
424 {
425 // Get information of the current sub-run
427
428 // Skip this sub-run if its position, type, or channel does not match the specified parameters
429 if (current_sub_run_info.empty())
430 continue;
431 if (current_sub_run_info["notes"][0] != position)
432 continue;
433 if (current_sub_run_info["type"][0] != type)
434 continue;
435 if (current_sub_run_info["channel"][0] != channel)
436 continue;
437
438 // Get the current point index in the TGraphErrors (used to add new points)
439 auto iPnt = result->GetN();
440
441 // Convert the "vbias" value from string to double for use as the x-axis value
442 auto x_value = std::stod(current_sub_run_info["vbias"][0]);
443
444 // Retrieve the y-value (pseudo-efficiency) and its associated error for the sub-run
446
447 // Set the x and y values for the current point in the graph
448 result->SetPoint(iPnt, x_value, y_value[0]);
449
450 // Set the y-axis error for the current point in the graph
451 result->SetPointError(iPnt, 0, y_value[1]);
452 }
453 // Return the completed TGraphErrors object with the plotted data and errors
454 return graphutils::average_same_x(result)["ave_err"];
455 }
456 TGraphErrors *get_pPDE_vs_bkg(std::string run, std::string channel, std::string type, std::string position)
457 {
458 // Create a new TGraphErrors object to store the graph with error bars
459 auto result = new TGraphErrors();
460
461 // Set the x-axis and y-axis titles for the graph
462 result->GetXaxis()->SetTitle("V_{bias} (V)"); // X-axis: bias voltage (V)
463 result->GetYaxis()->SetTitle("Pseudo-efficiency (%)"); // Y-axis: pseudo-efficiency percentage
464
465 // Retrieve all sub-run identifiers associated with the specified run
466 auto sub_run_list = database.get_children(database.get_name_ids(run)[0]);
467
468 // Loop through each sub-run's data, unpacking sub-run ID and name
470 {
471 // Get information of the current sub-run
473
474 // Skip this sub-run if its position, type, or channel does not match the specified parameters
475 if (current_sub_run_info.empty())
476 continue;
477 if (current_sub_run_info["notes"][0] != position)
478 continue;
479 if (current_sub_run_info["type"][0] != type)
480 continue;
481 if (current_sub_run_info["channel"][0] != channel)
482 continue;
483
484 // Get the current point index in the TGraphErrors (used to add new points)
485 auto iPnt = result->GetN();
486
487 // Convert the "vbias" value from string to double for use as the x-axis value
489
490 // Retrieve the y-value (pseudo-efficiency) and its associated error for the sub-run
492
493 // Set the x and y values for the current point in the graph
494 result->SetPoint(iPnt, x_value[0], y_value[0]);
495
496 // Set the y-axis error for the current point in the graph
497 result->SetPointError(iPnt, x_value[1], y_value[1]);
498 }
499 // Return the completed TGraphErrors object with the plotted data and errors
500 return result; // graphutils::average(result, 3);
501 }
502 std::map<std::string, TGraphErrors *> get_stability_check(std::vector<std::string> run_list)
503 {
504 std::map<std::string, TGraphErrors *> result;
506 {
507 result["pPDE::" + current_position] = new TGraphErrors();
508 result["bkg::" + current_position] = new TGraphErrors();
509 auto i_pnt = -1;
510 for (auto current_run : run_list)
511 {
512 i_pnt++;
513 auto current_timestamp = std::stoll(current_run);
515 auto current_bkg = get_bkg_vs_vbias(current_run, "A1", "reference", current_position);
516 result["pPDE::" + current_position]->SetPoint(i_pnt, current_timestamp, current_pPDE->GetPointY(2));
517 result["pPDE::" + current_position]->SetPointError(i_pnt, 0, current_pPDE->GetErrorY(2));
518 result["bkg::" + current_position]->SetPoint(i_pnt, current_timestamp, current_pPDE->GetPointY(2));
519 result["bkg::" + current_position]->SetPointError(i_pnt, 0, current_pPDE->GetErrorY(2));
520 }
521 }
522 return result;
523 }
524 std::map<std::string, TGraphErrors *> get_stability_check(std::vector<std::pair<int, std::string>> run_list)
525 {
526 std::vector<std::string> run_list_string(run_list.size());
527 std::transform(
528 run_list.begin(),
529 run_list.end(),
530 run_list_string.begin(),
531 [](const std::pair<int, std::string> &pair)
532 { return pair.second; });
534 }
535 void show_stability_check(std::vector<std::string> run_list)
536 {
538 TCanvas *plot_all = new TCanvas();
539 plot_all->Divide(1, 2);
540 plot_all->cd(1);
542 all_graphs["pPDE::" + current_position]->Draw("ALP");
543 // result["bkg::" + current_position];
544 plot_all->cd(2);
545 }
546 void show_stability_check(std::vector<std::pair<int, std::string>> run_list)
547 {
548 std::vector<std::string> run_list_string(run_list.size());
549 std::transform(
550 run_list.begin(),
551 run_list.end(),
552 run_list_string.begin(),
553 [](const std::pair<int, std::string> &pair)
554 { return pair.second; });
556 }
557 }
558 /*
559 namespace laser
560 {
561 // --- Constants ---
562 // Physics constants
563 const double coarse_to_ns = 3.125; // ns
564 // --- Utility data structures ---
565 // --- Data structure in database reference
566 std::vector<std::string> fields = {
567 "run", "status", "step", "board", "channels"};
568 std::vector<std::string> criteria = {
569 "run", "status", "channels"};
570 std::vector<std::string> sub_run_fields = {
571 "channel", "bcrconfig", "opmode", "deltathreshold", "vbias", "directory", "notes"};
572 std::vector<std::string> sub_run_criteria = {
573 "channel", "bcrconfig", "opmode", "deltathreshold", "vbias", "directory", "notes"};
574 // --- Global variables
575 std::string basedir = "./Data/";
576 // --- Board, Status, Run, Information
577 std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>>> database_memory;
578 // --- Run, Type, Channel, sub_run, Information
579 std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>>>> sub_runs_database_memory;
580
581
582 // --- Declarations ---
583 // --- I/O
584 bool look_for_run(std::string global_run_tag);
585 std::unordered_map<std::string, std::vector<std::string>> get_run(std::string global_run_tag);
586 void download_run(std::string campaign, std::string target_run_tag = ".");
587 void unzip_sub_run(std::string target_file, std::string target_dir = ".");
588 void unzip_all_sub_runs(std::string target_run_tag);
589 // --- Quality assurance
590 void show_database();
591 void show_sub_run_database();
592 // --- Getters
593 std::vector<std::string> get_channels(std::string board, std::string status, std::string run);
594 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> get_sub_runs(std::string run, std::string type, std::string channel);
595
596 // Implementations
597 // --- I/O
598 void read_database(std::string database_input_file)
599 {
600 // Start reading the file
601 std::ifstream data_stream(database_input_file);
602 std::string current_line;
603 while (std::getline(data_stream, current_line))
604 {
605 // Skip comment characters
606 if (current_line[0] == '#' || current_line[0] == ' ')
607 continue;
608 // Read database
609 std::stringstream string_in_stream(current_line);
610 std::unordered_map<std::string, std::string> data_by_field;
611 std::string current_data;
612 for (auto current_field : fields)
613 {
614 string_in_stream >> current_data;
615 data_by_field[current_field] = current_data;
616 }
617 // Record quality
618 database_memory[data_by_field["board"]][data_by_field["step"]][data_by_field["run"]]["status"].push_back(data_by_field["status"]);
619 // Record channels
620 std::vector<std::string> channels;
621 for (size_t i = 0; i < data_by_field["channels"].length(); i += 3)
622 {
623 // Extract the two-character group
624 char letter = data_by_field["channels"][i];
625 char symbol = data_by_field["channels"][i + 1];
626 if (symbol == '*')
627 {
628 // Expand when encountering '*'
629 channels.push_back(std::string(1, letter) + '1');
630 channels.push_back(std::string(1, letter) + '2');
631 channels.push_back(std::string(1, letter) + '3');
632 channels.push_back(std::string(1, letter) + '4');
633 }
634 else
635 {
636 // Add the two-character group as is
637 channels.push_back(std::string(1, letter) + symbol);
638 }
639 }
640 for (auto current_channel : channels)
641 database_memory[data_by_field["board"]][data_by_field["step"]][data_by_field["run"]]["channels"].push_back(current_channel);
642 }
643 }
644 bool look_for_run(std::string global_run_tag)
645 {
646 for (auto [current_board, all_statuses] : database_memory)
647 for (auto [current_status, all_runs] : all_statuses)
648 {
649 auto current_run = all_runs.find(global_run_tag);
650 if (current_run != all_runs.end())
651 return true;
652 }
653 return false;
654 }
655 std::unordered_map<std::string, std::vector<std::string>> get_run(std::string global_run_tag)
656 {
657 for (auto [current_board, all_statuses] : database_memory)
658 for (auto [current_status, all_runs] : all_statuses)
659 {
660 auto current_run = all_runs.find(global_run_tag);
661 if (current_run != all_runs.end())
662 return current_run->second;
663 }
664 return {};
665 }
666 void read_sub_run_database(std::string database_input_file, std::string type = "target")
667 {
668 // Check the run is there in the global database
669
670 // Start reading the file
671 std::ifstream data_stream(database_input_file);
672 if (!data_stream)
673 return;
674 std::string current_line;
675 while (std::getline(data_stream, current_line))
676 {
677 // Skip comment characters
678 if (current_line[0] == '#' || current_line[0] == ' ')
679 continue;
680 // Read database
681 std::stringstream string_in_stream(current_line);
682 std::unordered_map<std::string, std::string> data_by_field;
683 std::string current_data;
684 for (auto current_field : sub_run_fields)
685 {
686 string_in_stream >> current_data;
687 data_by_field[current_field] = current_data;
688 }
689 // Recover global run and sub_run number
690 std::string global_run_tag = data_by_field["directory"].substr(40, 15);
691 if (!look_for_run(global_run_tag))
692 cerr << "[WARNING][datbase::laser::read_sub_run_database] no run entry in general databse, loading sub_run data as orphan" << endl;
693 std::string sub_run_tag = data_by_field["directory"].substr(64, 15);
694 std::string channel = data_by_field["channel"];
695 for (auto current_field : sub_run_fields)
696 sub_runs_database_memory[global_run_tag][type][channel][sub_run_tag][current_field].push_back(data_by_field[current_field]);
697 }
698 }
699 void read_all_sub_runs(std::string target_run_tag)
700 {
701 if (!look_for_run(target_run_tag))
702 cerr << "[WARNING][datbase::laser::read_all_sub_runs] no run entry in general databse, loading sub_run data as orphan" << endl;
703 // Load the reference sensor
704 read_sub_run_database(basedir + "/" + target_run_tag + "/database.reference.A1.txt", "reference");
705 // Load the target sensors
706 auto current_run = get_run(target_run_tag);
707 for (auto current_channel : current_run["channels"])
708 read_sub_run_database(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".txt", "target");
709 for (auto current_channel : current_run["channels"])
710 read_sub_run_database(basedir + "/" + target_run_tag + "/database.proto." + current_channel + ".txt", "target");
711 }
712 void read_all_sub_runs()
713 {
714 for (auto [current_board, all_statuses] : database_memory)
715 for (auto [current_status, all_runs] : all_statuses)
716 for (auto [current_run, all_infos] : all_runs)
717 read_all_sub_runs(current_run);
718 }
719 void download_run(std::string campaign, std::string target_run_tag = ".")
720 {
721 if (!look_for_run(target_run_tag))
722 cerr << "[WARNING][datbase::laser::download_run] no run entry in general databse, loading sub_run data as orphan" << endl;
723 std::system(("mkdir -p " + basedir + "/" + target_run_tag + "/").c_str());
724 // Download the reference sensor
725 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.reference." + "A1" + ".signal.tgz " + basedir + "/" + target_run_tag + "/").c_str());
726 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.reference." + "A1" + ".txt " + basedir + "/" + target_run_tag + "/").c_str());
727 unzip_sub_run(basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".signal.tgz", basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".signal/");
728 read_sub_run_database(basedir + "/" + target_run_tag + "/database.reference." + "A1" + ".txt");
729 auto current_run = get_run(target_run_tag);
730 for (auto current_channel : current_run["channels"])
731 {
732 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz " + basedir + "/" + target_run_tag + "/").c_str());
733 std::system(("scp eic@eicdesk01:/home/eic/DATA/" + campaign + "/actual/" + target_run_tag + "/database.target." + current_channel + ".txt " + basedir + "/" + target_run_tag + "/").c_str());
734 unzip_sub_run(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz", basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal/");
735 read_sub_run_database(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".txt");
736 }
737 }
738 void unzip_sub_run(std::string target_file, std::string target_dir = ".")
739 {
740 std::system(("mkdir -p " + target_dir).c_str());
741 std::system(("tar -xf " + target_file + " -C " + target_dir).c_str());
742 std::system(("mv " + target_dir + "/home/eic/DATA/2024-laser-window/actual/\*\/sub_runs/\* " + target_dir).c_str());
743 std::system(("rm -r " + target_dir + "/home").c_str());
744 std::system(("rm " + target_file).c_str());
745 }
746 void unzip_all_sub_runs(std::string target_run_tag)
747 {
748 if (!look_for_run(target_run_tag))
749 cerr << "[WARNING][datbase::laser::unzip_all_sub_runs] no run entry in general databse, loading sub_run data as orphan" << endl;
750 // Load the reference sensor
751 unzip_sub_run(basedir + "/" + target_run_tag + "/database.reference." + "A1.signal" + ".tgz", basedir + "/" + target_run_tag + "/database.reference." + "A1.signal/");
752 // Load the target sensors
753 auto current_run = get_run(target_run_tag);
754 for (auto current_channel : current_run["channels"])
755 unzip_sub_run(basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal.tgz", basedir + "/" + target_run_tag + "/database.target." + current_channel + ".signal/");
756 }
757 // --- Quality assurance
758 void show_database()
759 {
760 cout << "[INFO][database::show_database] Starting print all database entries" << endl;
761 for (auto [current_board, all_statuses] : database_memory)
762 for (auto [current_status, all_runs] : all_statuses)
763 for (auto [current_run, all_informations] : all_runs)
764 for (auto [current_information, all_values] : all_informations)
765 for (auto current_value : all_values)
766 cout << "[INFO][database::show_database] [Board] " << current_board << " - [Status] " << current_status << " - [run] " << current_run << " - [Info] " << current_information << " - [Value] " << current_value << endl;
767 }
768 void show_sub_run_database()
769 {
770 cout << "[INFO][database::show_sub_run_database] Starting print all database entries" << endl;
771 for (auto [current_run, all_types] : sub_runs_database_memory)
772 for (auto [current_type, all_channels] : all_types)
773 for (auto [current_channel, all_sub_runs] : all_channels)
774 for (auto [current_sub_run, all_informations] : all_sub_runs)
775 for (auto [current_information, all_values] : all_informations)
776 for (auto current_value : all_values)
777 cout << "[INFO][database::show_sub_run_database] [Run] " << current_run << " - [Type] " << current_type << " - [Channel] " << current_channel << " - [sub_run] " << current_sub_run << " - [Info] " << current_information << " - [Value] " << current_value << endl;
778 }
779 // --- Getters
780 std::vector<std::string> get_channels(std::string board, std::string status, std::string run)
781 {
782 // TODO: Set limitations and protections for missing infos (no run, no board, no status)
783 return database_memory[board][status][run]["channels"];
784 }
785 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>> get_sub_runs(std::string run, std::string type, std::string channel)
786 {
787 return sub_runs_database_memory[run][type][channel];
788 }
789 // --- Measures
790 // Returns values for signal and background in large coincidence region
791 std::array<std::array<float, 2>, 2> get_sub_run_value(std::string global_run, std::string sub_run, std::string channel, std::string type = "target")
792 {
793 std::array<std::array<float, 2>, 2> result;
794 TFile *target_file = new TFile((basedir + "/" + global_run + "/database." + type + "." + channel + ".signal/" + sub_run + "/decoded/signal.root").c_str());
795 auto current_hDelta = (TH1F *)(target_file->Get("hDelta"));
796 double bkg_err_1, bkg_err_2, full_err;
797 auto bkg_val_1 = current_hDelta->IntegralAndError(19, 35, bkg_err_1);
798 auto bkg_val_2 = current_hDelta->IntegralAndError(67, 83, bkg_err_2);
799 auto full_val = current_hDelta->IntegralAndError(35, 67, full_err);
800 float bkg_val = (bkg_val_1 + bkg_val_2);
801 float bkg_err = TMath::Sqrt(bkg_err_1 * bkg_err_1 + bkg_err_2 * bkg_err_2);
802 float sig_val = full_val - bkg_val;
803 float sig_err = TMath::Sqrt(bkg_err * bkg_err + full_err * full_err);
804 bkg_val *= 1.e9 / (100 * coarse_to_ns);
805 bkg_err *= 1.e9 / (100 * coarse_to_ns);
806 delete current_hDelta;
807 delete target_file;
808 result[0] = {sig_val, sig_err};
809 result[1] = {bkg_val, bkg_err};
810 return result;
811 }
812 std::array<float, 2> get_sub_run_sig(std::string global_run, std::string sub_run, std::string channel, std::string type = "target")
813 {
814 return get_sub_run_value(global_run, sub_run, channel, type)[0];
815 }
816 std::array<float, 2> get_sub_run_bkg(std::string global_run, std::string sub_run, std::string channel, std::string type = "target")
817 {
818 return get_sub_run_value(global_run, sub_run, channel, type)[1];
819 }
820 // --- --- General functions
821 // --- --- --- Getters of curves
822 TGraphErrors *get_pPDE_vs_vbias(std::string run, std::string channel, std::string type, std::string position = "center")
823 {
824 auto result = new TGraphErrors();
825 result->GetXaxis()->SetTitle("V_{bias} (V)");
826 result->GetYaxis()->SetTitle("Pseudo-efficiency (%)");
827 auto all_sub_runs_data = get_sub_runs(run, type, channel);
828 for (auto [current_sub_run, all_informations] : all_sub_runs_data)
829 {
830 if (all_informations["notes"][0] != position)
831 continue;
832 auto iPnt = result->GetN();
833 auto x_value = std::stod(all_informations["vbias"][0]);
834 auto y_value = get_sub_run_sig(run, current_sub_run, channel, type);
835 result->SetPoint(iPnt, x_value, y_value[0]);
836 result->SetPointError(iPnt, 0, y_value[1]);
837 }
838 return result;
839 }
840 TGraphErrors *get_bkg_vs_vbias(std::string run, std::string channel, std::string type, std::string position = "center")
841 {
842 auto result = new TGraphErrors();
843 result->GetXaxis()->SetTitle("V_{bias} (V)");
844 result->GetYaxis()->SetTitle("DCR (Hz)");
845 auto all_sub_runs_data = get_sub_runs(run, type, channel);
846 for (auto [current_sub_run, all_informations] : all_sub_runs_data)
847 {
848 if (all_informations["notes"][0] != position)
849 continue;
850 auto iPnt = result->GetN();
851 auto x_value = std::stod(all_informations["vbias"][0]);
852 auto y_value = get_sub_run_bkg(run, current_sub_run, channel, type);
853 result->SetPoint(iPnt, x_value, y_value[0]);
854 result->SetPointError(iPnt, 0, y_value[1]);
855 }
856 return result;
857 }
858 TGraphErrors *get_pPDE_vs_bkg(std::string run, std::string channel, std::string type, std::string position = "center")
859 {
860 auto result = new TGraphErrors();
861 result->GetXaxis()->SetTitle("DCR (Hz)");
862 result->GetYaxis()->SetTitle("Pseudo-efficiency (%)");
863 auto all_sub_runs_data = get_sub_runs(run, type, channel);
864 for (auto [current_sub_run, all_informations] : all_sub_runs_data)
865 {
866 if (all_informations["notes"][0] != position)
867 continue;
868 auto iPnt = result->GetN();
869 auto x_value = get_sub_run_bkg(run, current_sub_run, channel, type);
870 auto y_value = get_sub_run_sig(run, current_sub_run, channel, type);
871 result->SetPoint(iPnt, x_value[0], y_value[0]);
872 result->SetPointError(iPnt, x_value[1], y_value[1]);
873 }
874 return result;
875 }
876 TGraphErrors *get_pPDE_merit_vs_vbias(std::string run, std::string channel, std::string type, std::string position = "center")
877 {
878 auto result = new TGraphErrors();
879 result->GetXaxis()->SetTitle("V_{bias} (V)");
880 result->GetYaxis()->SetTitle("Pseudo-efficiency figure of merit (%)");
881 auto all_sub_runs_data = get_sub_runs(run, type, channel);
882 for (auto [current_sub_run, all_informations] : all_sub_runs_data)
883 {
884 if (all_informations["notes"][0] != position)
885 continue;
886 auto iPnt = result->GetN();
887 auto x_value = std::stod(all_informations["vbias"][0]);
888 auto dcr_value = get_sub_run_bkg(run, current_sub_run, channel, type);
889 auto pde_value = get_sub_run_sig(run, current_sub_run, channel, type);
890 auto y_value_val = pde_value[0] / dcr_value[0];
891 auto y_value_err = y_value_val * std::sqrt((pde_value[1] / pde_value[0]) * (pde_value[1] / pde_value[0]) + (dcr_value[1] / dcr_value[0]) * (dcr_value[1] / dcr_value[0]));
892 std::array<float, 2> y_value = {y_value_val, y_value_err};
893 result->SetPoint(iPnt, x_value, y_value[0]);
894 result->SetPointError(iPnt, 0, y_value[1]);
895 }
896 return result;
897 }
898
899 std::array<float, 2>
900 get_pPDE_at_overvoltage(std::string run, std::string type, std::string channel, float overvoltage)
901 {
902 return database::get_value_at_overvoltage<database::laser::get_pPDE_vs_vbias>(run, type, channel, overvoltage);
903 }
904 std::array<float, 2>
905 get_bkg_at_overvoltage(std::string run, std::string type, std::string channel, float overvoltage)
906 {
907 return database::get_value_at_overvoltage<database::laser::get_bkg_vs_vbias>(run, type, channel, overvoltage);
908 }
909
910 std::vector<TGraphErrors *>
911 get_general_TGraphs_pPDE(std::string sensor, std::vector<std::pair<std::string, std::vector<std::string>>> target_list_w_runs, float overvoltage, int marker = kFullCircle, int color = kBlue)
912 {
913 return get_general_TGraphs<float, get_pPDE_at_overvoltage>(sensor, target_list_w_runs, overvoltage, marker, color);
914 }
915 std::vector<TGraphErrors *>
916 get_general_TGraphs_bkg(std::string sensor, std::vector<std::pair<std::string, std::vector<std::string>>> target_list_w_runs, float overvoltage, int marker = kFullCircle, int color = kBlue)
917 {
918 return get_general_TGraphs<float, get_bkg_at_overvoltage>(sensor, target_list_w_runs, overvoltage, marker, color);
919 }
920 }
921 */
922}
Definition tree_database.h:6
TH2_Type * build_fine_tune_raw_histogram(std::vector< TString > kInputFileNames, TString kRunTag, TString kOutputFileName, bool kRecalculate)
Functions -------------------------------------------------------------------------------------------...
Definition fine_analysis.h:80
std::unordered_map< std::string, std::vector< std::string > > get_sub_run_infos(std::string sub_run)
Definition database_laser.C:248
tree_database database
Definition database_laser.C:19
std::map< std::string, TGraphErrors * > get_stability_check(std::vector< std::string > run_list)
Definition database_laser.C:502
std::vector< std::string > fields
Definition database_laser.C:16
std::array< std::array< float, 2 >, 2 > get_sub_run_value(std::string sub_run)
Definition database_laser.C:315
void download_run(std::string campaign, std::string target_run_tag=".")
Definition database_laser.C:190
void read_all_sub_runs()
Definition database_laser.C:183
std::string basedir
Definition database_laser.C:24
std::array< float, 2 > get_sub_run_bkg(std::string sub_run)
Definition database_laser.C:54
std::map< std::string, TGraphErrors * > get_graph_sensor_from_channel(std::string run, std::string sensor, std::string type, std::string position, TGraphErrors *(*graph_getter)(std::string, std::string, std::string, std::string))
Definition database_laser.C:307
void show_stability_check(std::vector< std::string > run_list)
Definition database_laser.C:535
std::unordered_map< std::string, std::unordered_map< std::string, std::vector< std::string > > > get_sub_runs_infos(std::string run, std::string channel, std::string vbias, std::string type, std::string position)
Definition database_laser.C:285
const double coarse_to_ns
Definition database_laser.C:13
void read_database(std::string database_input_file)
Definition database_laser.C:68
std::vector< std::pair< int, std::string > > get_all_laser_runs()
Definition database_laser.C:43
std::array< float, 2 > get_sub_run_sig(std::string sub_run)
Definition database_laser.C:53
std::vector< std::string > sub_run_fields
Definition database_laser.C:17
std::unordered_map< std::string, std::vector< std::string > > get_run_infos(std::string run)
Definition database_laser.C:240
std::map< std::string, TGraphErrors * > get_sensor_bkg_vs_vbias(std::string run, std::string sensor, std::string type, std::string position)
Definition database_laser.C:59
void read_sub_run_database(std::string database_input_file, std::string type="target")
Definition database_laser.C:116
std::vector< std::string > laser_positions
Definition database_laser.C:22
std::map< std::string, TGraphErrors * > get_sensor_pPDE_vs_bkg(std::string run, std::string sensor, std::string type, std::string position)
Definition database_laser.C:60
TGraphErrors * get_bkg_vs_vbias(std::string run, std::string channel, std::string type, std::string position)
Definition database_laser.C:410
TGraphErrors * get_pPDE_vs_vbias(std::string run, std::string channel, std::string type, std::string position)
Definition database_laser.C:364
std::unordered_map< int, std::vector< std::string > > info_database
Definition database_laser.C:20
TGraphErrors * get_pPDE_vs_bkg(std::string run, std::string channel, std::string type, std::string position)
Definition database_laser.C:456
void unzip_all_sub_runs(std::string target_run_tag)
Definition database_laser.C:215
void unzip_sub_run(std::string target_file, std::string target_dir=".", std::string campaign="2024-laser-window")
Definition database_laser.C:207
std::pair< int, std::string > get_latest_laser_run(std::string board, std::string step)
Definition database_laser.C:277
std::map< std::string, TGraphErrors * > get_sensor_pPDE_vs_vbias(std::string run, std::string sensor, std::string type, std::string position)
Definition database_laser.C:58
void update_local_data_repository(std::string current_campaign="2024-laser-window")
Definition database_laser.C:224
Definition database.C:26
std::unordered_map< std::string, std::vector< std::string > > sensor_to_channels
Definition database.C:93
std::map< std::string, TGraphErrors * > average_graphs(std::vector< TGraphErrors * > graphs_list)
Definition graphutils.C:171
std::map< std::string, TGraphErrors * > average_same_x(TGraphErrors *target_graph)
Definition graphutils.C:125
std::vector< std::string > get_folders(const std::string &dir_path)
Definition general_utility.h:85