1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 // Author: Andrei Gheata, 31/05/2006
19 //==============================================================================
20 // AliAnalysisManager - Manager analysis class. Allows creation of several
21 // analysis tasks and data containers storing their input/output. Allows
22 // connecting/chaining tasks via shared data containers. Serializes the current
23 // event for all tasks depending only on initial input data.
24 //==============================================================================
26 //==============================================================================
28 #include "AliAnalysisManager.h"
31 #include <Riostream.h>
36 #include <TTreeCache.h>
40 #include <TMethodCall.h>
45 #include <TStopwatch.h>
48 #include "AliAnalysisSelector.h"
49 #include "AliAnalysisGrid.h"
50 #include "AliAnalysisTask.h"
51 #include "AliAnalysisDataContainer.h"
52 #include "AliAnalysisDataSlot.h"
53 #include "AliVEventHandler.h"
54 #include "AliVEventPool.h"
55 #include "AliSysInfo.h"
56 #include "AliAnalysisStatistics.h"
62 ClassImp(AliAnalysisManager)
64 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
65 TString AliAnalysisManager::fgCommonFileName = "";
66 TString AliAnalysisManager::fgMacroNames = "";
67 Int_t AliAnalysisManager::fPBUpdateFreq = 1;
69 //______________________________________________________________________________
70 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
73 fInputEventHandler(0),
74 fOutputEventHandler(0),
75 fMCtruthEventHandler(0),
79 fMode(kLocalAnalysis),
85 fSpecialOutputLocation(""),
94 fFileDescriptors(new TObjArray()),
95 fCurrentDescriptor(0),
102 fAutoBranchHandling(kTRUE),
103 fAsyncReading(kFALSE), // default prefetching on
108 fCacheSize(100000000), // default 100 MB
110 fRequestedBranches(),
120 // Default constructor.
121 fgAnalysisManager = this;
122 fgCommonFileName = "AnalysisResults.root";
123 if (TClass::IsCallingNew() != TClass::kDummyNew) {
124 fTasks = new TObjArray();
125 fTopTasks = new TObjArray();
126 fZombies = new TObjArray();
127 fContainers = new TObjArray();
128 fInputs = new TObjArray();
129 fOutputs = new TObjArray();
130 fParamCont = new TObjArray();
131 fGlobals = new TMap();
133 fIOTimer = new TStopwatch();
134 fCPUTimer = new TStopwatch();
135 fInitTimer = new TStopwatch();
139 //______________________________________________________________________________
140 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
143 fInputEventHandler(NULL),
144 fOutputEventHandler(NULL),
145 fMCtruthEventHandler(NULL),
150 fInitOK(other.fInitOK),
151 fMustClean(other.fMustClean),
152 fIsRemote(other.fIsRemote),
153 fLocked(other.fLocked),
154 fDebug(other.fDebug),
155 fSpecialOutputLocation(""),
164 fFileDescriptors(new TObjArray()),
165 fCurrentDescriptor(0),
170 fExtraFiles(other.fExtraFiles),
171 fFileInfoLog(other.fFileInfoLog),
172 fAutoBranchHandling(other.fAutoBranchHandling),
173 fAsyncReading(other.fAsyncReading),
176 fNcalls(other.fNcalls),
177 fMaxEntries(other.fMaxEntries),
178 fCacheSize(other.fCacheSize),
179 fStatisticsMsg(other.fStatisticsMsg),
180 fRequestedBranches(other.fRequestedBranches),
181 fStatistics(other.fStatistics),
182 fGlobals(other.fGlobals),
183 fIOTimer(new TStopwatch()),
184 fCPUTimer(new TStopwatch()),
185 fInitTimer(new TStopwatch()),
191 fTasks = new TObjArray(*other.fTasks);
192 fTopTasks = new TObjArray(*other.fTopTasks);
193 fZombies = new TObjArray(*other.fZombies);
194 fContainers = new TObjArray(*other.fContainers);
195 fInputs = new TObjArray(*other.fInputs);
196 fOutputs = new TObjArray(*other.fOutputs);
197 fParamCont = new TObjArray(*other.fParamCont);
198 fgCommonFileName = "AnalysisResults.root";
199 fgAnalysisManager = this;
202 //______________________________________________________________________________
203 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
206 if (&other != this) {
207 TNamed::operator=(other);
208 fInputEventHandler = other.fInputEventHandler;
209 fOutputEventHandler = other.fOutputEventHandler;
210 fMCtruthEventHandler = other.fMCtruthEventHandler;
211 fEventPool = other.fEventPool;
214 fNSysInfo = other.fNSysInfo;
216 fInitOK = other.fInitOK;
217 fIsRemote = other.fIsRemote;
218 fLocked = other.fLocked;
219 fDebug = other.fDebug;
220 fTasks = new TObjArray(*other.fTasks);
221 fTopTasks = new TObjArray(*other.fTopTasks);
222 fZombies = new TObjArray(*other.fZombies);
223 fContainers = new TObjArray(*other.fContainers);
224 fInputs = new TObjArray(*other.fInputs);
225 fOutputs = new TObjArray(*other.fOutputs);
226 fParamCont = new TObjArray(*other.fParamCont);
227 fDebugOptions = NULL;
228 fFileDescriptors = new TObjArray();
229 fCurrentDescriptor = 0;
231 fCommonOutput = NULL;
234 fExtraFiles = other.fExtraFiles;
235 fFileInfoLog = other.fFileInfoLog;
236 fgCommonFileName = "AnalysisResults.root";
237 fgAnalysisManager = this;
238 fAutoBranchHandling = other.fAutoBranchHandling;
239 fAsyncReading = other.fAsyncReading;
240 fTable.Clear("nodelete");
241 fRunFromPath = other.fRunFromPath;
242 fNcalls = other. fNcalls;
243 fMaxEntries = other.fMaxEntries;
244 fCacheSize = other.fCacheSize;
245 fStatisticsMsg = other.fStatisticsMsg;
246 fRequestedBranches = other.fRequestedBranches;
247 fStatistics = other.fStatistics;
248 fGlobals = new TMap();
249 fIOTimer = new TStopwatch();
250 fCPUTimer = new TStopwatch();
251 fInitTimer = new TStopwatch();
259 //______________________________________________________________________________
260 AliAnalysisManager::~AliAnalysisManager()
263 if (fTasks) {fTasks->Delete(); delete fTasks;}
264 if (fTopTasks) delete fTopTasks;
265 if (fZombies) delete fZombies;
266 if (fContainers) {fContainers->Delete(); delete fContainers;}
267 if (fInputs) delete fInputs;
268 if (fOutputs) delete fOutputs;
269 if (fParamCont) delete fParamCont;
270 if (fDebugOptions) delete fDebugOptions;
271 if (fGridHandler) delete fGridHandler;
272 if (fInputEventHandler) delete fInputEventHandler;
273 if (fOutputEventHandler) delete fOutputEventHandler;
274 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
275 if (fEventPool) delete fEventPool;
276 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
277 if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
278 if (fFileDescriptors) {fFileDescriptors->Delete(); delete fFileDescriptors;}
284 //______________________________________________________________________________
285 void AliAnalysisManager::CreateReadCache()
287 // Create cache for reading according fCacheSize and fAsyncReading.
288 if (!fTree || !fTree->GetCurrentFile()) {
289 Error("CreateReadCache","Current tree or tree file not yet defined");
293 if (fDebug) Info("CreateReadCache","=== Read caching disabled ===");
296 gEnv->SetValue("TFile.AsyncPrefetching",(Int_t)fAsyncReading);
297 if (fAsyncReading) gEnv->SetValue("Cache.Directory",Form("file://%s/cache", gSystem->WorkingDirectory()));
298 if (fAsyncReading) gEnv->SetValue("TFile.AsyncReading",1);
299 fTree->SetCacheSize(fCacheSize);
300 TTreeCache::SetLearnEntries(1); //<<< we can take the decision after 1 entry
301 fTree->AddBranchToCache("*",kTRUE); //<<< add all branches to the cache
303 Info("CreateReadCache","Read cache enabled %lld bytes with async reading=%d",fCacheSize, (Int_t)fAsyncReading);
308 //______________________________________________________________________________
309 Bool_t AliAnalysisManager::EventLoop(Long64_t nevents)
311 // Initialize an event loop where the data producer is the input handler
312 // The handler must implement MakeTree creating the tree of events (likely
313 // memory resident) and generate the current event in the method BeginEvent.
314 // If the tree is memory resident, the handler should never call TTree::Fill
316 cout << "===== RUNNING IN EVENT LOOP MODE: " << GetName() << endl;
317 if (!fInputEventHandler) {
318 Error("EventLoop", "No input handler: exiting");
321 TTree *tree = new TTree("DummyTree", "Dummy tree for AliAnalysisManager::EventLoop");
322 SetExternalLoop(kTRUE);
323 if (!Init(tree)) return kFALSE;
325 for (Long64_t iev=0; iev<nevents; iev++)
328 PackOutput(&dummyList);
333 //______________________________________________________________________________
334 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
336 // Read one entry of the tree or a whole branch.
337 fCurrentEntry = entry;
338 if (!fAutoBranchHandling)
340 if (!fTree || !fTree->GetTree()) return -1;
341 fIOTimer->Start(kTRUE);
342 Long64_t readbytes = fTree->GetTree()->GetEntry(entry, getall);
344 fIOTime += fIOTimer->RealTime();
345 return (Int_t)readbytes;
348 //______________________________________________________________________________
349 Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
351 // Attempt to extract run number from input data path. Works only for paths to
352 // alice data in alien.
353 // sim: /alice/sim/<production>/run_no/...
354 // data: /alice/data/year/period/000run_no/... (ESD or AOD)
355 TString type = "unknown";
357 if (s.Contains("/alice/data")) type = "real";
358 else if (s.Contains("/alice/sim")) type = "simulated";
361 ind1 = s.Index("/00");
363 ind2 = s.Index("/",ind1+1);
364 if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
367 ind1 = s.Index("/LHC");
369 ind1 = s.Index("/",ind1+1);
371 ind2 = s.Index("/",ind1+1);
372 if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
376 Int_t run = srun.Atoi();
377 if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
381 //______________________________________________________________________________
382 Bool_t AliAnalysisManager::Init(TTree *tree)
384 // The Init() function is called when the selector needs to initialize
385 // a new tree or chain. Typically here the branch addresses of the tree
386 // will be set. It is normaly not necessary to make changes to the
387 // generated code, but the routine can be extended by the user if needed.
388 // Init() will be called many times when running with PROOF.
389 Bool_t init = kFALSE;
390 if (!tree) return kFALSE; // Should not happen - protected in selector caller
392 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
394 // Call InitTree of EventHandler
395 if (fOutputEventHandler) {
396 if (fMode == kProofAnalysis) {
397 init = fOutputEventHandler->Init(0x0, "proof");
399 init = fOutputEventHandler->Init(0x0, "local");
402 Error("Init", "Output event handler failed to initialize");
407 if (fInputEventHandler) {
408 if (fMode == kProofAnalysis) {
409 init = fInputEventHandler->Init(tree, "proof");
411 init = fInputEventHandler->Init(tree, "local");
414 Error("Init", "Input event handler failed to initialize tree");
418 // If no input event handler we need to get the tree once
420 if(!tree->GetTree()) {
421 Long64_t readEntry = tree->LoadTree(0);
422 if (readEntry == -2) {
423 Error("Init", "Input tree has no entry. Exiting");
429 if (fMCtruthEventHandler) {
430 if (fMode == kProofAnalysis) {
431 init = fMCtruthEventHandler->Init(0x0, "proof");
433 init = fMCtruthEventHandler->Init(0x0, "local");
436 Error("Init", "MC event handler failed to initialize");
441 if (!fInitOK) InitAnalysis();
442 if (!fInitOK) return kFALSE;
444 if (fMode != kProofAnalysis) CreateReadCache();
446 AliAnalysisDataContainer *top = fCommonInput;
447 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
449 Error("Init","No top input container !");
453 CheckBranches(kFALSE);
455 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
460 //______________________________________________________________________________
461 void AliAnalysisManager::SlaveBegin(TTree *tree)
463 // The SlaveBegin() function is called after the Begin() function.
464 // When running with PROOF SlaveBegin() is called on each slave server.
465 // The tree argument is deprecated (on PROOF 0 is passed).
466 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
467 // Init timer should be already started
468 // Apply debug options
471 fMCtruthEventHandler &&
472 (fMode != kProofAnalysis)) fMCtruthEventHandler->SetCacheSize(fCacheSize);
473 if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
474 static Bool_t isCalled = kFALSE;
475 Bool_t init = kFALSE;
476 Bool_t initOK = kTRUE;
478 TDirectory *curdir = gDirectory;
479 // Call SlaveBegin only once in case of mixing
480 if (isCalled && fMode==kMixingAnalysis) return;
482 // Call Init of EventHandler
483 if (fOutputEventHandler) {
484 if (fMode == kProofAnalysis) {
485 // Merging AOD's in PROOF via TProofOutputFile
486 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
487 init = fOutputEventHandler->Init("proof");
488 if (!init) msg = "Failed to initialize output handler on worker";
490 init = fOutputEventHandler->Init("local");
491 if (!init) msg = "Failed to initialize output handler";
494 if (!fSelector) Error("SlaveBegin", "Selector not set");
495 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
498 if (fInputEventHandler) {
499 fInputEventHandler->SetInputTree(tree);
500 if (fMode == kProofAnalysis) {
501 init = fInputEventHandler->Init("proof");
502 if (!init) msg = "Failed to initialize input handler on worker";
504 init = fInputEventHandler->Init("local");
505 if (!init) msg = "Failed to initialize input handler";
508 if (!fSelector) Error("SlaveBegin", "Selector not set");
509 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
512 if (fMCtruthEventHandler) {
513 if (fMode == kProofAnalysis) {
514 init = fMCtruthEventHandler->Init("proof");
515 if (!init) msg = "Failed to initialize MC handler on worker";
517 init = fMCtruthEventHandler->Init("local");
518 if (!init) msg = "Failed to initialize MC handler";
521 if (!fSelector) Error("SlaveBegin", "Selector not set");
522 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
524 if (curdir) curdir->cd();
528 AliAnalysisTask *task;
529 // Call CreateOutputObjects for all tasks
530 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
531 Bool_t dirStatus = TH1::AddDirectoryStatus();
533 while ((task=(AliAnalysisTask*)next())) {
535 // Start with memory as current dir and make sure by default histograms do not get attached to files.
536 TH1::AddDirectory(kFALSE);
537 task->CreateOutputObjects();
538 if (!task->CheckPostData()) {
539 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
540 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
541 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
543 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
546 TH1::AddDirectory(dirStatus);
547 if (curdir) curdir->cd();
549 fInitTime += fInitTimer->RealTime();
550 fInitTimer->Continue();
551 printf("Initialization time: %g [sec]\n", fInitTime);
552 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
555 //______________________________________________________________________________
556 Bool_t AliAnalysisManager::Notify()
558 // The Notify() function is called when a new file is opened. This
559 // can be either for a new TTree in a TChain or when when a new TTree
560 // is started when using PROOF. It is normaly not necessary to make changes
561 // to the generated code, but the routine can be extended by the
562 // user if needed. The return value is currently not used.
563 fIOTimer->Start(kTRUE);
564 if (!fTree) return kFALSE;
565 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
567 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
568 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
570 TFile *curfile = fTree->GetCurrentFile();
572 Error("Notify","No current file");
575 if (IsCollectThroughput()) {
576 if (fCurrentDescriptor) fCurrentDescriptor->Done();
577 fCurrentDescriptor = new AliAnalysisFileDescriptor(curfile);
578 fFileDescriptors->Add(fCurrentDescriptor);
581 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
582 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
583 if (run && (run != fRunFromPath)) {
585 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
588 AliAnalysisTask *task;
590 // Call Notify of the event handlers
591 if (fInputEventHandler) {
592 fInputEventHandler->Notify(curfile->GetName());
595 if (fOutputEventHandler) {
596 fOutputEventHandler->Notify(curfile->GetName());
599 if (fMCtruthEventHandler) {
600 fMCtruthEventHandler->Notify(curfile->GetName());
603 // Call Notify for all tasks
604 while ((task=(AliAnalysisTask*)next()))
607 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
609 fIOTime += fIOTimer->RealTime();
613 //______________________________________________________________________________
614 Bool_t AliAnalysisManager::Process(Long64_t)
616 // The Process() function is called for each entry in the tree (or possibly
617 // keyed object in the case of PROOF) to be processed. The entry argument
618 // specifies which entry in the currently loaded tree is to be processed.
619 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
620 // to read either all or the required parts of the data. When processing
621 // keyed objects with PROOF, the object is already loaded and is available
622 // via the fObject pointer.
624 // This function should contain the "body" of the analysis. It can contain
625 // simple or elaborate selection criteria, run algorithms on the data
626 // of the event and typically fill histograms.
628 // WARNING when a selector is used with a TChain, you must use
629 // the pointer to the current TTree to call GetEntry(entry).
630 // The entry is always the local entry number in the current tree.
631 // Assuming that fChain is the pointer to the TChain being processed,
632 // use fChain->GetTree()->GetEntry(entry).
634 // This method is obsolete. ExecAnalysis is called instead.
638 //______________________________________________________________________________
639 void AliAnalysisManager::PackOutput(TList *target)
641 // Pack all output data containers in the output list. Called at SlaveTerminate
642 // stage in PROOF case for each slave.
643 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
644 fIOTimer->Start(kTRUE);
646 if (IsCollectThroughput()) {
647 if (fCurrentDescriptor) fCurrentDescriptor->Done();
648 fFileDescriptors->Print();
649 if (fFileInfoLog.IsNull()) fFileInfoLog = "fileinfo.log";
650 out.open(fFileInfoLog, std::ios::app);
651 if (out.bad()) Error("SavePrimitive", "Bad file name: %s", fFileInfoLog.Data());
653 TIter nextflog(fFileDescriptors);
655 while ((log=nextflog())) log->SavePrimitive(out,"");
659 Error("PackOutput", "No target. Exiting.");
662 TDirectory *cdir = gDirectory;
664 if (fInputEventHandler) fInputEventHandler ->Terminate();
665 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
666 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
669 // Call FinishTaskOutput() for each event loop task (not called for
670 // post-event loop tasks - use Terminate() fo those)
671 TIter nexttask(fTasks);
672 AliAnalysisTask *task;
673 while ((task=(AliAnalysisTask*)nexttask())) {
674 if (!task->IsPostEventLoop()) {
675 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
676 task->FinishTaskOutput();
678 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
681 // Write statistics message on the workers.
682 if (fStatistics) WriteStatisticsMsg(fNcalls);
684 if (fMode == kProofAnalysis) {
685 TIter next(fOutputs);
686 AliAnalysisDataContainer *output;
687 Bool_t isManagedByHandler = kFALSE;
690 while ((output=(AliAnalysisDataContainer*)next())) {
691 // Do not consider outputs of post event loop tasks
692 isManagedByHandler = kFALSE;
693 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
694 const char *filename = output->GetFileName();
695 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
696 isManagedByHandler = kTRUE;
697 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
698 filename = fOutputEventHandler->GetOutputFileName();
700 // Check if data was posted to this container. If not, issue an error.
701 if (!output->GetData() && !isManagedByHandler) {
702 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
705 if (!output->IsSpecialOutput()) {
707 if (strlen(filename) && !isManagedByHandler) {
708 // Backup current folder
709 TDirectory *opwd = gDirectory;
710 // File resident outputs.
711 // Check first if the file exists.
712 TString openoption = "RECREATE";
713 Bool_t firsttime = kTRUE;
714 if (filestmp.FindObject(output->GetFileName())) {
717 filestmp.Add(new TNamed(output->GetFileName(),""));
719 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
720 // TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
721 // Save data to file, then close.
722 if (output->GetData()->InheritsFrom(TCollection::Class())) {
723 // If data is a collection, we set the name of the collection
724 // as the one of the container and we save as a single key.
725 TCollection *coll = (TCollection*)output->GetData();
726 coll->SetName(output->GetName());
727 // coll->Write(output->GetName(), TObject::kSingleKey);
729 if (output->GetData()->InheritsFrom(TTree::Class())) {
730 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
731 // Save data to file, then close.
732 TTree *tree = (TTree*)output->GetData();
733 // Check if tree is in memory
734 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
738 // output->GetData()->Write();
741 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
743 // printf(" file %s listing content:\n", filename);
746 // Clear file list to release object ownership to user.
749 output->SetFile(NULL);
750 // Restore current directory
751 if (opwd) opwd->cd();
753 // Memory-resident outputs
754 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
756 AliAnalysisDataWrapper *wrap = 0;
757 if (isManagedByHandler) {
758 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
759 wrap->SetName(output->GetName());
761 else wrap =output->ExportData();
762 // Output wrappers must NOT delete data after merging - the user owns them
763 wrap->SetDeleteData(kFALSE);
766 // Special outputs. The file must be opened and connected to the container.
767 TDirectory *opwd = gDirectory;
768 TFile *file = output->GetFile();
770 AliAnalysisTask *producer = output->GetProducer();
772 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
773 output->GetFileName(), output->GetName(), producer->ClassName());
776 TString outFilename = file->GetName();
777 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
778 if (isManagedByHandler) {
779 // Terminate IO for files managed by the output handler
780 // file->Write() moved to AOD handler (A.G. 11.01.10)
781 // if (file) file->Write();
782 if (file && fDebug > 2) {
783 printf(" handled file %s listing content:\n", file->GetName());
786 fOutputEventHandler->TerminateIO();
789 // Release object ownership to users after writing data to file
790 if (output->GetData()->InheritsFrom(TCollection::Class())) {
791 // If data is a collection, we set the name of the collection
792 // as the one of the container and we save as a single key.
793 TCollection *coll = (TCollection*)output->GetData();
794 coll->SetName(output->GetName());
795 coll->Write(output->GetName(), TObject::kSingleKey);
797 if (output->GetData()->InheritsFrom(TTree::Class())) {
798 TTree *tree = (TTree*)output->GetData();
799 tree->SetDirectory(file);
802 output->GetData()->Write();
806 printf(" file %s listing content:\n", output->GetFileName());
809 // Clear file list to release object ownership to user.
812 output->SetFile(NULL);
814 // Restore current directory
815 if (opwd) opwd->cd();
816 // Check if a special output location was provided or the output files have to be merged
817 if (strlen(fSpecialOutputLocation.Data())) {
818 TString remote = fSpecialOutputLocation;
820 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
821 if (remote.BeginsWith("alien:")) {
822 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
823 remote += outFilename;
824 remote.ReplaceAll(".root", Form("_%d.root", gid));
826 remote += Form("%s_%d_", gSystem->HostName(), gid);
827 remote += outFilename;
830 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
831 output->GetName(), remote.Data());
832 TFile::Cp ( outFilename.Data(), remote.Data() );
833 // Copy extra outputs
834 if (fExtraFiles.Length() && isManagedByHandler) {
835 TObjArray *arr = fExtraFiles.Tokenize(" ");
837 TIter nextfilename(arr);
838 while ((os=(TObjString*)nextfilename())) {
839 outFilename = os->GetString();
840 remote = fSpecialOutputLocation;
842 if (remote.BeginsWith("alien://")) {
843 remote += outFilename;
844 remote.ReplaceAll(".root", Form("_%d.root", gid));
846 remote += Form("%s_%d_", gSystem->HostName(), gid);
847 remote += outFilename;
850 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
851 outFilename.Data(), remote.Data());
852 TFile::Cp ( outFilename.Data(), remote.Data() );
857 // No special location specified-> use TProofOutputFile as merging utility
858 // The file at this output slot must be opened in CreateOutputObjects
859 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
864 fIOTime += fIOTimer->RealTime();
865 if ((fDebug || IsCollectThroughput())) {
867 fInitTime = fInitTimer->RealTime()-fIOTime-fCPUTime;
868 printf("=Analysis %s= init time: %g[sec]\
869 \n I/O & data mng.: %g [sec]\
870 \n task execution: %g [sec]\
871 \n total time: CPU=%g [sec] REAL=%g[sec]\n",
872 GetName(), fInitTime, fIOTime, fCPUTime, fInitTimer->CpuTime(), fInitTimer->RealTime());
873 if (IsCollectThroughput()) {
874 out << "#summary#########################################################" << endl;
875 out << "train_name " << GetName() << endl;
876 out << "root_time " << fInitTimer->RealTime() << endl;
877 out << "root_cpu " << fInitTimer->CpuTime() << endl;
878 out << "init_time " << fInitTime << endl;
879 out << "io_mng_time " << fIOTime << endl;
880 out << "exec_time " << fCPUTime << endl;
881 TString aliensite = gSystem->Getenv("ALIEN_SITE");
882 out << "alien_site " << aliensite << endl;
884 TString hostname = gSystem->Getenv("ALIEN_HOSTNAME");
885 if (hostname.IsNull()) {
887 gSystem->Exec(Form("hostname -f >> %s", fFileInfoLog.Data()));
889 out << hostname << endl;
894 if (cdir) cdir->cd();
895 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
898 //______________________________________________________________________________
899 void AliAnalysisManager::ImportWrappers(TList *source)
901 // Import data in output containers from wrappers coming in source.
902 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
903 fIOTimer->Start(kTRUE);
904 TIter next(fOutputs);
905 AliAnalysisDataContainer *cont;
906 AliAnalysisDataWrapper *wrap;
908 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
909 TDirectory *cdir = gDirectory;
910 while ((cont=(AliAnalysisDataContainer*)next())) {
912 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
913 if (cont->IsRegisterDataset()) continue;
914 const char *filename = cont->GetFileName();
915 Bool_t isManagedByHandler = kFALSE;
916 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
917 isManagedByHandler = kTRUE;
918 filename = fOutputEventHandler->GetOutputFileName();
920 if (cont->IsSpecialOutput() || inGrid) {
921 if (strlen(fSpecialOutputLocation.Data())) continue;
922 // Copy merged file from PROOF scratch space.
923 // In case of grid the files are already in the current directory.
925 if (isManagedByHandler && fExtraFiles.Length()) {
926 // Copy extra registered dAOD files.
927 TObjArray *arr = fExtraFiles.Tokenize(" ");
929 TIter nextfilename(arr);
930 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
933 if (!GetFileFromWrapper(filename, source)) continue;
935 // Normally we should connect data from the copied file to the
936 // corresponding output container, but it is not obvious how to do this
937 // automatically if several objects in file...
938 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
939 if (!f) f = TFile::Open(filename, "READ");
941 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
946 // Cd to the directory pointed by the container
947 TString folder = cont->GetFolderName();
948 if (!folder.IsNull()) f->cd(folder);
949 // Try to fetch first an object having the container name.
950 obj = gDirectory->Get(cont->GetName());
952 Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList",
953 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
956 wrap = new AliAnalysisDataWrapper(obj);
957 wrap->SetDeleteData(kFALSE);
959 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
961 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
966 printf(" Importing data for container %s\n", cont->GetName());
967 if (strlen(filename)) printf(" -> file %s\n", filename);
970 cont->ImportData(wrap);
972 if (cdir) cdir->cd();
974 fIOTime += fIOTimer->RealTime();
975 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
978 //______________________________________________________________________________
979 void AliAnalysisManager::UnpackOutput(TList *source)
981 // Called by AliAnalysisSelector::Terminate only on the client.
982 fIOTimer->Start(kTRUE);
983 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
985 Error("UnpackOutput", "No target. Exiting.");
988 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
990 if (fMode == kProofAnalysis) ImportWrappers(source);
992 TIter next(fOutputs);
993 AliAnalysisDataContainer *output;
994 while ((output=(AliAnalysisDataContainer*)next())) {
995 if (!output->GetData()) continue;
996 // Check if there are client tasks that run post event loop
997 if (output->HasConsumers()) {
998 // Disable event loop semaphore
999 output->SetPostEventLoop(kTRUE);
1000 TObjArray *list = output->GetConsumers();
1001 Int_t ncons = list->GetEntriesFast();
1002 for (Int_t i=0; i<ncons; i++) {
1003 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
1004 task->CheckNotify(kTRUE);
1005 // If task is active, execute it
1006 if (task->IsPostEventLoop() && task->IsActive()) {
1007 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
1008 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
1009 task->ExecuteTask();
1012 if (fStatistics) fStatistics->StopTimer();
1016 fIOTime += fIOTimer->RealTime();
1017 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
1020 //______________________________________________________________________________
1021 void AliAnalysisManager::Terminate()
1023 // The Terminate() function is the last function to be called during
1024 // a query. It always runs on the client, it can be used to present
1025 // the results graphically.
1026 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
1027 fInitTimer->Start(kTRUE);
1028 TDirectory *cdir = gDirectory;
1030 AliAnalysisTask *task;
1031 AliAnalysisDataContainer *output;
1034 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1035 // Call Terminate() for tasks
1037 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
1038 // Save all the canvases produced by the Terminate
1039 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
1043 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
1045 if (TObject::TestBit(kSaveCanvases)) {
1046 if (!gROOT->IsBatch()) {
1047 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
1049 while (timer.RealTime()<5) {
1051 gSystem->ProcessEvents();
1054 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
1055 if (iend==0) continue;
1057 for (Int_t ipict=0; ipict<iend; ipict++) {
1058 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
1059 if (!canvas) continue;
1060 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
1062 gROOT->GetListOfCanvases()->Delete();
1066 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
1067 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
1068 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
1070 TObjArray *allOutputs = new TObjArray();
1072 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
1073 if (!IsSkipTerminate())
1074 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
1075 TIter next1(allOutputs);
1076 TString handlerFile = "";
1077 TString extraOutputs = "";
1078 if (fOutputEventHandler) {
1079 handlerFile = fOutputEventHandler->GetOutputFileName();
1080 extraOutputs = fOutputEventHandler->GetExtraOutputs();
1084 while ((output=(AliAnalysisDataContainer*)next1())) {
1085 // Special outputs or grid files have the files already closed and written.
1087 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
1088 if (fMode == kProofAnalysis) {
1089 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
1091 const char *filename = output->GetFileName();
1092 TString openoption = "RECREATE";
1093 if (!(strcmp(filename, "default"))) continue;
1094 if (!strlen(filename)) continue;
1095 if (!output->GetData()) continue;
1096 TDirectory *opwd = gDirectory;
1097 TFile *file = output->GetFile();
1098 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1100 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
1101 Bool_t firsttime = kTRUE;
1102 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
1105 filestmp.Add(new TNamed(filename,""));
1107 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
1108 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
1109 file = new TFile(filename, openoption);
1111 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
1112 openoption = file->GetOption();
1113 if (openoption == "READ") {
1114 if (fDebug>1) printf("...reopening in UPDATE mode\n");
1115 file->ReOpen("UPDATE");
1118 if (file->IsZombie()) {
1119 Error("Terminate", "Cannot open output file %s", filename);
1122 output->SetFile(file);
1124 // Check for a folder request
1125 TString dir = output->GetFolderName();
1126 if (!dir.IsNull()) {
1127 if (!file->GetDirectory(dir)) file->mkdir(dir);
1130 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1131 if (output->GetData()->InheritsFrom(TCollection::Class())) {
1132 // If data is a collection, we set the name of the collection
1133 // as the one of the container and we save as a single key.
1134 TCollection *coll = (TCollection*)output->GetData();
1135 coll->SetName(output->GetName());
1136 coll->Write(output->GetName(), TObject::kSingleKey);
1138 if (output->GetData()->InheritsFrom(TTree::Class())) {
1139 TTree *tree = (TTree*)output->GetData();
1140 tree->SetDirectory(gDirectory);
1143 output->GetData()->Write();
1146 if (opwd) opwd->cd();
1150 TString copiedFiles;
1151 while ((output=(AliAnalysisDataContainer*)next1())) {
1152 // Close all files at output
1153 TDirectory *opwd = gDirectory;
1154 if (output->GetFile()) {
1155 // Clear file list to release object ownership to user.
1156 // output->GetFile()->Clear();
1157 output->GetFile()->Close();
1158 // Copy merged outputs in alien if requested
1159 if (fSpecialOutputLocation.BeginsWith("alien://")) {
1160 if (copiedFiles.Contains(output->GetFile()->GetName())) {
1161 if (opwd) opwd->cd();
1162 output->SetFile(NULL);
1165 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
1166 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
1167 TFile::Cp(output->GetFile()->GetName(),
1168 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
1169 copiedFiles += output->GetFile()->GetName();
1171 output->SetFile(NULL);
1173 if (opwd) opwd->cd();
1176 //Write statistics information on the client
1177 if (fStatistics) WriteStatisticsMsg(fNcalls);
1179 TDirectory *crtdir = gDirectory;
1180 TFile f("syswatch.root", "RECREATE");
1183 if (!f.IsZombie()) {
1184 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1185 tree->SetName("syswatch");
1186 tree->SetMarkerStyle(kCircle);
1187 tree->SetMarkerColor(kBlue);
1188 tree->SetMarkerSize(0.5);
1189 if (!gROOT->IsBatch()) {
1190 tree->SetAlias("event", "id0");
1191 tree->SetAlias("task", "id1");
1192 tree->SetAlias("stage", "id2");
1193 // Already defined aliases
1194 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1195 // tree->SetAlias("T","stampSec-first");
1196 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1197 // tree->SetAlias("VM","pI.fMemVirtual");
1198 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1199 Int_t npads = 1 /*COO plot for all tasks*/ +
1200 fTopTasks->GetEntries() /*Exec plot per task*/ +
1201 1 /*Terminate plot for all tasks*/ +
1204 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1205 if (npads<iopt*(iopt+1))
1206 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1208 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1210 // draw the plot of deltaVM for Exec for each task
1211 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1212 task = (AliAnalysisTask*)fTopTasks->At(itask);
1214 cut = Form("task==%d && stage==1", itask);
1215 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1216 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1218 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1219 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1222 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1224 tree->SetMarkerStyle(kFullTriangleUp);
1225 tree->SetMarkerColor(kRed);
1226 tree->SetMarkerSize(0.8);
1227 cut = "task>=0 && task<1000 && stage==0";
1228 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1229 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1231 hist->SetTitle("Memory in CreateOutputObjects()");
1232 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1233 hist->GetXaxis()->SetTitle("task");
1235 // draw the plot of deltaVM for Terminate for all tasks
1237 tree->SetMarkerStyle(kOpenSquare);
1238 tree->SetMarkerColor(kMagenta);
1239 cut = "task>=0 && task<1000 && stage==2";
1240 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1241 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1243 hist->SetTitle("Memory in Terminate()");
1244 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1245 hist->GetXaxis()->SetTitle("task");
1249 tree->SetMarkerStyle(kFullCircle);
1250 tree->SetMarkerColor(kGreen);
1251 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1252 tree->Draw("VM:event",cut,"", 1234567890, 0);
1253 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1255 hist->SetTitle("Virtual memory");
1256 hist->GetYaxis()->SetTitle("VM [MB]");
1260 tree->SetMarkerStyle(kCircle);
1261 tree->SetMarkerColor(kBlue);
1262 tree->SetMarkerSize(0.5);
1267 if (crtdir) crtdir->cd();
1269 // Validate the output files
1270 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1272 out.open("outputs_valid", ios::out);
1275 if (cdir) cdir->cd();
1277 if (fDebug || IsCollectThroughput()) {
1278 printf("=Analysis %s= Terminate time: %g[sec]\n", GetName(), fInitTimer->RealTime());
1280 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1282 //______________________________________________________________________________
1283 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1285 // Profiles the task having the itop index in the list of top (first level) tasks.
1286 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1288 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1291 ProfileTask(task->GetName(), option);
1294 //______________________________________________________________________________
1295 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1297 // Profile a managed task after the execution of the analysis in case NSysInfo
1299 if (gSystem->AccessPathName("syswatch.root")) {
1300 Error("ProfileTask", "No file syswatch.root found in the current directory");
1303 if (gROOT->IsBatch()) return;
1304 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1306 Error("ProfileTask", "No top task named %s known by the manager.", name);
1309 Int_t itop = fTopTasks->IndexOf(task);
1310 Int_t itask = fTasks->IndexOf(task);
1311 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1312 TDirectory *cdir = gDirectory;
1313 TFile f("syswatch.root");
1314 TTree *tree = (TTree*)f.Get("syswatch");
1316 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1319 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1320 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1321 canvas->Divide(2, 2, 0.01, 0.01);
1325 // VM profile for COO and Terminate methods
1327 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1328 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1329 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1331 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1332 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1333 hist->GetXaxis()->SetTitle("method");
1335 // CPU profile per event
1337 cut = Form("task==%d && stage==1",itop);
1338 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1339 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1341 hist->SetTitle("Execution time per event");
1342 hist->GetYaxis()->SetTitle("CPU/event [s]");
1344 // VM profile for Exec
1346 cut = Form("task==%d && stage==1",itop);
1347 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1348 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1350 hist->SetTitle("Alocated VM[MB] per event");
1351 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1356 if (cdir) cdir->cd();
1359 //______________________________________________________________________________
1360 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1362 // Adds a user task to the global list of tasks.
1364 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1368 if (fTasks->FindObject(task)) {
1369 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1372 task->SetActive(kFALSE);
1376 //______________________________________________________________________________
1377 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1379 // Retreive task by name.
1380 if (!fTasks) return NULL;
1381 return (AliAnalysisTask*)fTasks->FindObject(name);
1384 //______________________________________________________________________________
1385 Int_t AliAnalysisManager::GetTaskIndex(const AliAnalysisTask *task) const
1387 // Returns task inded in the manager's list, -1 if not registered.
1388 if (!fTasks) return -1;
1389 return fTasks->IndexOf(task);
1392 //______________________________________________________________________________
1393 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1394 TClass *datatype, EAliAnalysisContType type, const char *filename)
1396 // Create a data container of a certain type. Types can be:
1397 // kExchangeContainer = 0, used to exchange data between tasks
1398 // kInputContainer = 1, used to store input data
1399 // kOutputContainer = 2, used for writing result to a file
1400 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1401 // the output object to a folder inside the output file
1402 if (fContainers->FindObject(name)) {
1403 Error("CreateContainer","A container named %s already defined !",name);
1406 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1407 fContainers->Add(cont);
1409 case kInputContainer:
1412 case kOutputContainer:
1413 fOutputs->Add(cont);
1414 if (filename && strlen(filename)) {
1415 cont->SetFileName(filename);
1416 cont->SetDataOwned(kFALSE); // data owned by the file
1419 case kParamContainer:
1420 fParamCont->Add(cont);
1421 if (filename && strlen(filename)) {
1422 cont->SetFileName(filename);
1423 cont->SetDataOwned(kFALSE); // data owned by the file
1426 case kExchangeContainer:
1432 //______________________________________________________________________________
1433 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1434 AliAnalysisDataContainer *cont)
1436 // Connect input of an existing task to a data container.
1438 Error("ConnectInput", "Task pointer is NULL");
1441 if (!fTasks->FindObject(task)) {
1443 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1445 Bool_t connected = task->ConnectInput(islot, cont);
1449 //______________________________________________________________________________
1450 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1451 AliAnalysisDataContainer *cont)
1453 // Connect output of an existing task to a data container.
1455 Error("ConnectOutput", "Task pointer is NULL");
1458 if (!fTasks->FindObject(task)) {
1460 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1462 Bool_t connected = task->ConnectOutput(islot, cont);
1466 //______________________________________________________________________________
1467 void AliAnalysisManager::CleanContainers()
1469 // Clean data from all containers that have already finished all client tasks.
1470 TIter next(fContainers);
1471 AliAnalysisDataContainer *cont;
1472 while ((cont=(AliAnalysisDataContainer *)next())) {
1473 if (cont->IsOwnedData() &&
1474 cont->IsDataReady() &&
1475 cont->ClientsExecuted()) cont->DeleteData();
1479 //______________________________________________________________________________
1480 Bool_t AliAnalysisManager::InitAnalysis()
1482 // Initialization of analysis chain of tasks. Should be called after all tasks
1483 // and data containers are properly connected
1484 // Reset flag and remove valid_outputs file if exists
1485 if (fInitOK) return kTRUE;
1486 if (!gSystem->AccessPathName("outputs_valid"))
1487 gSystem->Unlink("outputs_valid");
1488 // Check for top tasks (depending only on input data containers)
1489 if (!fTasks->First()) {
1490 Error("InitAnalysis", "Analysis has no tasks !");
1494 AliAnalysisTask *task;
1495 AliAnalysisDataContainer *cont;
1498 Bool_t iszombie = kFALSE;
1499 Bool_t istop = kTRUE;
1501 while ((task=(AliAnalysisTask*)next())) {
1504 Int_t ninputs = task->GetNinputs();
1505 for (i=0; i<ninputs; i++) {
1506 cont = task->GetInputSlot(i)->GetContainer();
1510 fZombies->Add(task);
1514 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1515 i, task->GetName());
1517 if (iszombie) continue;
1518 // Check if cont is an input container
1519 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1520 // Connect to parent task
1524 fTopTasks->Add(task);
1528 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1531 // Check now if there are orphan tasks
1532 for (i=0; i<ntop; i++) {
1533 task = (AliAnalysisTask*)fTopTasks->At(i);
1538 while ((task=(AliAnalysisTask*)next())) {
1539 if (!task->IsUsed()) {
1541 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1544 // Check the task hierarchy (no parent task should depend on data provided
1545 // by a daughter task)
1546 for (i=0; i<ntop; i++) {
1547 task = (AliAnalysisTask*)fTopTasks->At(i);
1548 if (task->CheckCircularDeps()) {
1549 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1554 // Check that all containers feeding post-event loop tasks are in the outputs list
1555 TIter nextcont(fContainers); // loop over all containers
1556 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1557 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1558 if (cont->HasConsumers()) {
1559 // Check if one of the consumers is post event loop
1560 TIter nextconsumer(cont->GetConsumers());
1561 while ((task=(AliAnalysisTask*)nextconsumer())) {
1562 if (task->IsPostEventLoop()) {
1563 fOutputs->Add(cont);
1570 // Check if all special output containers have a file name provided
1571 TIter nextout(fOutputs);
1572 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1573 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1574 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1578 // Initialize requested branch list if needed
1579 if (!fAutoBranchHandling) {
1581 while ((task=(AliAnalysisTask*)next())) {
1582 if (!task->HasBranches()) {
1583 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1584 task->GetName(), task->ClassName());
1587 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1588 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1591 TString taskbranches;
1592 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1593 if (taskbranches.IsNull()) {
1594 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1595 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1598 AddBranches(taskbranches);
1605 //______________________________________________________________________________
1606 void AliAnalysisManager::AddBranches(const char *branches)
1608 // Add branches to the existing fRequestedBranches.
1609 TString br(branches);
1610 TObjArray *arr = br.Tokenize(",");
1613 while ((obj=next())) {
1614 if (!fRequestedBranches.Contains(obj->GetName())) {
1615 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1616 fRequestedBranches += obj->GetName();
1622 //______________________________________________________________________________
1623 void AliAnalysisManager::CheckBranches(Bool_t load)
1625 // The method checks the input branches to be loaded during the analysis.
1626 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1627 TObjArray *arr = fRequestedBranches.Tokenize(",");
1630 while ((obj=next())) {
1631 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1633 br = fTree->GetBranch(obj->GetName());
1635 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1640 if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1641 br->GetEntry(GetCurrentEntry());
1647 //______________________________________________________________________________
1648 Bool_t AliAnalysisManager::CheckTasks() const
1650 // Check consistency of tasks.
1651 Int_t ntasks = fTasks->GetEntries();
1653 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1656 // Get the pointer to AliAnalysisTaskSE::Class()
1657 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1658 // Loop all tasks to check if their corresponding library was loaded
1661 while ((obj=next())) {
1662 if (obj->IsA() == badptr) {
1663 Error("CheckTasks", "##################\n \
1664 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1671 //______________________________________________________________________________
1672 void AliAnalysisManager::PrintStatus(Option_t *option) const
1674 // Print task hierarchy.
1676 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1679 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1681 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1682 TIter next(fTopTasks);
1683 AliAnalysisTask *task;
1684 while ((task=(AliAnalysisTask*)next()))
1685 task->PrintTask(option);
1687 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1688 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1690 TString sopt(option);
1693 if (sopt.Contains("ALL"))
1695 if ( fOutputEventHandler )
1697 cout << TString('_',78) << endl;
1698 cout << "OutputEventHandler:" << endl;
1699 fOutputEventHandler->Print(" ");
1704 //______________________________________________________________________________
1705 void AliAnalysisManager::ResetAnalysis()
1707 // Reset all execution flags and clean containers.
1711 //______________________________________________________________________________
1712 void AliAnalysisManager::RunLocalInit()
1714 // Run LocalInit method for all tasks.
1715 TDirectory *cdir = gDirectory;
1716 if (IsTrainInitialized()) return;
1717 TIter nextTask(fTasks);
1718 AliAnalysisTask *task;
1719 while ((task=(AliAnalysisTask*)nextTask())) {
1723 if (cdir) cdir->cd();
1724 TObject::SetBit(kTasksInitialized, kTRUE);
1727 //______________________________________________________________________________
1728 void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1730 // Retrieves name of the file from tree
1733 TFile *file = tree->GetCurrentFile();
1736 TChain *chain = dynamic_cast<TChain*>(tree);
1737 if (!chain || !chain->GetNtrees()) return;
1738 basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1740 basename = gSystem->BaseName(file->GetName());
1742 Int_t index = basename.Index("#");
1743 fname = basename(index+1, basename.Length());
1746 //______________________________________________________________________________
1747 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1749 // Start analysis having a grid handler.
1750 if (!fGridHandler) {
1751 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1752 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1756 return StartAnalysis(type, tree, nentries, firstentry);
1759 //______________________________________________________________________________
1760 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1762 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1763 // MIX. Process nentries starting from firstentry
1765 // Backup current directory and make sure gDirectory points to gROOT
1766 TDirectory *cdir = gDirectory;
1769 Error("StartAnalysis","Analysis manager was not initialized !");
1770 if (cdir) cdir->cd();
1773 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1775 printf("StartAnalysis %s\n",GetName());
1776 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1778 fMaxEntries = nentries;
1780 TString anaType = type;
1782 fMode = kLocalAnalysis;
1783 if (anaType.Contains("file")) fIsRemote = kTRUE;
1784 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1785 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1786 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1787 if (fInputEventHandler) {
1789 InputFileFromTree(tree, fname);
1790 if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1793 if (fMode == kGridAnalysis) {
1795 if (!anaType.Contains("terminate")) {
1796 if (!fGridHandler) {
1797 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1798 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1799 if (cdir) cdir->cd();
1802 // Write analysis manager in the analysis file
1803 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1804 // run local task configuration
1806 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1807 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1808 if (cdir) cdir->cd();
1812 // Terminate grid analysis
1813 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1814 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1815 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1816 if (!fGridHandler->MergeOutputs()) {
1817 // Return if outputs could not be merged or if it alien handler
1818 // was configured for offline mode or local testing.
1819 if (cdir) cdir->cd();
1823 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1824 if (cdir) cdir->cd();
1825 ImportWrappers(NULL);
1827 if (cdir) cdir->cd();
1831 SetEventLoop(kFALSE);
1832 // Enable event loop mode if a tree was provided
1833 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1836 TString ttype = "TTree";
1837 if (tree && tree->IsA() == TChain::Class()) {
1838 chain = (TChain*)tree;
1839 if (!chain || !chain->GetListOfFiles()->First()) {
1840 Error("StartAnalysis", "Cannot process null or empty chain...");
1841 if (cdir) cdir->cd();
1847 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1848 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1849 // Initialize locally all tasks (happens for all modes)
1851 AliAnalysisTask *task;
1855 case kLocalAnalysis:
1856 if (!tree && !fGridHandler) {
1857 TIter nextT(fTasks);
1858 // Call CreateOutputObjects for all tasks
1860 Bool_t dirStatus = TH1::AddDirectoryStatus();
1861 while ((task=(AliAnalysisTask*)nextT())) {
1862 TH1::AddDirectory(kFALSE);
1863 task->CreateOutputObjects();
1864 if (!task->CheckPostData()) {
1865 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1866 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1867 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1869 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1873 TH1::AddDirectory(dirStatus);
1874 if (IsExternalLoop()) {
1875 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1876 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1883 fSelector = new AliAnalysisSelector(this);
1884 // Check if a plugin handler is used
1886 // Get the chain from the plugin
1887 TString dataType = "esdTree";
1888 if (fInputEventHandler) {
1889 dataType = fInputEventHandler->GetDataType();
1893 chain = fGridHandler->GetChainForTestMode(dataType);
1895 Error("StartAnalysis", "No chain for test mode. Aborting.");
1898 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1899 retv = chain->Process(fSelector, "", nentries, firstentry);
1902 // Run tree-based analysis via AliAnalysisSelector
1903 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1904 retv = tree->Process(fSelector, "", nentries, firstentry);
1906 case kProofAnalysis:
1908 // Check if the plugin is used
1910 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1912 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1913 Error("StartAnalysis", "No PROOF!!! Exiting.");
1914 if (cdir) cdir->cd();
1917 line = Form("gProof->AddInput((TObject*)%p);", this);
1918 gROOT->ProcessLine(line);
1921 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1922 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1924 Error("StartAnalysis", "No chain!!! Exiting.");
1925 if (cdir) cdir->cd();
1931 if (!anaType.Contains("terminate")) {
1932 if (!fGridHandler) {
1933 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1934 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1935 if (cdir) cdir->cd();
1938 // Write analysis manager in the analysis file
1939 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1940 // Start the analysis via the handler
1941 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1942 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1943 if (cdir) cdir->cd();
1947 // Terminate grid analysis
1948 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1949 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1950 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1951 if (!fGridHandler->MergeOutputs()) {
1952 // Return if outputs could not be merged or if it alien handler
1953 // was configured for offline mode or local testing.
1954 if (cdir) cdir->cd();
1958 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1959 ImportWrappers(NULL);
1961 if (cdir) cdir->cd();
1963 case kMixingAnalysis:
1964 // Run event mixing analysis
1966 Error("StartAnalysis", "Cannot run event mixing without event pool");
1967 if (cdir) cdir->cd();
1970 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1971 fSelector = new AliAnalysisSelector(this);
1972 while ((chain=fEventPool->GetNextChain())) {
1974 // Call NotifyBinChange for all tasks
1975 while ((task=(AliAnalysisTask*)next()))
1976 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1977 retv = chain->Process(fSelector);
1979 Error("StartAnalysis", "Mixing analysis failed");
1980 if (cdir) cdir->cd();
1984 PackOutput(fSelector->GetOutputList());
1987 if (cdir) cdir->cd();
1991 //______________________________________________________________________________
1992 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1994 // Start analysis for this manager on a given dataset. Analysis task can be:
1995 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1997 Error("StartAnalysis","Analysis manager was not initialized !");
2001 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
2002 TString anaType = type;
2004 if (!anaType.Contains("proof")) {
2005 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
2008 fMode = kProofAnalysis;
2010 TString proofProcessOpt;
2011 SetEventLoop(kTRUE);
2012 // Set the dataset flag
2013 TObject::SetBit(kUseDataSet);
2016 // Start proof analysis using the grid handler
2017 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
2018 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
2021 // Check if the plugin is in test mode
2022 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
2023 dataset = "test_collection";
2025 dataset = fGridHandler->GetProofDataSet();
2028 proofProcessOpt = fGridHandler->GetProofProcessOpt();
2031 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
2032 Error("StartAnalysis", "No PROOF!!! Exiting.");
2036 // Initialize locally all tasks
2039 line = Form("gProof->AddInput((TObject*)%p);", this);
2040 gROOT->ProcessLine(line);
2042 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2043 dataset,proofProcessOpt.Data(), nentries, firstentry);
2044 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2045 retv = (Long_t)gROOT->ProcessLine(line);
2049 //______________________________________________________________________________
2050 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2052 // Opens according the option the file specified by cont->GetFileName() and changes
2053 // current directory to cont->GetFolderName(). If the file was already opened, it
2054 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
2055 // be optionally ignored.
2056 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2057 TString filename = cont->GetFileName();
2059 if (filename.IsNull()) {
2060 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2063 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2065 f = mgr->OpenProofFile(cont,option);
2067 // Check first if the file is already opened
2068 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2070 // Check if option "UPDATE" was preserved
2071 TString opt(option);
2073 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2074 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2076 f = TFile::Open(filename, option);
2079 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2083 // Check for a folder request
2084 TString dir = cont->GetFolderName();
2085 if (!dir.IsNull()) {
2086 if (!f->GetDirectory(dir)) f->mkdir(dir);
2091 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2092 cont->SetFile(NULL);
2096 //______________________________________________________________________________
2097 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
2099 // Opens a special output file used in PROOF.
2101 TString filename = cont->GetFileName();
2102 if (cont == fCommonOutput) {
2103 if (fOutputEventHandler) {
2104 if (strlen(extaod)) filename = extaod;
2105 filename = fOutputEventHandler->GetOutputFileName();
2107 else Fatal("OpenProofFile","No output container. Exiting.");
2110 if (fMode!=kProofAnalysis || !fSelector) {
2111 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2114 if (fSpecialOutputLocation.Length()) {
2115 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2117 // Check if option "UPDATE" was preserved
2118 TString opt(option);
2120 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2121 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2123 f = new TFile(filename, option);
2125 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2129 // Check for a folder request
2130 TString dir = cont->GetFolderName();
2132 if (!f->GetDirectory(dir)) f->mkdir(dir);
2137 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2138 cont->SetFile(NULL);
2141 // Check if there is already a proof output file in the output list
2142 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2144 // Get the actual file
2145 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
2146 filename = (const char*)gROOT->ProcessLine(line);
2148 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2150 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2152 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2155 // Check if option "UPDATE" was preserved
2156 TString opt(option);
2158 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2159 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2161 if (cont->IsRegisterDataset()) {
2162 TString dsetName = filename;
2163 dsetName.ReplaceAll(".root", cont->GetTitle());
2164 dsetName.ReplaceAll(":","_");
2165 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2166 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
2168 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2169 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2171 if (fDebug > 1) printf("=== %s\n", line.Data());
2172 gROOT->ProcessLine(line);
2173 line = Form("pf->OpenFile(\"%s\");", option);
2174 gROOT->ProcessLine(line);
2177 gROOT->ProcessLine("pf->Print()");
2178 printf(" == proof file name: %s", f->GetName());
2180 // Add to proof output list
2181 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2182 if (fDebug > 1) printf("=== %s\n", line.Data());
2183 gROOT->ProcessLine(line);
2185 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2189 // Check for a folder request
2190 TString dir = cont->GetFolderName();
2191 if (!dir.IsNull()) {
2192 if (!f->GetDirectory(dir)) f->mkdir(dir);
2197 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2198 cont->SetFile(NULL);
2202 //______________________________________________________________________________
2203 void AliAnalysisManager::ExecAnalysis(Option_t *option)
2205 // Execute analysis.
2206 static Long64_t nentries = 0;
2207 static TTree *lastTree = 0;
2208 static TStopwatch *timer = new TStopwatch();
2209 // Only the first call to Process will trigger a true Notify. Other Notify
2210 // coming before is ignored.
2211 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2212 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2215 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2217 if (fTree && (fTree != lastTree)) {
2218 nentries += fTree->GetEntries();
2221 if (!fNcalls) timer->Start();
2222 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2224 fIOTimer->Start(kTRUE);
2226 TDirectory *cdir = gDirectory;
2227 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2228 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2230 Error("ExecAnalysis", "Analysis manager was not initialized !");
2231 if (cdir) cdir->cd();
2235 AliAnalysisTask *task;
2236 // Check if the top tree is active.
2238 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2239 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2241 // De-activate all tasks
2242 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2243 AliAnalysisDataContainer *cont = fCommonInput;
2244 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2246 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2247 if (cdir) cdir->cd();
2250 cont->SetData(fTree); // This will notify all consumers
2251 Long64_t entry = fTree->GetTree()->GetReadEntry();
2253 // Call BeginEvent() for optional input/output and MC services
2254 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2255 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2256 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2258 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2259 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2261 // Execute the tasks
2262 // TIter next1(cont->GetConsumers());
2264 fIOTime += fIOTimer->RealTime();
2265 fCPUTimer->Start(kTRUE);
2266 TIter next1(fTopTasks);
2268 while ((task=(AliAnalysisTask*)next1())) {
2270 cout << " Executing task " << task->GetName() << endl;
2272 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2273 task->ExecuteTask(option);
2274 if (fStatistics) fStatistics->StopTimer();
2276 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2277 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2281 fCPUTime += fCPUTimer->RealTime();
2282 fIOTimer->Start(kTRUE);
2284 // Call FinishEvent() for optional output and MC services
2285 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2286 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2287 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2288 // Gather system information if requested
2289 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2290 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2291 if (cdir) cdir->cd();
2293 fIOTime += fIOTimer->RealTime();
2296 // The event loop is not controlled by TSelector
2298 // Call BeginEvent() for optional input/output and MC services
2299 fIOTimer->Start(kTRUE);
2300 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2301 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2302 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2304 fIOTime += fIOTimer->RealTime();
2306 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2307 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2308 fCPUTimer->Start(kTRUE);
2309 TIter next2(fTopTasks);
2310 while ((task=(AliAnalysisTask*)next2())) {
2311 task->SetActive(kTRUE);
2313 cout << " Executing task " << task->GetName() << endl;
2315 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2316 task->ExecuteTask(option);
2317 if (fStatistics) fStatistics->StopTimer();
2321 fCPUTime += fCPUTimer->RealTime();
2323 // Call FinishEvent() for optional output and MC services
2324 fIOTimer->Start(kTRUE);
2325 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2326 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2327 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2328 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2329 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2330 if (cdir) cdir->cd();
2332 fIOTime += fIOTimer->RealTime();
2335 //______________________________________________________________________________
2336 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2338 // Check if the stdout is connected to a pipe (C.Holm)
2339 Bool_t ispipe = kFALSE;
2340 out.seekp(0, std::ios_base::cur);
2343 if (errno == ESPIPE) ispipe = kTRUE;
2348 //______________________________________________________________________________
2349 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2351 // Set the input event handler and create a container for it.
2353 fInputEventHandler = handler;
2354 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2357 //______________________________________________________________________________
2358 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2360 // Set the input event handler and create a container for it.
2362 fOutputEventHandler = handler;
2363 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2364 fCommonOutput->SetSpecialOutput();
2367 //______________________________________________________________________________
2368 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2370 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2371 if (TObject::TestBit(kUseProgressBar)) {
2372 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2378 //______________________________________________________________________________
2379 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2381 // Enable a text mode progress bar. Resets debug level to 0.
2382 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2383 TObject::SetBit(kUseProgressBar,flag);
2384 fPBUpdateFreq = freq;
2388 //______________________________________________________________________________
2389 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2391 // This method is used externally to register output files which are not
2392 // connected to any output container, so that the manager can properly register,
2393 // retrieve or merge them when running in distributed mode. The file names are
2394 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2395 if (fExtraFiles.Contains(fname)) return;
2396 if (fExtraFiles.Length()) fExtraFiles += " ";
2397 fExtraFiles += fname;
2400 //______________________________________________________________________________
2401 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2403 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2407 TObject *pof = source->FindObject(filename);
2408 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2409 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2412 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2413 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2414 TString clientUrl(chUrl);
2415 TString fullPath_str(fullPath);
2416 if (clientUrl.Contains("localhost")){
2417 TObjArray* array = fullPath_str.Tokenize ( "//" );
2418 TObjString *strobj = ( TObjString *)array->At(1);
2419 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2420 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2421 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2422 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2423 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2427 else if (clientUrl.Contains("__lite__")) {
2428 // Special case for ProofLite environement - get file info and copy.
2429 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2430 fullPath_str = Form("%s/%s", tmp, fullPath);
2433 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2434 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2436 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2440 //______________________________________________________________________________
2441 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2443 // Fill analysis type in the provided string.
2445 case kLocalAnalysis:
2448 case kProofAnalysis:
2454 case kMixingAnalysis:
2459 //______________________________________________________________________________
2460 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2462 // Validate all output files.
2463 TIter next(fOutputs);
2464 AliAnalysisDataContainer *output;
2465 TDirectory *cdir = gDirectory;
2466 TString openedFiles;
2467 while ((output=(AliAnalysisDataContainer*)next())) {
2468 if (output->IsRegisterDataset()) continue;
2469 TString filename = output->GetFileName();
2470 if (filename == "default") {
2471 if (!fOutputEventHandler) continue;
2472 filename = fOutputEventHandler->GetOutputFileName();
2473 // Main AOD may not be there
2474 if (gSystem->AccessPathName(filename)) continue;
2476 // Check if the file is closed
2477 if (openedFiles.Contains(filename)) continue;;
2478 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2480 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2481 // Clear file list to release object ownership to user.
2485 file = TFile::Open(filename);
2486 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2487 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2488 if (cdir) cdir->cd();
2492 openedFiles += filename;
2495 if (cdir) cdir->cd();
2499 //______________________________________________________________________________
2500 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2502 // Implements a nice text mode progress bar.
2503 static Long64_t icount = 0;
2504 static TString oname;
2505 static TString nname;
2506 static Long64_t ocurrent = 0;
2507 static Long64_t osize = 0;
2508 static Int_t oseconds = 0;
2509 static TStopwatch *owatch = 0;
2510 static Bool_t oneoftwo = kFALSE;
2511 static Int_t nrefresh = 0;
2512 static Int_t nchecks = 0;
2513 static char lastChar = 0;
2514 const char symbol[4] = {'-','\\','|','/'};
2516 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2522 ocurrent = TMath::Abs(current);
2523 osize = TMath::Abs(size);
2524 if (ocurrent > osize) ocurrent=osize;
2529 if ((current % fPBUpdateFreq) != 0) return;
2531 char progress[11] = " ";
2532 Int_t ichar = icount%4;
2537 if (owatch && !last) {
2539 time = owatch->RealTime();
2540 seconds = int(time) % 60;
2541 minutes = (int(time) / 60) % 60;
2542 hours = (int(time) / 60 / 60);
2544 if (oseconds==seconds) {
2548 oneoftwo = !oneoftwo;
2552 if (refresh && oneoftwo) {
2554 if (nchecks <= 0) nchecks = nrefresh+1;
2555 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2556 oname = Form(" == %d%% ==", pctdone);
2558 Double_t percent = 100.0*ocurrent/osize;
2559 Int_t nchar = Int_t(percent/10);
2560 if (nchar>10) nchar=10;
2562 for (i=0; i<nchar; i++) progress[i] = '=';
2563 progress[nchar] = symbol[ichar];
2564 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2565 progress[10] = '\0';
2568 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2569 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2570 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2572 Int_t full = Int_t(ocurrent > 0 ?
2573 time * (float(osize)/ocurrent) + .5 :
2575 Int_t remain = Int_t(full - time);
2576 Int_t rsec = remain % 60;
2577 Int_t rmin = (remain / 60) % 60;
2578 Int_t rhour = (remain / 60 / 60);
2579 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2580 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2582 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2583 if (refresh && oneoftwo) oname = nname;
2584 if (owatch) owatch->Continue();
2593 fprintf(stderr, "\n");
2597 //______________________________________________________________________________
2598 void AliAnalysisManager::DoLoadBranch(const char *name)
2600 // Get tree and load branch if needed.
2601 static Long64_t crtEntry = -100;
2603 if (fAutoBranchHandling || !fTree)
2606 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2608 br = fTree->GetBranch(name);
2610 Error("DoLoadBranch", "Could not find branch %s",name);
2615 if (br->GetReadEntry()==fCurrentEntry) return;
2616 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2618 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2619 if (crtEntry != fCurrentEntry) {
2620 CountEvent(1,0,1,0);
2621 crtEntry = fCurrentEntry;
2624 if (crtEntry != fCurrentEntry) {
2625 CountEvent(1,1,0,0);
2626 crtEntry = fCurrentEntry;
2631 //______________________________________________________________________________
2632 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2634 // Add the statistics task to the manager.
2636 Info("AddStatisticsTask", "Already added");
2639 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2640 gROOT->ProcessLine(line);
2643 //______________________________________________________________________________
2644 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2646 // Bookkeep current event;
2647 if (!fStatistics) return;
2648 fStatistics->AddInput(ninput);
2649 fStatistics->AddProcessed(nprocessed);
2650 fStatistics->AddFailed(nfailed);
2651 fStatistics->AddAccepted(naccepted);
2654 //______________________________________________________________________________
2655 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2657 // Add a line in the statistics message. If available, the statistics message is written
2658 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2660 if (!strlen(line)) return;
2661 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2662 fStatisticsMsg += line;
2665 //______________________________________________________________________________
2666 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2668 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2669 static Bool_t done = kFALSE;
2672 if (!fStatistics) return;
2674 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2675 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2676 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2677 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2678 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2679 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2680 fStatistics->GetNaccepted()), ios::out);
2681 out << fStatisticsMsg << endl;
2685 //______________________________________________________________________________
2686 const char* AliAnalysisManager::GetOADBPath()
2688 // returns the path of the OADB
2689 // this static function just depends on environment variables
2691 static TString oadbPath;
2693 if (gSystem->Getenv("OADB_PATH"))
2694 oadbPath = gSystem->Getenv("OADB_PATH");
2695 else if (gSystem->Getenv("ALICE_ROOT"))
2696 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2698 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2703 //______________________________________________________________________________
2704 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2706 // Define a custom string variable mapped to a global unique name. The variable
2707 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2708 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2710 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2713 Bool_t valid = kFALSE;
2714 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2716 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2719 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2722 //______________________________________________________________________________
2723 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2725 // Static method to retrieve a global variable defined via SetGlobalStr.
2727 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2729 TObject *value = mgr->GetGlobals()->GetValue(key);
2730 if (!value) return 0;
2732 return value->GetName();
2735 //______________________________________________________________________________
2736 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2738 // Define a custom integer variable mapped to a global unique name. The variable
2739 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2740 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2742 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2745 Bool_t valid = kFALSE;
2746 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2748 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2751 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2754 //______________________________________________________________________________
2755 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2757 // Static method to retrieve a global variable defined via SetGlobalInt.
2759 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2761 TObject *value = mgr->GetGlobals()->GetValue(key);
2762 if (!value) return 0;
2764 TString s = value->GetName();
2768 //______________________________________________________________________________
2769 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2771 // Define a custom double precision variable mapped to a global unique name. The variable
2772 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2773 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2775 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2778 Bool_t valid = kFALSE;
2779 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2781 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2784 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2787 //______________________________________________________________________________
2788 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2790 // Static method to retrieve a global variable defined via SetGlobalDbl.
2792 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2794 TObject *value = mgr->GetGlobals()->GetValue(key);
2795 if (!value) return 0;
2797 TString s = value->GetName();
2801 //______________________________________________________________________________
2802 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2804 // Sets Class debug level
2806 if (!fDebugOptions) {
2807 fDebugOptions = new TObjArray();
2808 fDebugOptions->SetOwner(kTRUE);
2811 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2813 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
2814 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2816 TString oldDebugStr = debugOpt->GetTitle();
2817 Int_t oldDebug = oldDebugStr.Atoi();
2818 if (debugLevel > oldDebug) {
2819 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
2820 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2822 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
2827 //______________________________________________________________________________
2828 void AliAnalysisManager::ApplyDebugOptions()
2830 // Apply debug options
2832 if (!fDebugOptions) return;
2834 TIter next(fDebugOptions);
2837 while ((debug=dynamic_cast<TNamed*>(next()))) {
2838 debugLevel = debug->GetTitle();
2839 AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
2840 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2844 //______________________________________________________________________________
2845 Bool_t AliAnalysisManager::IsMacroLoaded(const char filename)
2847 // Check if a macro was loaded.
2848 return fgMacroNames.Contains(filename);
2851 //______________________________________________________________________________
2852 Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2854 // Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded
2856 TString macroName = gSystem->BaseName(filename);
2857 // Strip appended +, ++, +g, +O
2858 Int_t index = macroName.Index("+");
2859 if (index>0) macroName.Remove(index);
2860 if (fgMacroNames.Contains(macroName)) {
2861 // Macro with the same name loaded already in this root session, do
2866 Int_t ret = gROOT->LoadMacro(filename,error,check);
2867 // In case of error return the error code
2868 if (ret) return ret;
2869 // Append the macro name to the loaded macros list
2870 fgMacroNames += macroName;
2871 fgMacroNames += " ";
2875 //______________________________________________________________________________
2876 void AliAnalysisManager::Lock()
2878 // Security lock. This is to detect NORMAL user errors and not really to
2879 // protect against intentional hacks.
2880 if (fLocked) return;
2882 if (fInputEventHandler) fInputEventHandler->Lock();
2883 if (fOutputEventHandler) fOutputEventHandler->Lock();
2884 if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2885 Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2888 //______________________________________________________________________________
2889 void AliAnalysisManager::UnLock()
2891 // Verbose unlocking. Hackers will be punished ;-) ...
2892 if (!fLocked) return;
2894 if (fInputEventHandler) fInputEventHandler->UnLock();
2895 if (fOutputEventHandler) fOutputEventHandler->UnLock();
2896 if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2897 Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2900 //______________________________________________________________________________
2901 void AliAnalysisManager::Changed()
2903 // All critical setters pass through the Changed method that throws an exception
2904 // in case the lock was set.
2905 if (fLocked) Fatal("Changed","Critical setter called in locked mode");