GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TGRSIint.cxx
Go to the documentation of this file.
1#include "TGRSIint.h"
2
3#include "GRootGuiFactory.h"
4#include "GVersion.h"
5#include "Getline.h"
6#include "Globals.h"
7#include "TDataParser.h"
8#include "TGRSIOptions.h"
9#include "TGRSIUtilities.h"
10#include "GValue.h"
11#include "TROOT.h"
12#include "GCanvas.h"
13
14#include "StoppableThread.h"
15#include "TAnalysisHistLoop.h"
16#include "TAnalysisWriteLoop.h"
17#include "TDataLoop.h"
18#include "TDetBuildingLoop.h"
19#include "TEventBuildingLoop.h"
20#include "TFragHistLoop.h"
21#include "TFragWriteLoop.h"
22#include "TFragmentChainLoop.h"
23#include "TTerminalLoop.h"
24#include "TUnpackingLoop.h"
25#include "TPPG.h"
26#include "TSortingDiagnostics.h"
27#include "TParserLibrary.h"
28
29#include "GRootCommands.h"
30#include "TRunInfo.h"
31
32#include "TInterpreter.h"
33#include "TGHtmlBrowser.h"
34//#include <pstream.h>
35
36#include <thread>
37#include <utility>
38
39#include <pwd.h>
40
41extern void PopupLogo(bool);
42extern void WaitLogo();
43
45
46TEnv* TGRSIint::fGRSIEnv = nullptr;
47
48void ReadTheNews();
49
50TChain* gFragment = nullptr;
51TChain* gAnalysis = nullptr;
52
53TGRSIint* TGRSIint::instance(int argc, char** argv, void*, int, bool, const char* appClassName)
54{
55 /// Singleton constructor instance
56 if(fTGRSIint == nullptr) {
57 fTGRSIint = new TGRSIint(argc, argv, nullptr, 0, true, appClassName);
59 }
60 return fTGRSIint;
61}
62
63TGRSIint::TGRSIint(int argc, char** argv, void*, int, bool noLogo, const char* appClassName)
64 : TRint(appClassName, new int(0), argv, nullptr, 0, noLogo), fKeepAliveTimer(nullptr),
65 main_thread_id(std::this_thread::get_id()), fIsTabComplete(false), fAllowedToTerminate(true), fRootFilesOpened(0),
66 fRawFilesOpened(0)
67{
68 /// Singleton constructor
69 fGRSIEnv = gEnv;
70
71 GetSignalHandler()->Remove();
72 auto* interruptHandler = new TGRSIInterruptHandler();
73 interruptHandler->Add();
74
75 try {
76 TGRSIOptions* opt = TGRSIOptions::Get(argc, argv);
77 if(opt->ShouldExit()) {
78 exit(0);
79 }
80 } catch(ParseError& e) {
81 exit(1);
82 }
83
84 PrintLogo(TGRSIOptions::Get()->ShowLogo());
85 SetPrompt("GRSI [%d] ");
86 std::string grsipath = getenv("GRSISYS");
87 gInterpreter->AddIncludePath(Form("%s/include", grsipath.c_str()));
88}
89
91{
92 /// Applies options from TGRSIOptions. This include things such as batch sorting,
93 /// reading material, and logo. Also includes the setup of what to do with mid
94 /// and root files that are input.
96
97 if(opt->Batch()) {
98 MakeBatch();
99 }
100
101 bool missing_raw_file = !AllFilesExist(opt->InputFiles());
102
104
105 if(opt->ReadingMaterial()) {
106 std::thread fnews = std::thread(ReadTheNews);
107 fnews.detach();
108 }
109
110 ////////////////////////////////////////////////////////
111 ////////////////////////////////////////////////////////
112 ////// Start of redoing section ///////
113 ////////////////////////////////////////////////////////
114 ////////////////////////////////////////////////////////
115
116 // load parser library if provided
117 if(!opt->ParserLibrary().empty()) {
118 try {
120 } catch(std::runtime_error& e) {
121 // if we failed to load the library, try to continue w/o it
122 std::cerr << DRED << e.what() << RESET_COLOR << std::endl;
123 }
124 }
125
127 TRunInfo::SetVersion(GRSI_RELEASE);
128
130 TRunInfo::SetFullVersion(GRSI_GIT_COMMIT);
131
133 TRunInfo::SetDate(GRSI_GIT_COMMIT_TIME);
134
135 for(const auto& rawFile : opt->InputFiles()) {
136 OpenRawFile(rawFile);
137 }
138
139 for(const auto& filename : opt->RootInputFiles()) {
140 // this will populate gChain if able.
141 // TChannels from the root file will be loaded as file is opened.
142 // GValues from the root file will be loaded as file is opened.
143 OpenRootFile(filename);
144 }
145
147
148 if(opt->StartGui()) {
149 StartGUI();
150 }
151
152 for(const auto& filename : opt->MacroInputFiles()) {
153 RunMacroFile(filename);
154 }
155
156 std::cout << StoppableThread::AllThreadHeader() << std::endl;
158 if(opt->CloseAfterSort()) {
159 int exit_status = missing_raw_file ? 1 : 0;
160 Terminate(exit_status);
161 }
162}
163
165{
166 /// Outputs the thread status until all of the threads are complete.
167 int iter = 0;
169 std::this_thread::sleep_for(std::chrono::seconds(1));
170
171 // We need to process events in case a different thread is asking for a file to be opened.
172 // However, if there is no stdin, ProcessEvents() will call Terminate().
173 // This prevents the terminate from taking effect while in this context.
174 fAllowedToTerminate = false;
175 gSystem->ProcessEvents();
176 fAllowedToTerminate = true;
177
178 ++iter;
179 if(TGRSIOptions::Get()->StatusInterval() > 0 && iter % TGRSIOptions::Get()->StatusInterval() == 0) {
180 std::cout << "\r" << StoppableThread::AllThreadStatus() << std::endl;
181 }
182 std::cout << "\r" << StoppableThread::AllThreadProgress() << std::flush;
183 }
184 std::cout << std::endl;
185}
186
188{
189 /// Handles terminal input via TRint
190 return TRint::HandleTermInput();
191}
192
193void TGRSIint::Terminate(Int_t status)
194{
195 /// Kills all of the threads if the process is allowed to terminate. This
196 /// sends an error to TSortingDiagnostics if an analysis tree is being created
198 std::cout << "Not allowed to terminate, sorry!" << std::endl;
199 return;
200 }
201
205
206 if(TGRSIOptions::Get()->MakeAnalysisTree()) {
208 }
209
210 if((clock() % 60) == 0) {
211 std::cout << "DING!" << std::flush;
212 gSystem->Sleep(500); // 500 ms
213 std::cout << "\r \r" << std::flush;
214 }
215
216 TSeqCollection* canvases = gROOT->GetListOfCanvases();
217 while(canvases->GetEntries() > 0) {
218 static_cast<GCanvas*>(canvases->At(0))->Close();
219 }
220
221 // TChannel::DeleteAllChannels();
222 TRint::Terminate(status);
223}
224
225Int_t TGRSIint::TabCompletionHook(char* buf, int* pLoc, std::ostream& out)
226{
227 /// Tries to do a tab completion. Returns false if unsuccsessful
228 fIsTabComplete = true;
229 auto result = TRint::TabCompletionHook(buf, pLoc, out);
230 fIsTabComplete = false;
231 return result;
232}
233
234Long_t TGRSIint::ProcessLine(const char* inputLine, Bool_t sync, Int_t* error)
235{
236 /// This takes over the native root command line. There are two main reasons for this
237 /// 1. To keep the command line thread-safe.
238 /// 2. To block TCanvas from opening, and to instead use our GCanvas.
239
240 // If you print while fIsTabComplete is true, you will break tab complete.
241 // Any diagnostic print statements should be done after this if statement.
242 if(fIsTabComplete) {
243 Long_t res = TRint::ProcessLine(inputLine, sync, error);
244 return res;
245 }
246
247 // loop over the input line and replace all instances of "TCanvas" with "GCanvas"
248 std::string line(inputLine);
249 size_t pos = 0;
250 while((pos = line.find("TCanvas", pos)) != std::string::npos) {
251 line[pos] = 'G';
252 }
253
254 if(std::this_thread::get_id() != main_thread_id) {
255 return DelayedProcessLine(line);
256 }
257
258 return TRint::ProcessLine(line.c_str(), sync, error);
259}
260
262{
263 /// Opens a random wikipedia page for your enjoyment
264#ifdef __APPLE__
265 gROOT->ProcessLine(".! open http://en.wikipedia.org/wiki/Special:Random > /dev/null 2>&1;");
266#else
267 gROOT->ProcessLine(".! xdg-open http://en.wikipedia.org/wiki/Special:Random > /dev/null 2>&1;");
268#endif
269}
270
271void TGRSIint::PrintLogo(bool print)
272{
273 /// Prints the GRSISort logo to terminal
274 if(print) {
275#ifdef LINUX
276 const std::string& ref = ProgramName();
277 const unsigned int reflength = ref.length() - 78;
278#else
279 const std::string& ref = "Sorting Program for Online and Offline Nuclear Data";
280 const unsigned int reflength = 53;
281#endif
282
283 const unsigned int width = reflength + (reflength % 2);
284 printf("\t*%s*\n", std::string(width, '*').c_str());
285 printf("\t*%*s%*s*\n", width / 2 + 4, "GRSI Sort", width / 2 - 4, "");
286 printf("\t*%*s%*s*\n", width / 2 + 12, "a remake of GRSI SPOON", width / 2 - 12, "");
287 printf("\t*%*s%*s*\n", width / 2 + reflength / 2, ref.c_str(), width / 2 - reflength / 2, "");
288 printf("\t*%*s%*s*\n", width / 2 + 14, "A lean, mean sorting machine", width / 2 - 14, "");
289 printf("\t*%*s%*s*\n", width / 2 + 9, "version " GRSI_RELEASE, width / 2 - 9, "");
290 printf("\t*%s*\n", std::string(width, '*').c_str());
291
292 std::thread drawlogo(&TGRSIint::DrawLogo); //, this);
293 drawlogo.detach();
294 } else {
295 std::cout << "\tgrsisort version " << GRSI_RELEASE << std::endl;
296 }
297}
298
299TFile* TGRSIint::OpenRootFile(const std::string& filename, Option_t* opt)
300{
301 /// Opens root files provided on the command line. Also tells you where these files
302 /// are stored (ie _file0). If these files are analysis or fragment trees, they are
303 /// automatically chained into chains called gFragment and gAnalysis. Once this is
304 /// complete, the TChannels, GValues and RunInfo are also read in.
305 TString sopt(opt);
306 sopt.ToLower();
307
308 TFile* file = nullptr;
309 if(sopt.Contains("recreate") || sopt.Contains("new")) {
310 // We are being asked to make a new file.
311 file = new TFile(filename.c_str(), "RECREATE");
312 if(file != nullptr && file->IsOpen()) {
313 // Give access to the file inside the interpreter.
314 const char* command = Form("TFile* _file%i = (TFile*)%luL;", fRootFilesOpened, reinterpret_cast<unsigned long>(file));
315 TRint::ProcessLine(command);
317 } else {
318 std::cout << "Could not create " << filename << std::endl;
319 }
320 } else {
321 // Open an already existing file.
322 file = new TFile(filename.c_str(), opt);
323 if(file != nullptr && file->IsOpen()) {
324 // Give access to the file inside the interpreter.
325 const char* command = Form("TFile* _file%i = (TFile*)%luL;", fRootFilesOpened, reinterpret_cast<unsigned long>(file));
326 TRint::ProcessLine(command);
327 std::cout << "\tfile " << BLUE << file->GetName() << RESET_COLOR << " opened as " << BLUE << "_file"
328 << fRootFilesOpened << RESET_COLOR << std::endl;
329
330 // If FragmentTree exists, add the file to the chain.
331 if(file->FindObjectAny("FragmentTree") != nullptr) {
332 if(gFragment == nullptr) {
333 // TODO: Once we have a notifier set up
334 gFragment = new TChain("FragmentChain");
335 // gFragment->SetNotify(GrutNotifier::Get());
336 }
337 std::cout << "file " << file->GetName() << " added to gFragment." << std::endl;
338 gFragment->AddFile(file->GetName(), TTree::kMaxEntries, "FragmentTree");
339 }
340
341 // If AnalysisTree exists, add the file to the chain.
342 if(file->FindObjectAny("AnalysisTree") != nullptr) {
343 if(gAnalysis == nullptr) {
344 gAnalysis = new TChain("AnalysisChain");
345 // TODO: Once we have a notifier set up
346 // gAnalysis->SetNotify(GrutNotifier::Get());
347 }
348 std::cout << "file " << file->GetName() << " added to gAnalysis." << std::endl;
349 gAnalysis->AddFile(file->GetName(), TTree::kMaxEntries, "AnalysisTree");
350 }
351
352 if(file->FindObjectAny("Channel") != nullptr) {
353 // not necessary to do anything as FindObjectAny already seems to call the streamer?
354 // file->Get("Channel"); // this calls TChannel::Streamer
355 }
356 if(file->FindObjectAny("Values") != nullptr) {
357 file->Get("Values");
358 }
360 } else {
361 std::cout << "Could not open " << filename << std::endl;
362 }
363 }
364
365 AddFileToGUI(file);
367
368 return file;
369}
370
371TRawFile* TGRSIint::OpenRawFile(const std::string& filename)
372{
373 /// Opens Raw input file and stores them in _raw if successfuly opened.
374 if(!FileExists(filename.c_str())) {
375 std::cerr << R"(File ")" << filename << R"(" does not exist)" << std::endl;
376 return nullptr;
377 }
378
379 // create new raw file
380 try {
381 auto* file = TParserLibrary::Get()->CreateRawFile(filename);
382 fRawFiles.push_back(file);
383
384 if(file != nullptr) {
385 const char* command = Form("TRawFile* _raw%i = (TRawFile*)%luL;", fRawFilesOpened, reinterpret_cast<unsigned long>(file));
386 ProcessLine(command);
387
388 std::cout << "\tfile " << BLUE << filename << RESET_COLOR << " opened as "
389 << BLUE << "_raw" << fRawFilesOpened << RESET_COLOR << std::endl;
390 }
392 return file;
393 } catch(std::runtime_error& e) {
394 std::cout << e.what();
395 }
396 return nullptr;
397}
398
400{
401 /// Finds all of the files input as well as flags provided and makes all
402 /// of the decisions about what to sort and what order to open everything up
403 /// in. This also creates the output files. Starts the threads and gets the
404 /// sorting going. This is really the brains of the command line sorting routine.
406
407 // Determining which parts of the pipeline need to be set up.
408
409 bool missing_raw_file = false;
410 for(const auto& filename : opt->InputFiles()) {
411 if(!FileExists(filename.c_str())) {
412 missing_raw_file = true;
413 std::cerr << "File not found: " << filename << std::endl;
414 }
415 }
416
417 // Which input files do we have
418 bool has_raw_file = !opt->InputFiles().empty() && opt->SortRaw() && !missing_raw_file && !fRawFiles.empty();
419 bool has_input_fragment_tree = gFragment != nullptr; // && opt->SortRoot();
420 bool has_input_analysis_tree = gAnalysis != nullptr; // && opt->SortRoot();
421
422 // Which output files are could possibly be made
423 bool able_to_write_fragment_histograms =
424 ((has_raw_file || has_input_fragment_tree) && opt->FragmentHistogramLib().length() > 0);
425 bool able_to_write_fragment_tree = (has_raw_file && !missing_raw_file);
426 bool able_to_write_analysis_histograms = ((has_raw_file || has_input_fragment_tree || has_input_analysis_tree) &&
427 opt->AnalysisHistogramLib().length() > 0);
428 bool able_to_write_analysis_tree = (able_to_write_fragment_tree || has_input_fragment_tree);
429
430 // Which output files will we make
431 bool write_fragment_histograms = (able_to_write_fragment_histograms && opt->MakeHistos());
432 bool write_fragment_tree = able_to_write_fragment_tree && opt->WriteFragmentTree();
433 bool write_analysis_histograms =
434 (able_to_write_analysis_histograms && opt->MakeHistos()); // TODO: make it so we aren't always trying to generate both frag and analysis histograms
435 bool write_analysis_tree = (able_to_write_analysis_tree && opt->MakeAnalysisTree());
436
437 // Which steps need to be performed to get from the inputs to the outputs
438 bool self_stopping = opt->CloseAfterSort();
439
440 bool read_from_raw = (has_raw_file && (write_fragment_histograms || write_fragment_tree ||
441 write_analysis_histograms || write_analysis_tree));
442
443 bool read_from_fragment_tree =
444 (has_input_fragment_tree && (write_fragment_histograms || write_analysis_histograms || write_analysis_tree));
445
446 bool generate_analysis_data =
447 ((read_from_raw || read_from_fragment_tree) && (write_analysis_histograms || write_analysis_tree));
448
449 bool read_from_analysis_tree =
450 (has_input_analysis_tree && (write_analysis_histograms || write_analysis_tree) && !generate_analysis_data);
451
452 // Extract the run number and sub run number from whatever we were given
453 int run_number = 0;
454 int sub_run_number = 0;
455 if(read_from_raw) {
456 run_number = fRawFiles[0]->GetRunNumber();
457 sub_run_number = fRawFiles[0]->GetSubRunNumber();
458 } else if(read_from_fragment_tree) {
459 const auto* run_title = gFragment->GetListOfFiles()->At(0)->GetTitle();
460 run_number = GetRunNumber(run_title);
461 sub_run_number = GetSubRunNumber(run_title);
462 } else if(read_from_analysis_tree) {
463 const auto* run_title = gAnalysis->GetListOfFiles()->At(0)->GetTitle();
464 run_number = GetRunNumber(run_title);
465 sub_run_number = GetSubRunNumber(run_title);
466 }
467
468 // Choose output file names for the 4 possible output files
469 std::string output_fragment_tree_filename = opt->OutputFragmentFile();
470 if(output_fragment_tree_filename.length() == 0) {
471 if(sub_run_number == -1) {
472 output_fragment_tree_filename = Form("fragment%05i.root", run_number);
473 } else {
474 output_fragment_tree_filename = Form("fragment%05i_%03i.root", run_number, sub_run_number);
475 }
476 }
477
478 std::string output_fragment_hist_filename = opt->OutputFragmentHistogramFile();
479 if(output_fragment_hist_filename.length() == 0) {
480 if(sub_run_number == -1) {
481 output_fragment_hist_filename = Form("hist_fragment%05i.root", run_number);
482 } else {
483 output_fragment_hist_filename = Form("hist_fragment%05i_%03i.root", run_number, sub_run_number);
484 }
485 }
486
487 std::string output_analysis_tree_filename = opt->OutputAnalysisFile();
488 if(output_analysis_tree_filename.length() == 0) {
489 if(sub_run_number == -1) {
490 if(opt->UseRnTuple()) {
491 output_analysis_tree_filename = Form("rntuple%05i.root", run_number);
492 } else {
493 output_analysis_tree_filename = Form("analysis%05i.root", run_number);
494 }
495 } else {
496 if(opt->UseRnTuple()) {
497 output_analysis_tree_filename = Form("rntuple%05i_%03i.root", run_number, sub_run_number);
498 } else {
499 output_analysis_tree_filename = Form("analysis%05i_%03i.root", run_number, sub_run_number);
500 }
501 }
502 }
503
504 std::string output_analysis_hist_filename = opt->OutputAnalysisHistogramFile();
505 if(output_analysis_hist_filename.length() == 0) {
506 if(sub_run_number == -1) {
507 output_analysis_hist_filename = Form("hist_analysis%05i.root", run_number);
508 } else {
509 output_analysis_hist_filename = Form("hist_analysis%05i_%03i.root", run_number, sub_run_number);
510 }
511 }
512
513 if(read_from_analysis_tree) {
514 std::cerr << "Reading from analysis tree not currently supported" << std::endl;
515 }
516
517 ////////////////////////////////////////////////////
518 //////////// Setting up the loops ////////////////
519 ////////////////////////////////////////////////////
520
521 if(!write_fragment_histograms && !write_fragment_tree && !write_analysis_histograms && !write_analysis_tree) {
522 // We still might want to read the calibration, values, or run info files
523 for(const auto& cal_filename : opt->CalInputFiles()) {
524 TChannel::ReadCalFile(cal_filename.c_str());
525 }
526 for(const auto& val_filename : opt->ValInputFiles()) {
527 GValue::ReadValFile(val_filename.c_str());
528 }
529 for(const auto& info_filename : opt->ExternalRunInfo()) {
530 TRunInfo::ReadInfoFile(info_filename.c_str());
531 }
532 return;
533 }
534 // Set the width of the status and each column
537
538 // Different queues that can show up
539 std::vector<std::shared_ptr<ThreadsafeQueue<std::shared_ptr<const TFragment>>>> fragmentQueues;
540 std::vector<std::shared_ptr<ThreadsafeQueue<std::shared_ptr<TEpicsFrag>>>> scalerQueues;
541 std::vector<std::shared_ptr<ThreadsafeQueue<std::shared_ptr<TUnpackedEvent>>>> analysisQueues;
542
543 // The different loops that can run
544 TDataLoop* dataLoop = nullptr;
545 TUnpackingLoop* unpackLoop = nullptr;
546 TFragmentChainLoop* fragmentChainLoop = nullptr;
547 TEventBuildingLoop* eventBuildingLoop = nullptr;
548 TDetBuildingLoop* detBuildingLoop = nullptr;
549
550 // If needed, read from the raw file
551 if(read_from_raw) {
552 if(fRawFiles.size() > 1) {
553 std::cerr << "I'm going to ignore all but first .mid" << std::endl;
554 }
555
556 dataLoop = TDataLoop::Get("1_input_loop", fRawFiles[0]);
557 dataLoop->SetSelfStopping(self_stopping);
558
559 unpackLoop = TUnpackingLoop::Get("2_unpack_loop");
560 unpackLoop->InputQueue() = dataLoop->OutputQueue();
561 }
562
563 // If needed, read from the fragment tree
564 if(read_from_fragment_tree) {
565 fragmentChainLoop = TFragmentChainLoop::Get("1_chain_loop", gFragment);
566 fragmentChainLoop->SetSelfStopping(self_stopping);
567 }
568
569 // if I am passed any calibrations, lets load those, this
570 // will overwrite any with the same address previously read in.
571 for(const auto& cal_filename : opt->CalInputFiles()) {
572 TChannel::ReadCalFile(cal_filename.c_str());
573 }
574 // Set the run number and sub-run number
575 if(!fRawFiles.empty()) {
577 } else {
579 }
580
581 for(const auto& val_filename : opt->ValInputFiles()) {
582 GValue::ReadValFile(val_filename.c_str());
583 }
584 for(const auto& info_filename : opt->ExternalRunInfo()) {
585 TRunInfo::ReadInfoFile(info_filename.c_str());
586 }
587
589 if(TRunInfo::GetDetectorInformation() != nullptr) {
590 // call DetectorInformation::Set again, in case the calibration files we've loaded now changed things
592 event_build_mode = TRunInfo::GetDetectorInformation()->BuildMode();
593 } else {
594 std::cout << "no detector information, can't set build mode" << std::endl;
595 }
596
597 // If requested, write the fragment histograms
598 if(write_fragment_histograms) {
599 TFragHistLoop* loop = TFragHistLoop::Get("3_frag_hist_loop");
600 loop->SetOutputFilename(output_fragment_hist_filename);
601 if(unpackLoop != nullptr) {
602 loop->InputQueue() = unpackLoop->AddGoodOutputQueue();
603 }
604 if(fragmentChainLoop != nullptr) {
605 loop->InputQueue() = fragmentChainLoop->AddOutputQueue();
606 }
607 fragmentQueues.push_back(loop->InputQueue());
608 }
609
610 // If requested, write the fragment tree
611 if(write_fragment_tree) {
612 TFragWriteLoop* loop = TFragWriteLoop::Get("4_frag_write_loop", output_fragment_tree_filename);
613 fNewFragmentFile = output_fragment_tree_filename;
614 if(unpackLoop != nullptr) {
615 loop->InputQueue() = unpackLoop->AddGoodOutputQueue(TGRSIOptions::Get()->FragmentWriteQueueSize());
616 loop->BadInputQueue() = unpackLoop->BadOutputQueue();
617 loop->ScalerInputQueue() = unpackLoop->ScalerOutputQueue();
618 scalerQueues.push_back(loop->ScalerInputQueue());
619 }
620 if(fragmentChainLoop != nullptr) {
621 loop->InputQueue() = fragmentChainLoop->AddOutputQueue();
622 }
623 fragmentQueues.push_back(loop->InputQueue());
624 }
625
626 // If needed, generate the individual detectors from the TFragments
627 if(generate_analysis_data) {
629 eventBuildingLoop = TEventBuildingLoop::Get("5_event_build_loop", event_build_mode, TGRSIOptions::AnalysisOptions()->BuildWindow());
630 eventBuildingLoop->SetSortDepth(opt->SortDepth());
631 if(unpackLoop != nullptr) {
632 eventBuildingLoop->InputQueue() = unpackLoop->AddGoodOutputQueue();
633 }
634 if(fragmentChainLoop != nullptr) {
635 eventBuildingLoop->InputQueue() = fragmentChainLoop->AddOutputQueue();
636 }
637 fragmentQueues.push_back(eventBuildingLoop->InputQueue());
638
639 detBuildingLoop = TDetBuildingLoop::Get("6_det_build_loop");
640 detBuildingLoop->InputQueue() = eventBuildingLoop->OutputQueue();
641 }
642
643 // If requested, write the analysis histograms
644 if(write_analysis_histograms) {
645 TAnalysisHistLoop* loop = TAnalysisHistLoop::Get("7_analysis_hist_loop");
646 loop->SetOutputFilename(output_analysis_hist_filename);
647 if(detBuildingLoop != nullptr) { // TODO: This needs to be extended to being able to read from an analysis tree
648 loop->InputQueue() = detBuildingLoop->AddOutputQueue();
649 } else {
650 std::cerr << DRED << "Error, writing analysis histograms is enabled, but no detector building loop was found!"
651 << RESET_COLOR << std::endl;
652 exit(1);
653 }
654
655 analysisQueues.push_back(loop->InputQueue());
656 }
657
658 // If requested, write the analysis tree
659 if(write_analysis_tree) {
660 auto* loop = TAnalysisWriteLoop::Get("8_analysis_write_loop", output_analysis_tree_filename);
661 loop->InputQueue() = detBuildingLoop->AddOutputQueue(TGRSIOptions::Get()->AnalysisWriteQueueSize());
662 if(TGRSIOptions::Get()->SeparateOutOfOrder()) {
663 loop->OutOfOrderQueue() = eventBuildingLoop->OutOfOrderQueue();
664 }
665 analysisQueues.push_back(loop->InputQueue());
666 }
667
669}
670
671void TGRSIint::RunMacroFile(const std::string& filename)
672{
673 /// Runs a macro file. This happens when a .C file is provided on the command line
674 if(FileExists(filename.c_str())) {
675 const char* command = Form(".x %s", filename.c_str());
676 ProcessLine(command);
677 } else {
678 // check if commandline arguments were supplied
679 size_t beginning_pos = filename.find_first_of('(');
680 if(beginning_pos != std::string::npos && filename.back() == ')') {
681 std::string trueFilename = filename.substr(0, beginning_pos);
682 std::string arguments = filename.substr(beginning_pos, std::string::npos);
683 if(FileExists(trueFilename.c_str())) {
684 const char* command = Form(".L %s", trueFilename.c_str());
685 ProcessLine(command);
686 command = Form("%s%s", trueFilename.substr(0, filename.find_first_of('.')).c_str(), arguments.c_str());
687 ProcessLine(command);
688 } else {
689 std::cerr << R"(File ")" << trueFilename << R"(" does not exist)" << std::endl;
690 }
691 } else {
692 std::cerr << R"(File ")" << filename << R"(" does not exist)" << std::endl;
693 }
694 }
695}
696
698{
699 /// Draws the logo. Can be suppressed with -l
700 PopupLogo(false);
701 WaitLogo();
702}
703
705{
706 /// Loads root graphics in unless -b is used for batch mode.
707 if(gROOT->IsBatch()) {
708 return;
709 }
710 // force Canvas to load, this ensures global GUI Factory ptr exists.
711 gROOT->LoadClass("TCanvas", "Gpad");
712 gGuiFactory = new GRootGuiFactory();
713}
714
715void TGRSIint::PrintHelp(bool print)
716{
717 /// Prints the help. Not sure this is used anymore.
718 if(print) {
719 std::cout << DRED << BG_WHITE << " Sending Help!! " << RESET_COLOR << std::endl;
720 new TGHtmlBrowser(gSystem->ExpandPathName("${GRSISYS}/README.html"));
721 }
722}
723
725{
726 /// When ctrl-c is pressed, this takes over. This can be used in the future
727 /// for safe cleanup.
729 std::cout << std::endl
730 << DRED << BG_WHITE << " Control-c was pressed in interactive mode. " << RESET_COLOR << std::endl;
731 exit(1);
732 }
733 static int timesPressed = 0;
734 timesPressed++;
735 switch(timesPressed) {
736 case 1:
737 std::cout << std::endl
738 << DRED << BG_WHITE << " Control-c was pressed, terminating input loop. " << RESET_COLOR << std::endl;
740 break;
741 case 2:
742 std::cout << std::endl
743 << DRED << BG_WHITE << " Control-c was pressed, stopping all queues. " << RESET_COLOR << std::endl;
745 break;
746 default:
747 std::cout << std::endl
748 << DRED << BG_WHITE << " No you shutup! " << RESET_COLOR << std::endl;
749 exit(1);
750 }
751 return true;
752}
753
754// These variables are to be accessed only from DelayedProcessLine
755// and DelayedProcessLine_Action, nowhere else.
756// These are used to pass information between the two functions.
757// DelayedProcessLine_Action() should ONLY be called from a TTimer running
758// on the main thread. DelayedProcessLine may ONLY be called
759// from inside ProcessLine().
760namespace {
764std::condition_variable g__NewResult;
765
768
771} // namespace
772
773Long_t TGRSIint::DelayedProcessLine(std::string command)
774{
775 std::lock_guard<std::mutex> any_command_lock(g__CommandWaitingMutex);
776
777 g__LineToProcess = std::move(command);
778 g__CommandFinished = false;
779 g__ProcessingNeeded = true;
780 TTimer::SingleShot(0, "TGRSIint", this, "DelayedProcessLine_Action()");
781
782 std::unique_lock<std::mutex> lock(g__ResultListMutex);
783 while(!g__CommandFinished) {
784 g__NewResult.wait(lock);
785 }
786
787 return g__CommandResult;
788}
789
791{
792 std::string message;
793 {
794 std::lock_guard<std::mutex> lock(g__CommandListMutex);
795 if(!g__ProcessingNeeded) {
796 return;
797 }
798 message = g__LineToProcess;
799 }
800
801 Long_t result = ProcessLine(message.c_str());
802 Getlinem(EGetLineMode::kInit, (static_cast<TRint*>(gApplication))->GetPrompt());
803
804 {
805 std::lock_guard<std::mutex> lock(g__ResultListMutex);
806 g__CommandResult = result;
807 g__CommandFinished = true;
808 g__ProcessingNeeded = false;
809 }
810
811 g__NewResult.notify_one();
812}
void AddFileToGUI(TFile *file)
void StartGUI()
#define BG_WHITE
Definition Globals.h:24
#define DRED
Definition Globals.h:18
#define BLUE
Definition Globals.h:6
#define RESET_COLOR
Definition Globals.h:5
const std::string & ProgramName()
int GetRunNumber(const std::string &)
bool FileExists(const char *filename)
bool AllFilesExist(const std::vector< std::string > &filenames)
int GetSubRunNumber(const std::string &)
void PopupLogo(bool)
Definition grsixx.cxx:289
void WaitLogo()
Definition grsixx.cxx:376
void ReadTheNews()
Definition TGRSIint.cxx:261
static int ReadValFile(const char *filename="", Option_t *opt="replace")
Definition GValue.cxx:194
static void StopAll()
static void ClearAllQueues()
static std::string AllThreadStatus()
static size_t StatusWidth()
static std::string AllThreadProgress()
static std::string AllThreadHeader()
static bool AnyThreadRunning()
static void SendStop()
static void ResumeAll()
static size_t ColumnWidth()
void SetOutputFilename(const std::string &name)
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TUnpackedEvent > > > & InputQueue()
static TAnalysisHistLoop * Get(std::string name="")
void Print(Option_t *opt="") const override
static TAnalysisWriteLoop * Get(std::string name="", std::string outputFilename="")
static Int_t ReadCalFile(std::ifstream &infile)
static TDataLoop * Get(std::string name="", TRawFile *source=nullptr)
Definition TDataLoop.cxx:21
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TRawEvent > > > & OutputQueue()
Definition TDataLoop.h:42
void SetSelfStopping(bool self_stopping)
Definition TDataLoop.h:65
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TUnpackedEvent > > > & AddOutputQueue(size_t maxSize=50000)
std::shared_ptr< ThreadsafeQueue< std::vector< std::shared_ptr< const TFragment > > > > & InputQueue()
static TDetBuildingLoop * Get(std::string name="")
virtual TEventBuildingLoop::EBuildMode BuildMode() const
Set the detector information based on the available TChannels.
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & OutOfOrderQueue()
std::shared_ptr< ThreadsafeQueue< std::vector< std::shared_ptr< const TFragment > > > > & OutputQueue()
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & InputQueue()
static TEventBuildingLoop * Get(std::string name="", EBuildMode mode=EBuildMode::kTimestamp, uint64_t buildWindow=2000)
void SetSortDepth(unsigned int val)
static TFragHistLoop * Get(std::string name="")
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & InputQueue()
void SetOutputFilename(const std::string &name)
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TBadFragment > > > & BadInputQueue()
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & InputQueue()
static TFragWriteLoop * Get(std::string name="", std::string fOutputFilename="")
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TEpicsFrag > > > & ScalerInputQueue()
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & AddOutputQueue()
void SetSelfStopping(bool self_stopping)
static TFragmentChainLoop * Get(std::string name="", TChain *chain=nullptr)
bool Notify() override
Definition TGRSIint.cxx:724
const std::vector< std::string > & RootInputFiles() const
bool MakeAnalysisTree() const
bool SortRaw() const
static TGRSIOptions * Get(int argc=0, char **argv=nullptr)
Do not use!
bool WriteFragmentTree() const
const std::vector< std::string > & InputFiles() const
const std::string & OutputFragmentHistogramFile() const
const std::vector< std::string > & ExternalRunInfo() const
std::string AnalysisHistogramLib() const
const std::string & OutputAnalysisHistogramFile() const
static TAnalysisOptions * AnalysisOptions()
const std::vector< std::string > & ValInputFiles() const
bool StartGui() const
int SortDepth() const
bool Batch() const
bool CloseAfterSort() const
bool MakeHistos() const
bool UseRnTuple() const
bool ShouldExit() const
const std::vector< std::string > & CalInputFiles() const
bool ReadingMaterial() const
void ParserLibrary(std::string &library)
const std::vector< std::string > & MacroInputFiles() const
std::string FragmentHistogramLib() const
const std::string & OutputFragmentFile() const
const std::string & OutputAnalysisFile() const
void SetupPipeline()
Definition TGRSIint.cxx:399
TRawFile * OpenRawFile(const std::string &filename)
Definition TGRSIint.cxx:371
int TabCompletionHook(char *, int *, std::ostream &) override
Definition TGRSIint.cxx:225
static void PrintHelp(bool)
Definition TGRSIint.cxx:715
int fRawFilesOpened
Number of Raw Files opened.
Definition TGRSIint.h:96
Long_t DelayedProcessLine(std::string command)
Definition TGRSIint.cxx:773
std::thread::id main_thread_id
Main sorting thread id.
Definition TGRSIint.h:90
TGRSIint(int argc, char **argv, void *options=nullptr, int numOptions=0, bool noLogo=false, const char *appClassName="grsisort")
Definition TGRSIint.cxx:63
static TGRSIint * fTGRSIint
Static pointer (singleton)
Definition TGRSIint.h:51
TFile * OpenRootFile(const std::string &filename, Option_t *opt="read")
Definition TGRSIint.cxx:299
static void DrawLogo()
Definition TGRSIint.cxx:697
std::vector< TRawFile * > fRawFiles
List of Raw files opened.
Definition TGRSIint.h:99
static void LoadGROOTGraphics()
Definition TGRSIint.cxx:704
void DelayedProcessLine_Action()
Definition TGRSIint.cxx:790
std::string fNewFragmentFile
New fragment file name.
Definition TGRSIint.h:97
void RunMacroFile(const std::string &filename)
Definition TGRSIint.cxx:671
bool fAllowedToTerminate
Flag for shutting down GRSISort.
Definition TGRSIint.h:94
static TGRSIint * instance(int argc=0, char **argv=nullptr, void *options=nullptr, int numOptions=-1, bool noLogo=false, const char *appClassName="grsisort")
Definition TGRSIint.cxx:53
bool fIsTabComplete
Flag for tab completion hook.
Definition TGRSIint.h:93
int fRootFilesOpened
Number of ROOT files opened.
Definition TGRSIint.h:95
void LoopUntilDone()
Definition TGRSIint.cxx:164
static TEnv * fGRSIEnv
GRSI environment.
Definition TGRSIint.h:48
void PrintLogo(bool) override
Definition TGRSIint.cxx:271
Long_t ProcessLine(const char *line, Bool_t sync=kFALSE, Int_t *error=nullptr) override
Definition TGRSIint.cxx:234
void Terminate(Int_t status=0) override
Definition TGRSIint.cxx:193
void ApplyOptions()
Definition TGRSIint.cxx:90
bool HandleTermInput() override
Definition TGRSIint.cxx:187
void Load()
if necessary loads shared object library and sets/initializes all other functions
TRawFile * CreateRawFile(const std::string &file)
Reader for raw files.
Definition TRawFile.h:31
static void ClearVersion()
Definition TRunInfo.h:136
static void SetDate(const char *ver)
Definition TRunInfo.h:161
static void SetFullVersion(const char *ver)
Definition TRunInfo.h:149
static Bool_t ReadInfoFile(const char *filename="")
Definition TRunInfo.cxx:174
static void ClearFullVersion()
Definition TRunInfo.h:148
static void ClearDate()
Definition TRunInfo.h:160
static void SetRunInfo(int runnum=0, int subrunnum=-1)
Definition TRunInfo.cxx:135
static void SetVersion(const char *ver)
Definition TRunInfo.h:137
static Bool_t ReadInfoFromFile(TFile *tempf=nullptr)
Definition TRunInfo.cxx:15
static TDetectorInformation * GetDetectorInformation()
Definition TRunInfo.h:272
static TParserLibrary * Get(bool verbose=false)
Definition TSingleton.h:33
void Print(Option_t *opt="") const override
static TUnpackingLoop * Get(std::string name="")
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TFragment > > > & AddGoodOutputQueue(size_t maxSize=50000)
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TRawEvent > > > & InputQueue()
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< TEpicsFrag > > > & ScalerOutputQueue()
std::shared_ptr< ThreadsafeQueue< std::shared_ptr< const TBadFragment > > > & BadOutputQueue()
TChain * gAnalysis
Definition TGRSIint.cxx:51
TChain * gFragment
Definition TGRSIint.cxx:50
void PopupLogo(bool about)
Definition grsixx.cxx:289
void WaitLogo()
Definition grsixx.cxx:376
std::condition_variable g__NewResult
Definition TGRSIint.cxx:764