Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaAnalyzer.cxx
Go to the documentation of this file.
1//*-- Author : Ole Hansen 12-May-2000
2
4//
5// THaAnalyzer
6//
7// THaAnalyzer is the base class for a "Hall A analyzer" class.
8// An analyzer defines the basic actions to perform during analysis.
9// THaAnalyzer is the default analyzer that is used if no user class is
10// defined. It performs a standard analysis consisting of
11//
12// 1. Decoding/Calibrating
13// 2. Track Reconstruction
14// 3. Physics variable processing
15//
16// At the end of each step, testing and histogramming are done for
17// the appropriate block defined in the global test/histogram lists.
18//
20
21#include "THaAnalyzer.h"
22#include "THaRunBase.h"
23#include "THaEvent.h"
24#include "THaOutput.h"
25#include "THaEvData.h"
26#include "THaGlobals.h"
27#include "THaSpectrometer.h"
28#include "THaCutList.h"
29#include "THaPhysicsModule.h"
30#include "InterStageModule.h"
31#include "THaPostProcess.h"
32#include "THaBenchmark.h"
33#include "THaEvtTypeHandler.h"
34#include "THaEpicsEvtHandler.h"
35#include "TList.h"
36#include "TTree.h"
37#include "TFile.h"
38#include "TDatime.h"
39#include "TError.h"
40#include "TClass.h"
41#include "TSystem.h"
42#include "TROOT.h"
43#include "TDirectory.h"
44#include "THaCrateMap.h"
45#include "Helper.h"
46
47#include <iostream>
48#include <iomanip>
49#include <exception>
50#include <stdexcept>
51#include <algorithm>
52#include <vector>
53
54using namespace std;
55using namespace Decoder;
56using namespace Podd;
57
58const char* const THaAnalyzer::kMasterCutName = "master";
59const char* const THaAnalyzer::kDefaultOdefFile = "output.def";
60
61// Pointer to single instance of this object
63
64//FIXME:
65// do we need to "close" scalers/EPICS analysis if we reach the event limit?
66
67//_____________________________________________________________________________
68// Convert from type-unsafe ROOT containers to STL vectors
69template<typename T>
70inline size_t ListToVector( TList* lst, vector<T*>& vec )
71{
72 if( lst ) {
73 vec.reserve(std::max(lst->GetSize(), 0));
74 TIter next_item(lst);
75 while( TObject* obj = next_item() ) {
76 if( obj->IsZombie() )
77 // Skip objects whose constructor failed
78 continue;
79 auto* item = dynamic_cast<T*>(obj);
80 if( item ) {
81 // Skip duplicates
82 auto it = std::find(ALL(vec), item);
83 if( it == vec.end() )
84 vec.push_back(item);
85 }
86 }
87 }
88 return vec.size();
89}
90
91//_____________________________________________________________________________
93 : fFile(nullptr)
94 , fOutput(nullptr)
95 , fEpicsHandler(nullptr)
96 , fOdefFileName(kDefaultOdefFile)
97 , fEvent(nullptr)
98 , fWantCodaVers(-1)
99 , fNev(0)
100 , fMarkInterval(1000)
101 , fCompress(1)
102 , fVerbose(2)
103 , fCountMode(kCountRaw)
104 , fBench(nullptr)
105 , fPrevEvent(nullptr)
106 , fRun(nullptr)
107 , fEvData(nullptr)
108 , fIsInit(false)
109 , fAnalysisStarted(false)
110 , fLocalEvent(false)
111 , fUpdateRun(true)
112 , fOverwrite(true)
113 , fDoBench(false)
114 , fDoHelicity(false)
115 , fDoPhysics(true)
116 , fDoOtherEvents(true)
117 , fDoSlowControl(true)
118 , fFirstPhysics(true)
119 , fExtra(nullptr)
120{
121 // Default constructor.
122
123 //FIXME: relax this
124 // Allow only one analyzer object (because we use various global lists)
125 if( fgAnalyzer ) {
126 Error("THaAnalyzer", "only one instance of THaAnalyzer allowed.");
127 MakeZombie();
128 return;
129 }
130 fgAnalyzer = this;
131
132 // EPICS data
133 fEpicsHandler = new THaEpicsEvtHandler("epics","EPICS event type");
134 // fEpicsHandler->SetDebugFile("epicsdat.txt");
135 fEvtHandlers.push_back(fEpicsHandler);
136
137 // Timers
138 fBench = new THaBenchmark;
139}
140
141//_____________________________________________________________________________
143{
144 // Destructor.
145
147 DeleteContainer(fPostProcess);
148 DeleteContainer(fEvtHandlers);
149 DeleteContainer(fInterStage);
150 delete fExtra; fExtra = nullptr;
151 delete fBench;
152 if( fgAnalyzer == this )
153 fgAnalyzer = nullptr;
154}
155
156//_____________________________________________________________________________
158{
159 // Add 'module' to the list of inter-stage modules. See AddPostProcess()
160 // for additional comments
161
162 //FIXME: code duplication
163 const char* const here = "AddInterStage";
164
165 // No module, nothing to do
166 if( !module )
167 return 0;
168
169 // Can't add modules in the middle of things
170 if( fAnalysisStarted ) {
171 Error( Here(here), "Cannot add analysis modules while analysis "
172 "is in progress. Close() this analysis first." );
173 return 237;
174 }
175
176 // Init this module if Analyzer already initialized. Otherwise, the
177 // module will be initialized in Init() later.
178 if( fIsInit ) {
179 // FIXME: debug
180 if( !fRun || !fRun->IsInit()) {
181 Error(Here(here),"fIsInit, but bad fRun?!?");
182 return 236;
183 }
184 TDatime run_time = fRun->GetDate();
185 Int_t retval = module->Init(run_time);
186 if( retval )
187 return retval;
188 }
189
190 fInterStage.push_back(module);
191 return 0;
192}
193
194//_____________________________________________________________________________
196{
197 // Add 'module' to the list of post-processing modules. This can only
198 // be done if no analysis is in progress. If the Analyzer has been
199 // initialized, the module will be initialized immediately for the current
200 // run time.
201
202 // No module, nothing to do
203 if( !module )
204 return 0;
205
206 // Can't add modules in the middle of things
207 if( fAnalysisStarted ) {
208 Error( "AddPostProcess", "Cannot add analysis modules while analysis "
209 "is in progress. Close() this analysis first." );
210 return 237;
211 }
212
213 // Init this module if Analyzer already initialized. Otherwise, the
214 // module will be initialized in Init() later.
215 if( fIsInit ) {
216 // FIXME: debug
217 if( !fRun || !fRun->IsInit()) {
218 Error("AddPostProcess","fIsInit, but bad fRun?!?");
219 return 236;
220 }
221 TDatime run_time = fRun->GetDate();
222 Int_t retval = module->Init(run_time);
223 if( retval )
224 return retval;
225 }
226
227 fPostProcess.push_back(module);
228 return 0;
229}
230
231//_____________________________________________________________________________
233{
234 // Clear statistics counters
235 for( auto& theCounter : fCounters ) {
236 theCounter.count = 0;
237 }
238}
239
240//_____________________________________________________________________________
242{
243 // Close output files and delete fOutput, fFile, and fRun objects.
244 // Also delete fEvent if it was allocated automatically by us.
245
246 // Close all Post-process objects, but do not delete them
247 // (destructor does that)
248 for( auto* postProc : fPostProcess)
249 postProc->Close();
250
251 // After Close(), will need to Init() again, where these lists will be filled
252 fApps.clear();
253 fSpectrometers.clear();
254 fPhysics.clear();
255 fEvtHandlers.clear();
256
257 if( gHaRun && *gHaRun == *fRun )
258 gHaRun = nullptr;
259
260 delete fEvData; fEvData = nullptr;
261 delete fOutput; fOutput = nullptr;
262 if( TROOT::Initialized() )
263 delete fFile;
264 fFile = nullptr;
265 delete fRun; fRun = nullptr;
266 if( fLocalEvent ) {
267 delete fEvent; fEvent = fPrevEvent = nullptr;
268 }
269 fIsInit = fAnalysisStarted = false;
270}
271
272
273//_____________________________________________________________________________
278
279//_____________________________________________________________________________
284
285//_____________________________________________________________________________
290
291//_____________________________________________________________________________
296
297//_____________________________________________________________________________
302
303//_____________________________________________________________________________
308
309//_____________________________________________________________________________
314
315//_____________________________________________________________________________
317{
318 // Fill histogram block for analysis stage 'n', then evaluate cut block.
319 // Return 'false' if master cut is not true, 'true' otherwise.
320 // The result can be used to skip further processing of the current event.
321 // If event is skipped, increment associated statistics counter.
322 // Call InitCuts() before using! This is an internal function.
323
324 if( fDoBench ) fBench->Begin("Cuts");
325
326 const Stage_t& theStage = fStages[n];
327
328 //FIXME: support stage-wise blocks of histograms
329 // if( theStage.hist_list ) {
330 // Fill histograms
331 // }
332
333 bool ret = true;
334 if( theStage.cut_list ) {
336 if( theStage.master_cut &&
337 !theStage.master_cut->GetResult() ) {
338 if( theStage.countkey >= 0 ) // stage may not have a counter
339 Incr(theStage.countkey);
340 ret = false;
341 }
342 }
343 if( fDoBench ) fBench->Stop("Cuts");
344 return ret;
345}
346
347//_____________________________________________________________________________
349{
350 // Return the decoder object that this analyzer uses to process the input
351
352 if( !fEvData ) {
353 Warning( "GetDecoder", "Decoder not yet set up. You need to "
354 "initialize the analyzer with Init(run) first." );
355 }
356 return fEvData;
357}
358
359//_____________________________________________________________________________
361{
362 // Define analysis stages. Called from Init(). Does nothing if called again.
363 // Derived classes can override this method to define their own
364 // stages or additional stages. This should be done with caution.
365
366 if( !fStages.empty() ) return;
367 fStages.reserve(kPhysics - kRawDecode + 1);
368 fStages = {
369 {kRawDecode, kRawDecodeTest, "RawDecode"},
370 {kDecode, kDecodeTest, "Decode"},
371 {kCoarseTrack, kCoarseTrackTest, "CoarseTracking"},
372 {kCoarseRecon, kCoarseReconTest, "CoarseReconstruct"},
373 {kTracking, kTrackTest, "Tracking"},
374 {kReconstruct, kReconstructTest, "Reconstruct"},
375 {kPhysics, kPhysicsTest, "Physics"}
376 };
377}
378
379//_____________________________________________________________________________
381 // Allocate statistics counters.
382 // See notes for InitStages() for additional information.
383
384 if( !fCounters.empty() ) return;
385 fCounters.reserve(kPhysicsTest - kNevRead + 1);
386 fCounters = {
387 {kNevRead, "events read"},
388 {kNevGood, "events decoded"},
389 {kNevPhysics, "physics events"},
390 {kNevEpics, "slow control events"},
391 {kNevOther, "other event types"},
392 {kNevPostProcess, "events post-processed"},
393 {kNevAnalyzed, "physics events analyzed"},
394 {kNevAccepted, "events accepted"},
395 {kDecodeErr, "decoding error"},
396 {kCodaErr, "CODA errors"},
397 {kRawDecodeTest, "skipped after raw decoding"},
398 {kDecodeTest, "skipped after Decode"},
399 {kCoarseTrackTest, "skipped after Coarse Tracking"},
400 {kCoarseReconTest, "skipped after Coarse Reconstruct"},
401 {kTrackTest, "skipped after Tracking"},
402 {kReconstructTest, "skipped after Reconstruct"},
403 {kPhysicsTest, "skipped after Physics"}
404 };
405}
406
407//_____________________________________________________________________________
409{
410 // Internal function that sets up structures to handle cuts more efficiently:
411 //
412 // - Find pointers to the THaNamedList lists that hold the cut blocks.
413 // - find pointer to each block's master cut
414
415 for( auto& theStage : fStages ) {
416 // If block not found, this will return nullptr and work just fine later.
417 theStage.cut_list = gHaCuts->FindBlock( theStage.name );
418
419 if( theStage.cut_list ) {
420 TString master_cut( theStage.name );
421 master_cut.Append( '_' );
422 master_cut.Append( kMasterCutName );
423 theStage.master_cut = gHaCuts->FindCut( master_cut );
424 } else
425 theStage.master_cut = nullptr;
426 }
427}
428
429//_____________________________________________________________________________
431 const std::vector<THaAnalysisObject*>& module_list, TDatime& run_time )
432{
433 // Initialize a list of THaAnalysisObjects for time 'run_time'.
434 // If 'baseclass' given, ensure that each object in the list inherits
435 // from 'baseclass'.
436
437 static const char* const here = "InitModules()";
438
439 Int_t retval = 0;
440 for( auto it = module_list.begin(); it != module_list.end(); ) {
441 auto* theModule = *it;
442 if( fVerbose > 1 )
443 cout << "Initializing " << theModule->GetName() << endl;
444 try {
445 retval = theModule->Init( run_time );
446 }
447 catch( const exception& e ) {
448 Error(here, "Exception %s caught during initialization of module "
449 "%s (%s). Analyzer initialization failed.",
450 e.what(), theModule->GetName(), theModule->GetTitle() );
451 retval = -1;
452 goto errexit;
453 }
454 if( retval != kOK || !theModule->IsOK() ) {
455 Error( here, "Error %d initializing module %s (%s). "
456 "Analyzer initialization failed.",
457 retval, theModule->GetName(), theModule->GetTitle() );
458 if( retval == kOK )
459 retval = -1;
460 break;
461 }
462 ++it;
463 }
464 errexit:
465 return retval;
466}
467
468//_____________________________________________________________________________
470{
471 // Initialize the analyzer.
472
473 // This is a wrapper, so we can conveniently control the benchmark counter
474 if( !run ) return -1;
475
476 if( !fIsInit ) fBench->Reset();
477 fBench->Begin("Total");
478
479 if( fDoBench ) fBench->Begin("Init");
480 Int_t retval = DoInit( run );
481 if( fDoBench ) fBench->Stop("Init");
482
483 // Stop "Total" counter since Init() may be called separately from Process()
484 fBench->Stop("Total");
485 return retval;
486}
487
488//_____________________________________________________________________________
490{
491 // Internal function called by Init(). This is where the actual work is done.
492
493 //FIXME:should define return codes in header
494 static const char* const here = "Init";
495 Int_t retval = 0;
496
497 //--- Initialize the run object, if necessary
498 if( !run ) {
499 Error(here, "run is null");
500 return -243;
501 }
502 // If we've been told to use a specific CODA version, tell the run
503 // object about it. (FIXME: This may not work with non-CODA runs.)
504 if( fWantCodaVers > 0 && run->SetDataVersion(fWantCodaVers) < 0 ) {
505 Error( here, "Failed to set CODA version %d for run. Call expert.",
507 return -242;
508 }
509 // Make sure the run is initialized.
510 bool run_init = false;
511 if( !run->IsInit()) {
512 cout << "Initializing run object" << endl;
513 run_init = true;
514 retval = run->Init();
515 if( retval )
516 return retval; //Error message printed by run class
517 }
518
519 //--- Open the output file if necessary so that Trees and Histograms
520 // are created on disk.
521
522 // File previously created and name changed?
523 if( fFile && fOutFileName != fFile->GetName()) {
524 // But -- we are analyzing split runs (so multiple initializations)
525 // and the tree's file has split too (so fFile has changed automatically)
526#if 0
527 if( fAnalysisStarted ) {
528 Error( here, "Cannot change output file name after analysis has been "
529 "started. Close() first, then Init() or Process() again." );
530 return -11;
531 }
532 Close();
533#endif
534 }
535 if( !fFile ) {
536 if( fOutFileName.IsNull() ) {
537 Error( here, "Must specify an output file. Set it with SetOutFile()." );
538 return -12;
539 }
540 // File exists?
541 if( !gSystem->AccessPathName(fOutFileName) ) { //sic
542 if( !fOverwrite ) {
543 Error( here, "Output file %s already exists. Choose a different "
544 "file name or enable overwriting with EnableOverwrite().",
545 fOutFileName.Data() );
546 return -13;
547 }
548 cout << "Overwriting existing";
549 } else
550 cout << "Creating new";
551 cout << " output file: " << fOutFileName << endl;
552 fFile = new TFile( fOutFileName.Data(), "RECREATE" );
553 }
554 if( !fFile || fFile->IsZombie() ) {
555 Error( here, "failed to create output file %s. Check file/directory "
556 "permissions.", fOutFileName.Data() );
557 Close();
558 return -14;
559 }
561
562 //--- Set up the summary output file, if any
564 ofstream ofs;
565 auto openmode = fOverwrite ? ios::out : ios::app;
566 ofs.open(fSummaryFileName, openmode);
567 if( !ofs ) {
568 Error(here, "Failed to open summary file %s. Check file/directory "
569 "permissions", fSummaryFileName.Data());
570 return -15;
571 }
572 ofs << "==== " << TDatime().AsString();
573 ofs.close();
574 }
575
576 // Set up the analysis stages and allocate counters.
577 if( !fIsInit ) {
578 InitStages();
579 InitCounters();
580 }
581
582 // Allocate the event structure.
583 // Use the default (containing basic event header) unless the user has
584 // specified a different one.
585 bool new_event = false;
586 // Event changed since a previous initialization?
587 if( fEvent != fPrevEvent ) {
588 if( fAnalysisStarted ) {
589 // Don't allow a new event in the middle of the analysis!
590 Error( here, "Cannot change event structure for continuing analysis. "
591 "Close() this analysis, then Init() again." );
592 return -254;
593 } else if( fIsInit ) {
594 // If previously initialized, we might have to clean up first.
595 // If we had automatically allocated an event before, and now the
596 // user specifies his/her own (fEvent != 0), then get rid of the
597 // previous event. Otherwise, keep the old event since it would just be
598 // re-created anyway.
599 if( !fLocalEvent || fEvent )
600 new_event = true;
601 if( fLocalEvent && fEvent ) {
602 delete fPrevEvent; fPrevEvent = nullptr;
603 fLocalEvent = false;
604 }
605 }
606 }
607 if( !fEvent ) {
608 fEvent = new THaEvent;
609 fLocalEvent = true;
610 new_event = true;
611 }
613 fEvent->Reset();
614
615 // Allocate the output module. Recreate if necessary. At this time, this is
616 // always THaOutput, and the user cannot specify his/her own.
617 // A new event requires recreation of the output module because the event
618 // occupies a dedicated branch in the output tree.
619 bool new_output = false;
620 if( !fOutput || new_event ) {
621 delete fOutput;
622 fOutput = new THaOutput;
623 new_output = true;
624 }
625
626 //--- Create our decoder from the TClass specified by the user.
627 bool new_decoder = false;
628 if( !fEvData || fEvData->IsA() != gHaDecoder ) {
629 delete fEvData; fEvData = nullptr;
630 if( gHaDecoder )
631 fEvData = static_cast<THaEvData*>(gHaDecoder->New());
632 if( !fEvData ) {
633 Error( here, "Failed to create decoder object. "
634 "Something is very wrong..." );
635 return -241;
636 }
637 new_decoder = true;
638 }
639 // Set run-level info that was retrieved when initializing the run.
640 // In case we analyze a continuation segment, fEvtData may not see
641 // the event(s) where these data come from (usually Prestart).
643 run->GetType(),
644 run->GetDate().Convert());
645
646 // Deal with the run.
647 bool new_run = ( !fRun || *fRun != *run );
648 bool need_init = ( !fIsInit || new_event || new_output || new_run ||
649 new_decoder || run_init );
650
651#if 0
652 // Warn user if trying to analyze the same run twice with overlapping
653 // event ranges. Broken for split files now, so disable warning.
654 // FIXME: generalize event range business?
655 if( fAnalysisStarted && !new_run && fCountMode!=kCountRaw &&
656 ((fRun->GetLastEvent() >= run->GetFirstEvent() &&
657 fRun->GetFirstEvent() < run->GetLastEvent()) ||
658 (fRun->GetFirstEvent() <= run->GetLastEvent() &&
659 fRun->GetLastEvent() > run->GetFirstEvent()) )) {
660 Warning( here, "You are analyzing the same run twice with "
661 "overlapping event ranges! prev: %d-%d, now: %d-%d",
663 run->GetFirstEvent(), run->GetLastEvent() );
664 if( !gROOT->IsBatch() ) {
665 cout << "Are you sure (y/n)?" << endl;
666 char c = 0;
667 while( c != 'y' && c != 'n' && c != EOF ) {
668 cin >> c;
669 }
670 if( c != 'y' && c != 'Y' )
671 return -240;
672 }
673 }
674#endif
675
676 // Make sure we save a copy of the run in fRun.
677 // Note that the run may be derived from THaRunBase, so this is a bit tricky.
678 // Check if run changed using Compare to be sure we note change of split runs
679 if( new_run || fRun->Compare(run) ) {
680 delete fRun;
681 fRun = static_cast<THaRunBase*>(run->IsA()->New());
682 if( !fRun ) {
683 Error(here, "Failed to create copy of run object. "
684 "Something is very wrong...");
685 return -252;
686 }
687 *fRun = *run; // Copy the run via its virtual operator=
688 }
689
690 // Make the current run available globally - the run parameters are
691 // needed by some modules
692 gHaRun = fRun;
693
694 // Print run info
695 if( fVerbose>0 ) {
696 fRun->Print("STARTINFO");
697 }
698
699 // Write startup info to summary file
700 if( !fSummaryFileName.IsNull() ) {
701 ofstream ofs(fSummaryFileName.Data(), ios::app);
702 if( !ofs ) {
703 // This would be odd, since it just worked above
704 Error(here, "Failed to open summary file %s (after previous success). "
705 "Check file/directory permissions", fSummaryFileName.Data());
706 return -15;
707 }
708 ofs << " " << (fAnalysisStarted ? "Continuing" : "Started") << " analysis"
709 << ", run " << run->GetNumber() << endl;
710 ofs << "Reading from ";
711 // Redirect cout to ofs
712 auto* cout_buf = cout.rdbuf();
713 cout.rdbuf(ofs.rdbuf());
714 fRun->Print("NAMEDESC");
715 cout.rdbuf(cout_buf);
716 ofs << endl;
717 ofs.close();
718 }
719
720 // Clear counters unless we are continuing an analysis
721 if( !fAnalysisStarted )
723
724 //---- If previously initialized and nothing changed, we are done----
725 if( !need_init )
726 return 0;
727
728 // Obtain time of the run, the one parameter we really need
729 // for initializing the modules
730 TDatime run_time = fRun->GetDate();
731
732 // Tell the decoder the run time. This will trigger decoder
733 // initialization (reading of crate map data etc.)
734 fEvData->SetRunTime( run_time.Convert());
735
736 // Tell the decoder about the run's CODA version
738
739 // Use the global lists of analysis objects.
740 if( !fAnalysisStarted ) {
745 }
746
747 // Initialize all apparatuses, physics modules, event type handlers
748 // and inter-stage modules in that order. Quit on any errors.
749 cout << "Initializing analysis objects" << endl;
750 vector<THaAnalysisObject*> modulesToInit;
751 modulesToInit.reserve(fApps.size() + fPhysics.size() +
752 fEvtHandlers.size() + fInterStage.size());
753 modulesToInit.insert(modulesToInit.end(), ALL(fApps));
754 modulesToInit.insert(modulesToInit.end(), ALL(fPhysics));
755 modulesToInit.insert(modulesToInit.end(), ALL(fEvtHandlers));
756 modulesToInit.insert(modulesToInit.end(), ALL(fInterStage));
757 retval = InitModules(modulesToInit, run_time);
758 if( retval == 0 ) {
759
760 // Set up cuts here, now that all global variables are available
761 if( fCutFileName.IsNull() ) {
762 // No test definitions -> make sure list is clear
763 gHaCuts->Clear();
765 } else {
767 // New test definitions -> load them
768 cout << "Loading cuts from " << fCutFileName << endl;
771 }
772 // Ensure all tests are up-to-date. Global variables may have changed.
773 gHaCuts->Compile();
774 }
775 // Initialize local pointers to test blocks and master cuts
776 InitCuts();
777
778 // fOutput must be initialized after all apparatuses are
779 // initialized and before adding anything to its tree.
780
781 // first, make sure we are in the output file, but remember the previous
782 // state. This makes a difference if another ROOT-file is opened to read
783 // in simulated or old data
784 TDirectory *olddir = gDirectory;
785 fFile->cd();
786
787 cout << "Initializing output" << endl;
788 if( (retval = fOutput->Init( fOdefFileName )) < 0 ) {
789 Error( here, "Error initializing THaOutput." );
790 } else if( retval == 1 )
791 retval = 0; // Reinitialization ok, not an error
792 else {
793 // If initialized ok, but not re-initialized, make a branch for
794 // the event structure in the output tree
795 TTree* outputTree = fOutput->GetTree();
796 if( outputTree )
797 outputTree->Branch( "Event_Branch", fEvent->IsA()->GetName(),
798 &fEvent, 16000, 99 );
799 }
800 olddir->cd();
801
802 // Post-process has to be initialized after all cuts are known
803 if( !fPostProcess.empty() )
804 cout << "Initializing post processors" << endl;
805 for( auto* obj : fPostProcess) {
806 retval = obj->Init(run_time);
807 if( retval != 0 )
808 break;
809 }
810 }
811
812 if ( retval == 0 ) {
813 if ( ! fOutput ) {
814 Error( here, "Error initializing THaOutput for objects(again!)" );
815 retval = -5;
816 } else {
817 // call the apparatuses again, to permit them to write more
818 // complex output directly to the TTree
819 retval = InitOutput(modulesToInit);
820 }
821 }
822
823 // If initialization succeeded, set status flags accordingly
824 if( retval == 0 ) {
825 fIsInit = true;
826 }
827 return retval;
828}
829
830//_____________________________________________________________________________
831Int_t THaAnalyzer::InitOutput( const std::vector<THaAnalysisObject*>& module_list )
832{
833 // Initialize a list of THaAnalysisObject's for output
834 // If 'baseclass' given, ensure that each object in the list inherits
835 // from 'baseclass'.
836 static const char* const here = "InitOutput()";
837
838 Int_t retval = 0;
839 for( auto* theModule : module_list ) {
840 theModule->InitOutput( fOutput );
841 if( !theModule->IsOKOut() ) {
842 Error( here, "Error initializing output for %s (%s). "
843 "Analyzer initialization failed.",
844 theModule->GetName(), theModule->GetTitle() );
845 retval = -1;
846 break;
847 }
848 }
849 return retval;
850}
851
852
853//_____________________________________________________________________________
855{
856 // Read one event from current run (fRun) and raw-decode it using the
857 // current decoder (fEvData)
858
859 if( fDoBench ) fBench->Begin("RawDecode");
860
861 // Find next event buffer in CODA file. Quit if error.
862 Int_t status = THaRunBase::READ_OK;
863 if( !fEvData->DataCached() )
864 status = fRun->ReadEvent();
865
866 switch( status ) {
868 // Decode the event
869 status = fEvData->LoadEvent( fRun->GetEvBuffer() );
870 switch( status ) {
871 case THaEvData::HED_OK: // fall through
873 status = THaRunBase::READ_OK;
874 Incr(kNevRead);
875 break;
877 // Decoding error
878 status = THaRunBase::READ_ERROR;
880 break;
882 status = THaRunBase::READ_FATAL;
883 break;
884 default:
885 Error("THaAnalyzer::ReadEvent",
886 "Unsupported decoder return code %d. Call expert.", status);
887 status = THaRunBase::READ_FATAL;
888 break;
889 }
890 break;
891
892 case THaRunBase::READ_EOF: // fall through
894 // Just exit on EOF - don't count it
895 break;
896 default:
897 Incr(kCodaErr);
898 break;
899 }
900
901 if( fDoBench ) fBench->Stop("RawDecode");
902 return status;
903}
904
905//_____________________________________________________________________________
911
912//_____________________________________________________________________________
917
918//_____________________________________________________________________________
920{
921 // Set the way the internal event counter is defined.
922 // If mode >= 0 and mode is one of kCountAll, kCountPhysics, or kCountRaw,
923 // then set the mode. If mode >= 0 but unknown, return -mode.
924 // If mode < 0, don't change the mode but return the current count mode.
925
926 if( mode < 0 )
927 return fCountMode;
928
929 if( mode != kCountAll && mode != kCountPhysics && mode != kCountRaw )
930 return -mode;
931
933 return mode;
934}
935
936//_____________________________________________________________________________
937void THaAnalyzer::SetCrateMapFileName( const char* name )
938{
939 // Set name of file from which to read the crate map.
940 // For simplicity, a simple string like "mymap" is automatically
941 // converted to "db_mymap.dat". See THaAnalysisObject::GetDBFileList
942 // Must be called before initialization.
943
945}
946
947//_____________________________________________________________________________
949{
950 // Report status of the analyzer.
951
952 //FIXME: preliminary
953 if( fRun )
954 fRun->Print();
955}
956
957//_____________________________________________________________________________
959{
960 // Print statistics counters
961 UInt_t w = 0;
962 auto ncounters = static_cast<Int_t>(fCounters.size());
963 for( Int_t i = 0; i < ncounters; i++ ) {
964 if( GetCount(i) > w )
965 w = GetCount(i);
966 }
967 w = IntDigits(SINT(w));
968
969 bool first = true;
970 for( Int_t i = 0; i < ncounters; i++ ) {
971 const char* text = fCounters[i].description;
972 if( GetCount(i) != 0 && text && *text ) {
973 if( first ) {
974 cout << "Counter summary:" << endl;
975 first = false;
976 }
977 cout << setw(w) << GetCount(i) << " " << text << endl;
978 }
979 }
980 cout << endl;
981}
982
983//_____________________________________________________________________________
985{
986 // Print analyzer exit status
987
988 cout << dec;
989 switch( status ) {
991 cout << "Analysis ended.";
992 break;
994 cout << "End of file.";
995 break;
997 cout << "Event limit reached.";
998 break;
1000 cout << "Fatal processing error.";
1001 break;
1003 cout << "Terminated during processing.";
1004 break;
1005 }
1006 cout << endl;
1007}
1008
1009//_____________________________________________________________________________
1011{
1012 // Print general summary of run
1013
1014 cout << "==== " << TDatime().AsString()
1015 << " Summary for run " << fRun->GetNumber()
1016 << endl;
1017}
1018
1019//_____________________________________________________________________________
1021{
1022 // Print summary of cuts
1023
1024 if( gHaCuts->GetSize() > 0 ) {
1025 cout << "Cut summary:" << endl;
1026 gHaCuts->Print("STATS");
1027 }
1028}
1029
1030//_____________________________________________________________________________
1032{
1033 // Print timing statistics, if benchmarking enabled
1034 if( (fVerbose > 1 || fDoBench) ) {
1035 vector<TString> names;
1036 if( fDoBench ) {
1037 cout << "Timing summary:" << endl;
1038 names = {
1039 "Init", "Begin", "RawDecode", "Decode", "CoarseTracking",
1040 "CoarseReconstruct", "Tracking", "Reconstruct", "Physics", "End",
1041 "Output", "Cuts"
1042 };
1043 }
1044 names.emplace_back("Total");
1045 fBench->PrintByName(names);
1046 }
1047}
1048
1049//_____________________________________________________________________________
1051{
1052 // Print summary (cuts etc.)
1053 // Only print to screen if fVerbose>1.
1054 // Always write to the summary file if a summary file is requested.
1055
1056 if( fVerbose > 0 ) {
1057 PrintExitStatus(exit_status);
1059 if( exit_status != EExitStatus::kFatal ) {
1060 PrintCounters();
1061 if( fVerbose > 1 )
1063 }
1064 }
1066
1067 if( !fSummaryFileName.IsNull() ) {
1068 // Append to the summary file. If fOverwrite is set, it was already
1069 // recreated earlier
1070 ofstream ostr(fSummaryFileName, ios::app );
1071 if( ostr ) {
1072 // Write to file via cout
1073 auto* cout_buf = cout.rdbuf();
1074 cout.rdbuf(ostr.rdbuf());
1075
1076 PrintExitStatus(exit_status);
1078 if( exit_status != EExitStatus::kFatal ) {
1079 PrintCounters();
1081 }
1083
1084 cout.rdbuf(cout_buf);
1085 ostr.close();
1086 }
1087 }
1088
1089}
1090
1091//_____________________________________________________________________________
1093{
1094 // Internal function called right before the start of the event loop
1095 // for each run.
1096 // Initializes subroutine-specific variables.
1097 // Executes Begin() for all Apparatus and Physics modules.
1098
1099 fFirstPhysics = true;
1100
1101 if( fDoBench ) fBench->Begin("Begin");
1102
1103 for( auto* theModule : fAnalysisModules ) {
1104 theModule->Begin( fRun );
1105 }
1106
1107 for( auto* obj : fEvtHandlers ) {
1108 obj->Begin(fRun);
1109 }
1110
1111 if( fDoBench ) fBench->Stop("Begin");
1112
1113 return 0;
1114}
1115
1116//_____________________________________________________________________________
1118{
1119 // Execute End() for all Apparatus and Physics modules. Internal function
1120 // called right after event loop is finished for each run.
1121
1122 if( fDoBench ) fBench->Begin("End");
1123
1124 for( auto* theModule : fAnalysisModules ) {
1125 theModule->End( fRun );
1126 }
1127
1128 for( auto* obj : fEvtHandlers ) {
1129 obj->End(fRun);
1130 }
1131
1132 if( fDoBench ) fBench->Stop("End");
1133
1134 return 0;
1135}
1136
1137//_____________________________________________________________________________
1139{
1140 // Analysis of physics events
1141
1142 static const char* const here = "PhysicsAnalysis";
1143
1144 // Don't analyze events that did not pass RawDecode cuts
1145 if( code != kOK )
1146 return code;
1147
1148 //--- Skip physics events until we reach the first requested event
1149 if( fNev < fRun->GetFirstEvent() )
1150 return kSkip;
1151
1152 if( fFirstPhysics ) {
1153 fFirstPhysics = false;
1154 if( fVerbose>2 )
1155 cout << "Starting physics analysis at event " << GetCount(kNevPhysics)
1156 << endl;
1157 }
1158 // Update counters
1161
1162 //--- Process all apparatuses that are defined in fApps
1163 // First Decode(), then Reconstruct()
1164
1165 const char* stage = "";
1166 THaAnalysisObject* obj = nullptr; // current module, for exception error message
1167
1168 try {
1169 stage = "Decode";
1170 if( fDoBench ) fBench->Begin(stage);
1171 for( auto* mod : fAnalysisModules ) {
1172 obj = mod;
1173 mod->Clear();
1174 }
1175 for( auto* app : fApps ) {
1176 obj = app;
1177 app->Decode(*fEvData);
1178 }
1179 for( auto* mod : fInterStage ) {
1180 if( mod->GetStage() == kDecode ) {
1181 obj = mod;
1182 mod->Process(*fEvData);
1183 }
1184 }
1185 if( fDoBench ) fBench->Stop(stage);
1186 if( !EvalStage(kDecode) ) return kSkip;
1187
1188 //--- Main physics analysis. Calls the following for each defined apparatus
1189 // THaSpectrometer::CoarseTrack (only for spectrometers)
1190 // THaApparatus::CoarseReconstruct
1191 // THaSpectrometer::Track (only for spectrometers)
1192 // THaApparatus::Reconstruct
1193 //
1194 // Test blocks are evaluated after each of these stages
1195
1196 //-- Coarse processing
1197
1198 stage = "CoarseTracking";
1199 if( fDoBench ) fBench->Begin(stage);
1200 for( auto* spectro : fSpectrometers ) {
1201 obj = spectro;
1202 spectro->CoarseTrack();
1203 }
1204 for( auto* mod : fInterStage ) {
1205 if( mod->GetStage() == kCoarseTrack ) {
1206 obj = mod;
1207 mod->Process(*fEvData);
1208 }
1209 }
1210 if( fDoBench ) fBench->Stop(stage);
1211 if( !EvalStage(kCoarseTrack) ) return kSkip;
1212
1213
1214 stage = "CoarseReconstruct";
1215 if( fDoBench ) fBench->Begin(stage);
1216 for( auto* app : fApps ) {
1217 obj = app;
1218 app->CoarseReconstruct();
1219 }
1220 for( auto* mod : fInterStage ) {
1221 if( mod->GetStage() == kCoarseRecon ) {
1222 obj = mod;
1223 mod->Process(*fEvData);
1224 }
1225 }
1226 if( fDoBench ) fBench->Stop(stage);
1227 if( !EvalStage(kCoarseRecon) ) return kSkip;
1228
1229 //-- Fine (Full) Reconstruct().
1230
1231 stage = "Tracking";
1232 if( fDoBench ) fBench->Begin(stage);
1233 for( auto* spectro : fSpectrometers ) {
1234 obj = spectro;
1235 spectro->Track();
1236 }
1237 for( auto* mod : fInterStage ) {
1238 if( mod->GetStage() == kTracking ) {
1239 obj = mod;
1240 mod->Process(*fEvData);
1241 }
1242 }
1243 if( fDoBench ) fBench->Stop(stage);
1244 if( !EvalStage(kTracking) ) return kSkip;
1245
1246
1247 stage = "Reconstruct";
1248 if( fDoBench ) fBench->Begin(stage);
1249 for( auto* app : fApps ) {
1250 obj = app;
1251 app->Reconstruct();
1252 }
1253 for( auto* mod : fInterStage ) {
1254 if( mod->GetStage() == kReconstruct ) {
1255 obj = mod;
1256 mod->Process(*fEvData);
1257 }
1258 }
1259 if( fDoBench ) fBench->Stop(stage);
1260 if( !EvalStage(kReconstruct) ) return kSkip;
1261
1262 //--- Process the list of physics modules
1263
1264 stage = "Physics";
1265 if( fDoBench ) fBench->Begin(stage);
1266 for( auto* physmod : fPhysics ) {
1267 obj = physmod;
1268 Int_t err = physmod->Process( *fEvData );
1269 if( err == THaPhysicsModule::kTerminate )
1270 code = kTerminate;
1271 else if( err == THaPhysicsModule::kFatal ) {
1272 code = kFatal;
1273 break;
1274 }
1275 }
1276 for( auto* mod : fInterStage ) {
1277 if( mod->GetStage() == kPhysics ) {
1278 obj = mod;
1279 mod->Process(*fEvData);
1280 }
1281 }
1282 if( fDoBench ) fBench->Stop(stage);
1283 if( code == kFatal ) return kFatal;
1284
1285 //--- Evaluate "Physics" test block
1286
1287 if( !EvalStage(kPhysics) )
1288 // any status code form the physics analysis overrides skip code
1289 return (code == kOK) ? kSkip : code;
1290
1291 } // end try
1292 catch( const exception& e ) {
1293 TString module_name = (obj != nullptr) ? obj->GetName() : "unknown";
1294 TString module_desc = (obj != nullptr) ? obj->GetTitle() : "unknown";
1295 Error( here, "Caught exception %s in module %s (%s) during %s analysis "
1296 "stage. Terminating analysis.", e.what(), module_name.Data(),
1297 module_desc.Data(), stage );
1298 if( fDoBench ) fBench->Stop(stage);
1299 code = kFatal;
1300 goto errexit;
1301 }
1302
1303 //--- Process output
1304 if( fDoBench ) fBench->Begin("Output");
1305 try {
1306 //--- If Event defined, fill it.
1307 if( fEvent ) {
1309 fEvData->GetEvType(),
1311 fEvData->GetEvTime(),
1314 fRun->GetNumber()
1315 );
1316 fEvent->Fill();
1317 }
1318 // Write to output file
1319 if( fOutput ) fOutput->Process();
1320 }
1321 catch( const exception& e ) {
1322 Error( here, "Caught exception %s during output of event %u. "
1323 "Terminating analysis.", e.what(), fNev );
1324 code = kFatal;
1325 }
1326 if( fDoBench ) fBench->Stop("Output");
1327
1328 errexit:
1329 return code;
1330}
1331
1332//_____________________________________________________________________________
1334{
1335 // Analyze slow control (EPICS) data and write them to output.
1336 // Ignores RawDecode results and requested event range, so EPICS
1337 // data are always analyzed continuously from the beginning of the run.
1338
1339 if( code == kFatal )
1340 return code;
1341 if ( !fEpicsHandler ) return kOK;
1342 if( fDoBench ) fBench->Begin("Output");
1344 if( fDoBench ) fBench->Stop("Output");
1345 if( code == kTerminate )
1346 return code;
1347 return kOK;
1348}
1349
1350//_____________________________________________________________________________
1352{
1353 // Analysis of other events (i.e. events that are not physics, scaler, or
1354 // slow control events).
1355 //
1356 // This default version does nothing. Returns 'code'.
1357
1358 return code;
1359}
1360
1361//_____________________________________________________________________________
1363{
1364 // Post-processing via generic PostProcess modules
1365 // May be used for event filtering etc.
1366 // 'code' (status of the preceding analysis) is passed to the
1367 // THaPostProcess::Process() function for optional evaluation,
1368 // e.g. skipping events that fail analysis stage cuts.
1369
1370 if( fDoBench ) fBench->Begin("PostProcess");
1371
1372 if( code == kFatal )
1373 return code;
1374 for( auto* obj : fPostProcess ) {
1375 Int_t ret = obj->Process(fEvData,fRun,code);
1376 if( obj->TestBits(THaPostProcess::kUseReturnCode) &&
1377 ret > code )
1378 code = ret;
1379 }
1380 if( fDoBench ) fBench->Stop("PostProcess");
1381 return code;
1382}
1383
1384//_____________________________________________________________________________
1386{
1387 // Main analysis carried out for each event
1388
1389 static const char* const here = "MainAnalysis";
1390
1391 Int_t retval = kOK;
1392
1393 Incr(kNevGood);
1394
1395 //--- Evaluate test block "RawDecode"
1396 bool rawfail = false;
1397 if( !EvalStage(kRawDecode) ) {
1398 retval = kSkip;
1399 rawfail = true;
1400 }
1401
1402 //FIXME Move to "OtherAnalysis"?
1403 for( auto* obj : fEvtHandlers ) {
1404 try {
1405 obj->Analyze(fEvData);
1406 }
1407 catch( const exception& e) {
1408 // Generic exceptions are not fatal. Print message and continue.
1409 Error( here, "%s", e.what() );
1410 }
1411 }
1412
1413 bool evdone = false;
1414 //=== Physics triggers ===
1415 if( fEvData->IsPhysicsTrigger() && fDoPhysics ) {
1417 retval = PhysicsAnalysis(retval);
1418 evdone = true;
1419 }
1420
1421 //=== EPICS data ===
1422 if( fEpicsHandler->GetNumTypes() > 0 ) {
1425 Incr(kNevEpics);
1426 retval = SlowControlAnalysis(retval);
1427 evdone = true;
1428 }
1429 }
1430
1431 //=== Other events ===
1432 if( !evdone && fDoOtherEvents ) {
1433 Incr(kNevOther);
1434 retval = OtherAnalysis(retval);
1435
1436 } // End trigger type test
1437
1438
1439 //=== Post-processing (e.g. event filtering) ===
1440 if( !fPostProcess.empty() ) {
1442 retval = PostProcess(retval);
1443 }
1444
1445 // Take care of the RawDecode skip counter
1446 if( rawfail && retval != kSkip && GetCount(kRawDecodeTest)>0 )
1447 fCounters[kRawDecodeTest].count--;
1448
1449 return retval;
1450}
1451
1452//_____________________________________________________________________________
1454{
1455 // Process the given run. Loop over all events in the event range and
1456 // analyze all apparatuses defined in the global apparatus list.
1457 // Fill Event structure if it is defined.
1458 // If Event and Filename are defined, then fill the output tree with Event
1459 // and write the file.
1460
1461 static const char* const here = "Process";
1462
1463 if( !run ) {
1464 if( fRun )
1465 run = fRun;
1466 else
1467 return -1;
1468 }
1469
1470 //--- Initialization. Creates fFile, fOutput, and fEvent if necessary.
1471 // Also copies run to fRun if run is different from fRun
1472 Int_t status = Init( run );
1473 if( status != 0 ) {
1474 return status;
1475 }
1476
1477 // Restart "Total" since it is stopped in Init()
1478 fBench->Begin("Total");
1479
1480 //--- Re-open the data source. Should succeed since this was tested in Init().
1481 if( (status = fRun->Open()) != THaRunBase::READ_OK ) {
1482 Error( here, "Failed to re-open the input file. "
1483 "Make sure the file still exists.");
1484 fBench->Stop("Total");
1485 return -4;
1486 }
1487
1488 // Make the current run available globally - the run parameters are
1489 // needed by some modules
1490 gHaRun = fRun;
1491
1492 // Enable/disable helicity decoding as requested
1494 // Set decoder reporting level. FIXME: update when THaEvData is updated
1495 fEvData->SetVerbose( (fVerbose>2) );
1496 fEvData->SetDebug( (fVerbose>3) );
1497
1498 // Informational messages
1499 if( fVerbose>1 ) {
1500 cout << "Decoder: helicity "
1501 << (fEvData->HelicityEnabled() ? "enabled" : "disabled")
1502 << endl;
1503 cout << endl << "Starting analysis" << endl;
1504 }
1505 // Events prior to fRun->GetFirstEvent() are skipped in MainAnalysis()
1506 if( fVerbose>2 && fRun->GetFirstEvent()>1 )
1507 cout << "Skipping " << fRun->GetFirstEvent() << " events" << endl;
1508
1509 //--- The main event loop.
1510
1511 if( fDoBench ) fBench->Begin("Init");
1512 fNev = 0;
1513 bool terminate = false, fatal = false;
1514 UInt_t nlast = fRun->GetLastEvent();
1515 fAnalysisStarted = true;
1517 if( fDoBench ) fBench->Stop("Init");
1518 BeginAnalysis();
1519 if( fFile ) {
1520 if( fDoBench ) fBench->Begin("Output");
1521 fFile->cd();
1522 fRun->Write("Run_Data"); // Save run data to first ROOT file
1523 if( fDoBench ) fBench->Stop("Output");
1524 }
1525
1526 while ( !terminate && fNev < nlast &&
1527 (status = ReadOneEvent()) != THaRunBase::READ_EOF ) {
1528
1529 //--- Skip events with errors, unless fatal
1530 if( status == THaRunBase::READ_FATAL ) {
1531 terminate = fatal = true;
1532 continue;
1533 }
1534 if( status != THaRunBase::READ_OK )
1535 continue;
1536
1537 UInt_t evnum = fEvData->GetEvNum();
1538
1539 // Set the event counter according to the requested mode
1540 switch(fCountMode) {
1541 case kCountPhysics:
1542 if( fEvData->IsPhysicsTrigger() )
1543 fNev++;
1544 break;
1545 case kCountAll:
1546 fNev++;
1547 break;
1548 case kCountRaw:
1549 fNev = evnum;
1550 break;
1551 default:
1552 break;
1553 }
1554
1555 //--- Print marks periodically
1556 if( fVerbose > 1 && fNev > 0 && (fNev % fMarkInterval == 0) &&
1557 // Avoid duplicates that may occur if a physics event is followed by
1558 // non-physics events. Only physics events update the event number.
1560 cout << dec << fNev << endl;
1561
1562 //--- Update run parameters with current event
1563 if( fUpdateRun )
1564 fRun->Update( fEvData );
1565
1566 //--- Clear all tests/cuts
1567 if( fDoBench ) fBench->Begin("Cuts");
1568 gHaCuts->ClearAll();
1569 if( fDoBench ) fBench->Stop("Cuts");
1570
1571 //--- Perform the analysis
1572 Int_t err = MainAnalysis();
1573 switch( err ) {
1574 case kOK:
1575 break;
1576 case kSkip:
1577 continue;
1578 case kFatal:
1579 fatal = terminate = true;
1580 continue;
1581 case kTerminate:
1582 terminate = true;
1583 break;
1584 default:
1585 Error( here, "Unknown return code from MainAnalysis(): %d", err );
1586 terminate = fatal = true;
1587 continue;
1588 }
1589
1591
1592 } // End of event loop
1593
1594 EndAnalysis();
1595
1596 //--- Close the input file
1597 fRun->Close();
1598
1599 // Save final run parameters in run object of caller, if any
1600 *run = *fRun;
1601
1602 // Write the output file and clean up.
1603 // This writes the Tree as well as any objects (histograms etc.)
1604 // that are defined in the current directory.
1605
1606 if( fDoBench ) fBench->Begin("Output");
1607 // Ensure that we are in the output file's current directory
1608 // ... someone might have pulled the rug from under our feet
1609
1610 // get the CURRENT file, since splitting might have occurred
1611 if( fOutput && fOutput->GetTree() )
1613 if( fFile ) fFile->cd();
1614 if( fOutput ) fOutput->End();
1615 if( fFile ) {
1616 fRun->Write("Run_Data"); // Save run data to ROOT file
1617 // fFile->Write();//already done by fOutput->End()
1618 fFile->Purge(); // get rid of excess object "cycles"
1619 }
1620 if( fDoBench ) fBench->Stop("Output");
1621
1622 fBench->Stop("Total");
1623
1624 //--- Report statistics and summary information (also to file if one given)
1625 EExitStatus exit_status = EExitStatus::kUnknown;
1626 if( status == THaRunBase::READ_EOF )
1627 exit_status = EExitStatus::kEOF;
1628 else if( fNev == nlast )
1629 exit_status = EExitStatus::kEvLimit;
1630 else if( fatal )
1631 exit_status = EExitStatus::kFatal;
1632 else if( terminate )
1633 exit_status = EExitStatus::kTerminated;
1634
1635 PrintSummary(exit_status);
1636
1637 //keep the last run available
1638 // gHaRun = nullptr;
1639 return SINT(fNev);
1640}
1641
1642//_____________________________________________________________________________
1644{
1645 if (vers != 2 && vers != 3) {
1646 Warning( "THaAnalyzer::SetCodaVersion", "Illegal CODA version = %d. "
1647 "Must be 2 or 3. Setting version to 2.", vers );
1648 vers = 2;
1649 }
1650 fWantCodaVers = vers;
1651}
1652
1653//_____________________________________________________________________________
1655{
1656 // Fill fAnalysisModules in the order fApps, fInterStage, fPhysics to be
1657 // used with PhysicsAnalysis().
1658
1659 fAnalysisModules.clear();
1660 fAnalysisModules.reserve(fApps.size() + fInterStage.size() +
1661 fPhysics.size());
1662 fAnalysisModules.insert(fAnalysisModules.end(), ALL(fApps));
1663 fAnalysisModules.insert(fAnalysisModules.end(), ALL(fInterStage));
1664 fAnalysisModules.insert(fAnalysisModules.end(), ALL(fPhysics));
1665}
1666
1667//_____________________________________________________________________________
1668
int Int_t
unsigned int UInt_t
#define c(i)
#define e(i)
bool Bool_t
const char Option_t
#define gDirectory
winID w
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char text
char name[80]
size_t ListToVector(TList *lst, vector< T * > &vec)
UInt_t IntDigits(Int_t n)
static const vector< ModuleDef > module_list
Definition THaDetMap.cxx:32
R__EXTERN class TList * gHaEvtHandlers
Definition THaGlobals.h:15
R__EXTERN class TList * gHaApps
Definition THaGlobals.h:13
R__EXTERN class THaRunBase * gHaRun
Definition THaGlobals.h:16
R__EXTERN class TList * gHaPhysics
Definition THaGlobals.h:14
R__EXTERN class TClass * gHaDecoder
Definition THaGlobals.h:17
R__EXTERN class THaCutList * gHaCuts
Definition THaGlobals.h:12
static const char *const here
Definition THaVar.cxx:64
#define gROOT
R__EXTERN TSystem * gSystem
virtual void Reset()
virtual void Stop(const char *name)
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
virtual Int_t GetSize() const
UInt_t Convert(Bool_t toGMT=kFALSE) const
const char * AsString() const
Bool_t cd() override
void Purge(Short_t nkeep=1) override
virtual Bool_t cd()
virtual void SetCompressionLevel(Int_t level=ROOT::RCompressionSetting::ELevel::kUseMin)
virtual void Clear(Option_t *="")
virtual void PrintRunSummary() const
THaBenchmark * fBench
virtual bool EvalStage(int n)
UInt_t GetCount(Int_t which) const
virtual ~THaAnalyzer()
virtual void Print(Option_t *opt="") const
static const char *const kDefaultOdefFile
std::vector< THaApparatus * > fApps
virtual void PrintCounters() const
virtual Int_t PhysicsAnalysis(Int_t code)
Bool_t fFirstPhysics
virtual Int_t SetCountMode(Int_t mode)
void SetEpicsEvtType(Int_t itype)
TString fOutFileName
std::vector< THaAnalysisObject * > fAnalysisModules
static THaAnalyzer * fgAnalyzer
virtual Int_t MainAnalysis()
virtual Int_t Process(THaRunBase *run=nullptr)
THaEvData * fEvData
Int_t fWantCodaVers
THaEvent * fEvent
TObject * fExtra
TString fCutFileName
UInt_t Incr(Int_t which)
void EnableRunUpdate(Bool_t b=true)
std::vector< THaPhysicsModule * > fPhysics
Bool_t fDoSlowControl
virtual Int_t BeginAnalysis()
virtual Int_t ReadOneEvent()
Bool_t fDoOtherEvents
THaEvent * fPrevEvent
std::vector< THaEvtTypeHandler * > fEvtHandlers
std::vector< Stage_t > fStages
TString fSummaryFileName
virtual Int_t InitModules(const std::vector< THaAnalysisObject * > &module_list, TDatime &run_time)
void EnablePhysicsEvents(Bool_t b=true)
Bool_t fIsInit
virtual void InitCounters()
UInt_t fMarkInterval
void ClearCounters()
virtual void PrepareModuleList()
Bool_t fDoBench
void EnableOverwrite(Bool_t b=true)
TString fOdefFileName
Int_t fCompress
virtual void InitCuts()
std::vector< THaPostProcess * > fPostProcess
void SetCrateMapFileName(const char *name)
virtual void Close()
THaEvData * GetDecoder() const
virtual void PrintExitStatus(EExitStatus status) const
virtual Int_t Init(THaRunBase *run)
virtual void PrintSummary(EExitStatus exit_status) const
THaOutput * fOutput
void SetCodaVersion(Int_t vers)
THaRunBase * fRun
void EnableBenchmarks(Bool_t b=true)
virtual void PrintCutSummary() const
void EnableOtherEvents(Bool_t b=true)
virtual Int_t DoInit(THaRunBase *run)
TFile * fFile
std::vector< Podd::InterStageModule * > fInterStage
static const char *const kMasterCutName
Bool_t fOverwrite
virtual Int_t SlowControlAnalysis(Int_t code)
THaEpicsEvtHandler * fEpicsHandler
virtual void PrintTimingSummary() const
Bool_t fLocalEvent
std::vector< THaSpectrometer * > fSpectrometers
Bool_t fDoPhysics
Bool_t fUpdateRun
virtual Int_t PostProcess(Int_t code)
Int_t fCountMode
virtual Int_t InitOutput(const std::vector< THaAnalysisObject * > &module_list)
void EnableHelicity(Bool_t b=true)
std::vector< Counter_t > fCounters
virtual Int_t AddInterStage(Podd::InterStageModule *module)
virtual Int_t AddPostProcess(THaPostProcess *module)
virtual void InitStages()
virtual Int_t EndAnalysis()
TString fLoadedCutFileName
void EnableSlowControl(Bool_t b=true)
virtual Int_t OtherAnalysis(Int_t code)
Bool_t HelicityEnabled() const
Definition THaAnalyzer.h:77
void AddEpicsEvtType(Int_t itype)
Bool_t fAnalysisStarted
Bool_t fDoHelicity
virtual void Begin(const char *name)
void PrintByName(const std::vector< TString > &names) const
virtual void Clear(Option_t *opt="")
virtual Int_t Load(const char *filename=kDefaultCutFile)
virtual Int_t EvalBlock(const char *block=kDefaultBlockName)
virtual void Print(Option_t *option="") const
Int_t GetSize() const
Definition THaCutList.h:64
virtual void Compile()
THaNamedList * FindBlock(const char *block) const
Definition THaCutList.h:59
THaCut * FindCut(const char *name) const
Definition THaCutList.h:57
virtual void ClearAll(Option_t *opt="")
Bool_t GetResult() const
Definition THaCut.h:36
virtual Bool_t DataCached()
Definition THaEvData.h:43
void SetDebug(Int_t level)
virtual ULong64_t GetEvTime() const
Definition THaEvData.h:99
UInt_t GetEvType() const
Definition THaEvData.h:53
void SetVerbose(Int_t level)
virtual Int_t LoadEvent(const UInt_t *evbuffer)=0
Bool_t IsPhysicsTrigger() const
Definition THaEvData.h:348
virtual void SetRunTime(ULong64_t tloc)
void SetRunInfo(UInt_t num, UInt_t type, ULong64_t tloc)
static void SetDefaultCrateMapName(const char *name)
virtual Int_t SetDataVersion(Int_t version)
Bool_t HelicityEnabled() const
Definition THaEvData.h:384
void EnableHelicity(Bool_t enable=true)
void SetEpicsEvtType(UInt_t itype)
Definition THaEvData.h:48
UInt_t GetEvNum() const
Definition THaEvData.h:56
virtual Int_t GetHelicity() const
Definition THaEvData.h:101
UInt_t GetTrigBits() const
Definition THaEvData.h:55
UInt_t GetEvLength() const
Definition THaEvData.h:54
void Set(UInt_t num, UInt_t type, UInt_t len, ULong64_t time, Int_t hel, UInt_t tbits, UInt_t run)
Definition THaEvent.h:23
THaEventHeader * GetHeader()
Definition THaEvent.h:61
virtual Int_t Fill()
Definition THaEvent.cxx:48
virtual void Reset(Option_t *opt="")
Definition THaEvent.cxx:191
virtual void AddEvtType(UInt_t evtype)
virtual Bool_t IsMyEvent(UInt_t type) const
virtual UInt_t GetNumTypes()
virtual void SetEvtType(UInt_t evtype)
virtual UInt_t GetEvtType()
virtual Int_t Process()
virtual Int_t Init(const char *filename="output.def")
virtual Int_t ProcEpics(THaEvData *ev, THaEpicsEvtHandler *han)
virtual TTree * GetTree() const
Definition THaOutput.h:82
virtual Int_t End()
virtual Int_t Update(const THaEvData *evdata)
UInt_t GetFirstEvent() const
Definition THaRunBase.h:59
virtual Int_t ReadEvent()=0
virtual Int_t Init()
const TDatime & GetDate() const
Definition THaRunBase.h:52
virtual void Print(Option_t *opt="") const
UInt_t GetLastEvent() const
Definition THaRunBase.h:60
virtual Int_t GetDataVersion()
Definition THaRunBase.h:55
Bool_t IsInit() const
Definition THaRunBase.h:64
UInt_t GetType() const
Definition THaRunBase.h:58
virtual const UInt_t * GetEvBuffer() const =0
virtual Int_t SetDataVersion(Int_t version)
virtual Int_t Close()=0
UInt_t GetNumber() const
Definition THaRunBase.h:57
virtual Int_t Compare(const TObject *obj) const
void IncrNumAnalyzed(Int_t n=1)
Definition THaRunBase.h:51
virtual Int_t Open()=0
const char * GetName() const override
const char * GetTitle() const override
TClass * IsA() const override
virtual void Warning(const char *method, const char *msgfmt,...) const
R__ALWAYS_INLINE Bool_t IsZombie() const
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
virtual void Error(const char *method, const char *msgfmt,...) const
virtual TClass * IsA() const
void MakeZombie()
static Bool_t Initialized()
const char * Data() const
TString & Append(char c, Ssiz_t rep=1)
Bool_t IsNull() const
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
TFile * GetCurrentFile() const
virtual Int_t Branch(const char *folder, Int_t bufsize=32000, Int_t splitlevel=99)
const Int_t n
double T(double x)
STL namespace.
ClassImp(TPyArg)