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