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),
86 fSpecialOutputLocation(""),
95 fFileDescriptors(new TObjArray()),
96 fCurrentDescriptor(0),
103 fAutoBranchHandling(kTRUE),
104 fAsyncReading(kFALSE), // default prefetching on
109 fCacheSize(100000000), // default 100 MB
111 fRequestedBranches(),
121 // Default constructor.
122 fgAnalysisManager = this;
123 fgCommonFileName = "AnalysisResults.root";
124 if (TClass::IsCallingNew() != TClass::kDummyNew) {
125 fTasks = new TObjArray();
126 fTopTasks = new TObjArray();
127 fZombies = new TObjArray();
128 fContainers = new TObjArray();
129 fInputs = new TObjArray();
130 fOutputs = new TObjArray();
131 fParamCont = new TObjArray();
132 fGlobals = new TMap();
134 fIOTimer = new TStopwatch();
135 fCPUTimer = new TStopwatch();
136 fInitTimer = new TStopwatch();
140 //______________________________________________________________________________
141 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
144 fInputEventHandler(NULL),
145 fOutputEventHandler(NULL),
146 fMCtruthEventHandler(NULL),
151 fInitOK(other.fInitOK),
152 fMustClean(other.fMustClean),
153 fIsRemote(other.fIsRemote),
154 fLocked(other.fLocked),
155 fMCLoop(other.fMCLoop),
156 fDebug(other.fDebug),
157 fSpecialOutputLocation(""),
166 fFileDescriptors(new TObjArray()),
167 fCurrentDescriptor(0),
172 fExtraFiles(other.fExtraFiles),
173 fFileInfoLog(other.fFileInfoLog),
174 fAutoBranchHandling(other.fAutoBranchHandling),
175 fAsyncReading(other.fAsyncReading),
178 fNcalls(other.fNcalls),
179 fMaxEntries(other.fMaxEntries),
180 fCacheSize(other.fCacheSize),
181 fStatisticsMsg(other.fStatisticsMsg),
182 fRequestedBranches(other.fRequestedBranches),
183 fStatistics(other.fStatistics),
184 fGlobals(other.fGlobals),
185 fIOTimer(new TStopwatch()),
186 fCPUTimer(new TStopwatch()),
187 fInitTimer(new TStopwatch()),
193 fTasks = new TObjArray(*other.fTasks);
194 fTopTasks = new TObjArray(*other.fTopTasks);
195 fZombies = new TObjArray(*other.fZombies);
196 fContainers = new TObjArray(*other.fContainers);
197 fInputs = new TObjArray(*other.fInputs);
198 fOutputs = new TObjArray(*other.fOutputs);
199 fParamCont = new TObjArray(*other.fParamCont);
200 fgCommonFileName = "AnalysisResults.root";
201 fgAnalysisManager = this;
204 //______________________________________________________________________________
205 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
208 if (&other != this) {
209 TNamed::operator=(other);
210 fInputEventHandler = other.fInputEventHandler;
211 fOutputEventHandler = other.fOutputEventHandler;
212 fMCtruthEventHandler = other.fMCtruthEventHandler;
213 fEventPool = other.fEventPool;
216 fNSysInfo = other.fNSysInfo;
218 fInitOK = other.fInitOK;
219 fIsRemote = other.fIsRemote;
220 fLocked = other.fLocked;
221 fMCLoop = other.fMCLoop;
222 fDebug = other.fDebug;
223 fTasks = new TObjArray(*other.fTasks);
224 fTopTasks = new TObjArray(*other.fTopTasks);
225 fZombies = new TObjArray(*other.fZombies);
226 fContainers = new TObjArray(*other.fContainers);
227 fInputs = new TObjArray(*other.fInputs);
228 fOutputs = new TObjArray(*other.fOutputs);
229 fParamCont = new TObjArray(*other.fParamCont);
230 fDebugOptions = NULL;
231 fFileDescriptors = new TObjArray();
232 fCurrentDescriptor = 0;
234 fCommonOutput = NULL;
237 fExtraFiles = other.fExtraFiles;
238 fFileInfoLog = other.fFileInfoLog;
239 fgCommonFileName = "AnalysisResults.root";
240 fgAnalysisManager = this;
241 fAutoBranchHandling = other.fAutoBranchHandling;
242 fAsyncReading = other.fAsyncReading;
243 fTable.Clear("nodelete");
244 fRunFromPath = other.fRunFromPath;
245 fNcalls = other. fNcalls;
246 fMaxEntries = other.fMaxEntries;
247 fCacheSize = other.fCacheSize;
248 fStatisticsMsg = other.fStatisticsMsg;
249 fRequestedBranches = other.fRequestedBranches;
250 fStatistics = other.fStatistics;
251 fGlobals = new TMap();
252 fIOTimer = new TStopwatch();
253 fCPUTimer = new TStopwatch();
254 fInitTimer = new TStopwatch();
262 //______________________________________________________________________________
263 AliAnalysisManager::~AliAnalysisManager()
266 if (fTasks) {fTasks->Delete(); delete fTasks;}
267 if (fTopTasks) delete fTopTasks;
268 if (fZombies) delete fZombies;
269 if (fContainers) {fContainers->Delete(); delete fContainers;}
270 if (fInputs) delete fInputs;
271 if (fOutputs) delete fOutputs;
272 if (fParamCont) delete fParamCont;
273 if (fDebugOptions) delete fDebugOptions;
274 if (fGridHandler) delete fGridHandler;
275 if (fInputEventHandler) delete fInputEventHandler;
276 if (fOutputEventHandler) delete fOutputEventHandler;
277 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
278 if (fEventPool) delete fEventPool;
279 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
280 if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
281 if (fFileDescriptors) {fFileDescriptors->Delete(); delete fFileDescriptors;}
287 //______________________________________________________________________________
288 void AliAnalysisManager::CreateReadCache()
290 // Create cache for reading according fCacheSize and fAsyncReading.
291 if (!fTree || !fTree->GetCurrentFile()) {
292 Error("CreateReadCache","Current tree or tree file not yet defined");
296 if (fDebug) Info("CreateReadCache","=== Read caching disabled ===");
299 gEnv->SetValue("TFile.AsyncPrefetching",(Int_t)fAsyncReading);
300 if (fAsyncReading) gEnv->SetValue("Cache.Directory",Form("file://%s/cache", gSystem->WorkingDirectory()));
301 if (fAsyncReading) gEnv->SetValue("TFile.AsyncReading",1);
302 fTree->SetCacheSize(fCacheSize);
303 TTreeCache::SetLearnEntries(1); //<<< we can take the decision after 1 entry
304 if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) {
305 TObjArray *arr = fRequestedBranches.Tokenize(",");
309 fTree->AddBranchToCache(obj->GetName(),kTRUE); //<<< add requested branches to cache
312 fTree->AddBranchToCache("*", kTRUE); //<<< add all branches to cache
315 Info("CreateReadCache","Read cache enabled %lld bytes with async reading=%d",fCacheSize, (Int_t)fAsyncReading);
320 //______________________________________________________________________________
321 Bool_t AliAnalysisManager::EventLoop(Long64_t nevents)
323 // Initialize an event loop where the data producer is the input handler
324 // The handler must implement MakeTree creating the tree of events (likely
325 // memory resident) and generate the current event in the method BeginEvent.
326 // If the tree is memory resident, the handler should never call TTree::Fill
328 cout << "===== RUNNING IN EVENT LOOP MODE: " << GetName() << endl;
329 if (!fInputEventHandler) {
330 Error("EventLoop", "No input handler: exiting");
333 TTree *tree = new TTree("DummyTree", "Dummy tree for AliAnalysisManager::EventLoop");
334 SetExternalLoop(kTRUE);
335 if (!Init(tree)) return kFALSE;
337 for (Long64_t iev=0; iev<nevents; iev++)
340 PackOutput(&dummyList);
346 //______________________________________________________________________________
347 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
349 // Read one entry of the tree or a whole branch.
350 fCurrentEntry = entry;
351 if (!fAutoBranchHandling)
353 if (!fTree || !fTree->GetTree()) return -1;
354 fIOTimer->Start(kTRUE);
355 Long64_t readbytes = fTree->GetTree()->GetEntry(entry, getall);
357 fIOTime += fIOTimer->RealTime();
358 return (Int_t)readbytes;
361 //______________________________________________________________________________
362 Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
364 // Attempt to extract run number from input data path. Works only for paths to
365 // alice data in alien.
366 // sim: /alice/sim/<production>/run_no/...
367 // data: /alice/data/year/period/000run_no/... (ESD or AOD)
368 TString type = "unknown";
370 if (s.Contains("/alice/data")) type = "real";
371 else if (s.Contains("/alice/sim")) type = "simulated";
374 ind1 = s.Index("/00");
376 ind2 = s.Index("/",ind1+1);
377 if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
380 ind1 = s.Index("/LHC");
382 ind1 = s.Index("/",ind1+1);
384 ind2 = s.Index("/",ind1+1);
385 if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
389 Int_t run = srun.Atoi();
390 if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
394 //______________________________________________________________________________
395 Bool_t AliAnalysisManager::Init(TTree *tree)
397 // The Init() function is called when the selector needs to initialize
398 // a new tree or chain. Typically here the branch addresses of the tree
399 // will be set. It is normaly not necessary to make changes to the
400 // generated code, but the routine can be extended by the user if needed.
401 // Init() will be called many times when running with PROOF.
402 Bool_t init = kFALSE;
403 if (!tree) return kFALSE; // Should not happen - protected in selector caller
405 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
407 // Call InitTree of EventHandler
408 if (fOutputEventHandler) {
409 if (fMode == kProofAnalysis) {
410 init = fOutputEventHandler->Init(0x0, "proof");
412 init = fOutputEventHandler->Init(0x0, "local");
415 Error("Init", "Output event handler failed to initialize");
420 if (fInputEventHandler) {
421 if (fMode == kProofAnalysis) {
422 init = fInputEventHandler->Init(tree, "proof");
424 init = fInputEventHandler->Init(tree, "local");
427 Error("Init", "Input event handler failed to initialize tree");
431 // If no input event handler we need to get the tree once
433 if(!tree->GetTree()) {
434 Long64_t readEntry = tree->LoadTree(0);
435 if (readEntry == -2) {
436 Error("Init", "Input tree has no entry. Exiting");
442 if (fMCtruthEventHandler) {
443 if (fMode == kProofAnalysis) {
444 init = fMCtruthEventHandler->Init(0x0, "proof");
446 init = fMCtruthEventHandler->Init(0x0, "local");
449 Error("Init", "MC event handler failed to initialize");
454 if (!fInitOK) InitAnalysis();
455 if (!fInitOK) return kFALSE;
457 if (fMode != kProofAnalysis) CreateReadCache();
459 // cholm - here we should re-add to the table or branches
462 AliAnalysisDataContainer *top = fCommonInput;
463 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
465 Error("Init","No top input container !");
469 CheckBranches(kFALSE);
472 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
477 //______________________________________________________________________________
478 void AliAnalysisManager::SlaveBegin(TTree *tree)
480 // The SlaveBegin() function is called after the Begin() function.
481 // When running with PROOF SlaveBegin() is called on each slave server.
482 // The tree argument is deprecated (on PROOF 0 is passed).
483 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
484 // Init timer should be already started
485 // Apply debug options
488 fMCtruthEventHandler &&
489 (fMode != kProofAnalysis)) fMCtruthEventHandler->SetCacheSize(fCacheSize);
490 if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
491 static Bool_t isCalled = kFALSE;
492 Bool_t init = kFALSE;
493 Bool_t initOK = kTRUE;
495 TDirectory *curdir = gDirectory;
496 // Call SlaveBegin only once in case of mixing
497 if (isCalled && fMode==kMixingAnalysis) return;
499 // Call Init of EventHandler
500 if (fOutputEventHandler) {
501 if (fMode == kProofAnalysis) {
502 // Merging AOD's in PROOF via TProofOutputFile
503 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
504 init = fOutputEventHandler->Init("proof");
505 if (!init) msg = "Failed to initialize output handler on worker";
507 init = fOutputEventHandler->Init("local");
508 if (!init) msg = "Failed to initialize output handler";
511 if (!fSelector) Error("SlaveBegin", "Selector not set");
512 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
515 if (fInputEventHandler) {
516 fInputEventHandler->SetInputTree(tree);
517 if (fMode == kProofAnalysis) {
518 init = fInputEventHandler->Init("proof");
519 if (!init) msg = "Failed to initialize input handler on worker";
521 init = fInputEventHandler->Init("local");
522 if (!init) msg = "Failed to initialize input handler";
525 if (!fSelector) Error("SlaveBegin", "Selector not set");
526 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
529 if (fMCtruthEventHandler) {
530 if (fMode == kProofAnalysis) {
531 init = fMCtruthEventHandler->Init("proof");
532 if (!init) msg = "Failed to initialize MC handler on worker";
534 init = fMCtruthEventHandler->Init("local");
535 if (!init) msg = "Failed to initialize MC handler";
538 if (!fSelector) Error("SlaveBegin", "Selector not set");
539 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
541 if (curdir) curdir->cd();
545 AliAnalysisTask *task;
546 // Call CreateOutputObjects for all tasks
547 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
548 Bool_t dirStatus = TH1::AddDirectoryStatus();
550 while ((task=(AliAnalysisTask*)next())) {
552 // Start with memory as current dir and make sure by default histograms do not get attached to files.
553 TH1::AddDirectory(kFALSE);
554 task->CreateOutputObjects();
555 if (!task->CheckPostData()) {
556 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
557 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
558 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
560 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
563 TH1::AddDirectory(dirStatus);
564 if (curdir) curdir->cd();
566 fInitTime += fInitTimer->RealTime();
567 fInitTimer->Continue();
568 printf("Initialization time: %g [sec]\n", fInitTime);
569 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
572 //______________________________________________________________________________
573 Bool_t AliAnalysisManager::Notify()
575 // The Notify() function is called when a new file is opened. This
576 // can be either for a new TTree in a TChain or when when a new TTree
577 // is started when using PROOF. It is normaly not necessary to make changes
578 // to the generated code, but the routine can be extended by the
579 // user if needed. The return value is currently not used.
580 fIOTimer->Start(kTRUE);
581 if (!fTree) return kFALSE;
582 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
584 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
585 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
587 TFile *curfile = fTree->GetCurrentFile();
589 Error("Notify","No current file");
592 if (IsCollectThroughput()) {
593 if (fCurrentDescriptor) fCurrentDescriptor->Done();
594 fCurrentDescriptor = new AliAnalysisFileDescriptor(curfile);
595 fFileDescriptors->Add(fCurrentDescriptor);
598 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
599 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
600 if (run && (run != fRunFromPath)) {
602 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
605 AliAnalysisTask *task;
607 // Call Notify of the event handlers
608 if (fInputEventHandler) {
609 fInputEventHandler->Notify(curfile->GetName());
612 if (fOutputEventHandler) {
613 fOutputEventHandler->Notify(curfile->GetName());
616 if (fMCtruthEventHandler) {
617 fMCtruthEventHandler->Notify(curfile->GetName());
620 // Call Notify for all tasks
621 while ((task=(AliAnalysisTask*)next()))
624 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
626 fIOTime += fIOTimer->RealTime();
630 //______________________________________________________________________________
631 Bool_t AliAnalysisManager::Process(Long64_t)
633 // The Process() function is called for each entry in the tree (or possibly
634 // keyed object in the case of PROOF) to be processed. The entry argument
635 // specifies which entry in the currently loaded tree is to be processed.
636 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
637 // to read either all or the required parts of the data. When processing
638 // keyed objects with PROOF, the object is already loaded and is available
639 // via the fObject pointer.
641 // This function should contain the "body" of the analysis. It can contain
642 // simple or elaborate selection criteria, run algorithms on the data
643 // of the event and typically fill histograms.
645 // WARNING when a selector is used with a TChain, you must use
646 // the pointer to the current TTree to call GetEntry(entry).
647 // The entry is always the local entry number in the current tree.
648 // Assuming that fChain is the pointer to the TChain being processed,
649 // use fChain->GetTree()->GetEntry(entry).
651 // This method is obsolete. ExecAnalysis is called instead.
655 //______________________________________________________________________________
656 void AliAnalysisManager::PackOutput(TList *target)
658 // Pack all output data containers in the output list. Called at SlaveTerminate
659 // stage in PROOF case for each slave.
660 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
661 fIOTimer->Start(kTRUE);
663 if (IsCollectThroughput()) {
664 if (fCurrentDescriptor) fCurrentDescriptor->Done();
665 fFileDescriptors->Print();
666 if (fFileInfoLog.IsNull()) fFileInfoLog = "fileinfo.log";
667 out.open(fFileInfoLog, std::ios::app);
668 if (out.bad()) Error("SavePrimitive", "Bad file name: %s", fFileInfoLog.Data());
670 TIter nextflog(fFileDescriptors);
672 while ((log=nextflog())) log->SavePrimitive(out,"");
676 Error("PackOutput", "No target. Exiting.");
679 TDirectory *cdir = gDirectory;
681 if (fInputEventHandler) fInputEventHandler ->Terminate();
682 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
683 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
686 // Call FinishTaskOutput() for each event loop task (not called for
687 // post-event loop tasks - use Terminate() fo those)
688 TIter nexttask(fTasks);
689 AliAnalysisTask *task;
690 while ((task=(AliAnalysisTask*)nexttask())) {
691 if (!task->IsPostEventLoop()) {
692 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
693 task->FinishTaskOutput();
695 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
698 // Write statistics message on the workers.
699 if (fStatistics) WriteStatisticsMsg(fNcalls);
701 if (fMode == kProofAnalysis) {
702 TIter next(fOutputs);
703 AliAnalysisDataContainer *output;
704 Bool_t isManagedByHandler = kFALSE;
707 while ((output=(AliAnalysisDataContainer*)next())) {
708 // Do not consider outputs of post event loop tasks
709 isManagedByHandler = kFALSE;
710 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
711 const char *filename = output->GetFileName();
712 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
713 isManagedByHandler = kTRUE;
714 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
715 filename = fOutputEventHandler->GetOutputFileName();
717 // Check if data was posted to this container. If not, issue an error.
718 if (!output->GetData() && !isManagedByHandler) {
719 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
722 if (!output->IsSpecialOutput()) {
724 if (strlen(filename) && !isManagedByHandler) {
725 // Backup current folder
726 TDirectory *opwd = gDirectory;
727 // File resident outputs.
728 // Check first if the file exists.
729 TString openoption = "RECREATE";
730 Bool_t firsttime = kTRUE;
731 if (filestmp.FindObject(output->GetFileName())) {
734 filestmp.Add(new TNamed(output->GetFileName(),""));
736 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
737 // TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
738 // Save data to file, then close.
739 if (output->GetData()->InheritsFrom(TCollection::Class())) {
740 // If data is a collection, we set the name of the collection
741 // as the one of the container and we save as a single key.
742 TCollection *coll = (TCollection*)output->GetData();
743 coll->SetName(output->GetName());
744 // coll->Write(output->GetName(), TObject::kSingleKey);
746 if (output->GetData()->InheritsFrom(TTree::Class())) {
747 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
748 // Save data to file, then close.
749 TTree *tree = (TTree*)output->GetData();
750 // Check if tree is in memory
751 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
755 // output->GetData()->Write();
758 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
760 // printf(" file %s listing content:\n", filename);
763 // Clear file list to release object ownership to user.
766 output->SetFile(NULL);
767 // Restore current directory
768 if (opwd) opwd->cd();
770 // Memory-resident outputs
771 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
773 AliAnalysisDataWrapper *wrap = 0;
774 if (isManagedByHandler) {
775 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
776 wrap->SetName(output->GetName());
778 else wrap =output->ExportData();
779 // Output wrappers must NOT delete data after merging - the user owns them
780 wrap->SetDeleteData(kFALSE);
783 // Special outputs. The file must be opened and connected to the container.
784 TDirectory *opwd = gDirectory;
785 TFile *file = output->GetFile();
787 AliAnalysisTask *producer = output->GetProducer();
789 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
790 output->GetFileName(), output->GetName(), producer->ClassName());
793 TString outFilename = file->GetName();
794 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
795 if (isManagedByHandler) {
796 // Terminate IO for files managed by the output handler
797 // file->Write() moved to AOD handler (A.G. 11.01.10)
798 // if (file) file->Write();
799 if (file && fDebug > 2) {
800 printf(" handled file %s listing content:\n", file->GetName());
803 fOutputEventHandler->TerminateIO();
806 // Release object ownership to users after writing data to file
807 if (output->GetData()->InheritsFrom(TCollection::Class())) {
808 // If data is a collection, we set the name of the collection
809 // as the one of the container and we save as a single key.
810 TCollection *coll = (TCollection*)output->GetData();
811 coll->SetName(output->GetName());
812 coll->Write(output->GetName(), TObject::kSingleKey);
814 if (output->GetData()->InheritsFrom(TTree::Class())) {
815 TTree *tree = (TTree*)output->GetData();
816 tree->SetDirectory(file);
819 output->GetData()->Write();
823 printf(" file %s listing content:\n", output->GetFileName());
826 // Clear file list to release object ownership to user.
829 output->SetFile(NULL);
831 // Restore current directory
832 if (opwd) opwd->cd();
833 // Check if a special output location was provided or the output files have to be merged
834 if (strlen(fSpecialOutputLocation.Data())) {
835 TString remote = fSpecialOutputLocation;
837 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
838 if (remote.BeginsWith("alien:")) {
839 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
840 remote += outFilename;
841 remote.ReplaceAll(".root", Form("_%d.root", gid));
843 remote += Form("%s_%d_", gSystem->HostName(), gid);
844 remote += outFilename;
847 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
848 output->GetName(), remote.Data());
849 TFile::Cp ( outFilename.Data(), remote.Data() );
850 // Copy extra outputs
851 if (fExtraFiles.Length() && isManagedByHandler) {
852 TObjArray *arr = fExtraFiles.Tokenize(" ");
854 TIter nextfilename(arr);
855 while ((os=(TObjString*)nextfilename())) {
856 outFilename = os->GetString();
857 remote = fSpecialOutputLocation;
859 if (remote.BeginsWith("alien://")) {
860 remote += outFilename;
861 remote.ReplaceAll(".root", Form("_%d.root", gid));
863 remote += Form("%s_%d_", gSystem->HostName(), gid);
864 remote += outFilename;
867 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
868 outFilename.Data(), remote.Data());
869 TFile::Cp ( outFilename.Data(), remote.Data() );
874 // No special location specified-> use TProofOutputFile as merging utility
875 // The file at this output slot must be opened in CreateOutputObjects
876 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
881 fIOTime += fIOTimer->RealTime();
882 if ((fDebug || IsCollectThroughput())) {
884 fInitTime = fInitTimer->RealTime()-fIOTime-fCPUTime;
885 printf("=Analysis %s= init time: %g[sec]\
886 \n I/O & data mng.: %g [sec]\
887 \n task execution: %g [sec]\
888 \n total time: CPU=%g [sec] REAL=%g[sec]\n",
889 GetName(), fInitTime, fIOTime, fCPUTime, fInitTimer->CpuTime(), fInitTimer->RealTime());
890 if (IsCollectThroughput()) {
891 out << "#summary#########################################################" << endl;
892 out << "train_name " << GetName() << endl;
893 out << "root_time " << fInitTimer->RealTime() << endl;
894 out << "root_cpu " << fInitTimer->CpuTime() << endl;
895 out << "init_time " << fInitTime << endl;
896 out << "io_mng_time " << fIOTime << endl;
897 out << "exec_time " << fCPUTime << endl;
898 TString aliensite = gSystem->Getenv("ALIEN_SITE");
899 out << "alien_site " << aliensite << endl;
901 TString hostname = gSystem->Getenv("ALIEN_HOSTNAME");
902 if (hostname.IsNull()) {
904 gSystem->Exec(Form("hostname -f >> %s", fFileInfoLog.Data()));
906 out << hostname << endl;
911 if (cdir) cdir->cd();
912 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
915 //______________________________________________________________________________
916 void AliAnalysisManager::ImportWrappers(TList *source)
918 // Import data in output containers from wrappers coming in source.
919 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
920 fIOTimer->Start(kTRUE);
921 TIter next(fOutputs);
922 AliAnalysisDataContainer *cont;
923 AliAnalysisDataWrapper *wrap;
925 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
926 TDirectory *cdir = gDirectory;
927 while ((cont=(AliAnalysisDataContainer*)next())) {
929 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
930 if (cont->IsRegisterDataset()) continue;
931 const char *filename = cont->GetFileName();
932 Bool_t isManagedByHandler = kFALSE;
933 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
934 isManagedByHandler = kTRUE;
935 filename = fOutputEventHandler->GetOutputFileName();
937 if (cont->IsSpecialOutput() || inGrid) {
938 if (strlen(fSpecialOutputLocation.Data())) continue;
939 // Copy merged file from PROOF scratch space.
940 // In case of grid the files are already in the current directory.
942 if (isManagedByHandler && fExtraFiles.Length()) {
943 // Copy extra registered dAOD files.
944 TObjArray *arr = fExtraFiles.Tokenize(" ");
946 TIter nextfilename(arr);
947 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
950 if (!GetFileFromWrapper(filename, source)) continue;
952 // Normally we should connect data from the copied file to the
953 // corresponding output container, but it is not obvious how to do this
954 // automatically if several objects in file...
955 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
956 if (!f) f = TFile::Open(filename, "READ");
958 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
963 // Cd to the directory pointed by the container
964 TString folder = cont->GetFolderName();
965 if (!folder.IsNull()) f->cd(folder);
966 // Try to fetch first an object having the container name.
967 obj = gDirectory->Get(cont->GetName());
969 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",
970 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
973 wrap = new AliAnalysisDataWrapper(obj);
974 wrap->SetDeleteData(kFALSE);
976 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
978 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
983 printf(" Importing data for container %s\n", cont->GetName());
984 if (strlen(filename)) printf(" -> file %s\n", filename);
987 cont->ImportData(wrap);
989 if (cdir) cdir->cd();
991 fIOTime += fIOTimer->RealTime();
992 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
995 //______________________________________________________________________________
996 void AliAnalysisManager::UnpackOutput(TList *source)
998 // Called by AliAnalysisSelector::Terminate only on the client.
999 fIOTimer->Start(kTRUE);
1000 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
1002 Error("UnpackOutput", "No target. Exiting.");
1005 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
1007 if (fMode == kProofAnalysis) ImportWrappers(source);
1009 TIter next(fOutputs);
1010 AliAnalysisDataContainer *output;
1011 while ((output=(AliAnalysisDataContainer*)next())) {
1012 if (!output->GetData()) continue;
1013 // Check if there are client tasks that run post event loop
1014 if (output->HasConsumers()) {
1015 // Disable event loop semaphore
1016 output->SetPostEventLoop(kTRUE);
1017 TObjArray *list = output->GetConsumers();
1018 Int_t ncons = list->GetEntriesFast();
1019 for (Int_t i=0; i<ncons; i++) {
1020 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
1021 task->CheckNotify(kTRUE);
1022 // If task is active, execute it
1023 if (task->IsPostEventLoop() && task->IsActive()) {
1024 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
1025 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
1026 task->ExecuteTask();
1029 if (fStatistics) fStatistics->StopTimer();
1033 fIOTime += fIOTimer->RealTime();
1034 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
1037 //______________________________________________________________________________
1038 void AliAnalysisManager::Terminate()
1040 // The Terminate() function is the last function to be called during
1041 // a query. It always runs on the client, it can be used to present
1042 // the results graphically.
1043 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
1044 fInitTimer->Start(kTRUE);
1045 TDirectory *cdir = gDirectory;
1047 AliAnalysisTask *task;
1048 AliAnalysisDataContainer *output;
1051 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1052 // Call Terminate() for tasks
1054 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
1055 // Save all the canvases produced by the Terminate
1056 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
1060 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
1062 if (TObject::TestBit(kSaveCanvases)) {
1063 if (!gROOT->IsBatch()) {
1064 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
1066 while (timer.RealTime()<5) {
1068 gSystem->ProcessEvents();
1071 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
1072 if (iend==0) continue;
1074 for (Int_t ipict=0; ipict<iend; ipict++) {
1075 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
1076 if (!canvas) continue;
1077 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
1079 gROOT->GetListOfCanvases()->Delete();
1083 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
1084 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
1085 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
1087 TObjArray *allOutputs = new TObjArray();
1089 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
1090 if (!IsSkipTerminate())
1091 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
1092 TIter next1(allOutputs);
1093 TString handlerFile = "";
1094 TString extraOutputs = "";
1095 if (fOutputEventHandler) {
1096 handlerFile = fOutputEventHandler->GetOutputFileName();
1097 extraOutputs = fOutputEventHandler->GetExtraOutputs();
1101 while ((output=(AliAnalysisDataContainer*)next1())) {
1102 // Special outputs or grid files have the files already closed and written.
1104 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
1105 if (fMode == kProofAnalysis) {
1106 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
1108 const char *filename = output->GetFileName();
1109 TString openoption = "RECREATE";
1110 if (!(strcmp(filename, "default"))) continue;
1111 if (!strlen(filename)) continue;
1112 if (!output->GetData()) continue;
1113 TDirectory *opwd = gDirectory;
1114 TFile *file = output->GetFile();
1115 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1117 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
1118 Bool_t firsttime = kTRUE;
1119 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
1122 filestmp.Add(new TNamed(filename,""));
1124 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
1125 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
1126 file = new TFile(filename, openoption);
1128 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
1129 openoption = file->GetOption();
1130 if (openoption == "READ") {
1131 if (fDebug>1) printf("...reopening in UPDATE mode\n");
1132 file->ReOpen("UPDATE");
1135 if (file->IsZombie()) {
1136 Error("Terminate", "Cannot open output file %s", filename);
1139 output->SetFile(file);
1141 // Check for a folder request
1142 TString dir = output->GetFolderName();
1143 if (!dir.IsNull()) {
1144 if (!file->GetDirectory(dir)) file->mkdir(dir);
1147 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1148 if (output->GetData()->InheritsFrom(TCollection::Class())) {
1149 // If data is a collection, we set the name of the collection
1150 // as the one of the container and we save as a single key.
1151 TCollection *coll = (TCollection*)output->GetData();
1152 coll->SetName(output->GetName());
1153 coll->Write(output->GetName(), TObject::kSingleKey);
1155 if (output->GetData()->InheritsFrom(TTree::Class())) {
1156 TTree *tree = (TTree*)output->GetData();
1157 tree->SetDirectory(gDirectory);
1160 output->GetData()->Write();
1163 if (opwd) opwd->cd();
1167 TString copiedFiles;
1168 while ((output=(AliAnalysisDataContainer*)next1())) {
1169 // Close all files at output
1170 TDirectory *opwd = gDirectory;
1171 if (output->GetFile()) {
1172 // Clear file list to release object ownership to user.
1173 // output->GetFile()->Clear();
1174 output->GetFile()->Close();
1175 // Copy merged outputs in alien if requested
1176 if (fSpecialOutputLocation.BeginsWith("alien://")) {
1177 if (copiedFiles.Contains(output->GetFile()->GetName())) {
1178 if (opwd) opwd->cd();
1179 output->SetFile(NULL);
1182 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
1183 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
1184 TFile::Cp(output->GetFile()->GetName(),
1185 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
1186 copiedFiles += output->GetFile()->GetName();
1188 output->SetFile(NULL);
1190 if (opwd) opwd->cd();
1193 //Write statistics information on the client
1194 if (fStatistics) WriteStatisticsMsg(fNcalls);
1196 TDirectory *crtdir = gDirectory;
1197 TFile f("syswatch.root", "RECREATE");
1200 if (!f.IsZombie()) {
1201 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1202 tree->SetName("syswatch");
1203 tree->SetMarkerStyle(kCircle);
1204 tree->SetMarkerColor(kBlue);
1205 tree->SetMarkerSize(0.5);
1206 if (!gROOT->IsBatch()) {
1207 tree->SetAlias("event", "id0");
1208 tree->SetAlias("task", "id1");
1209 tree->SetAlias("stage", "id2");
1210 // Already defined aliases
1211 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1212 // tree->SetAlias("T","stampSec-first");
1213 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1214 // tree->SetAlias("VM","pI.fMemVirtual");
1215 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1216 Int_t npads = 1 /*COO plot for all tasks*/ +
1217 fTopTasks->GetEntries() /*Exec plot per task*/ +
1218 1 /*Terminate plot for all tasks*/ +
1221 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1222 if (npads<iopt*(iopt+1))
1223 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1225 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1227 // draw the plot of deltaVM for Exec for each task
1228 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1229 task = (AliAnalysisTask*)fTopTasks->At(itask);
1231 cut = Form("task==%d && stage==1", itask);
1232 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1233 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1235 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1236 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1239 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1241 tree->SetMarkerStyle(kFullTriangleUp);
1242 tree->SetMarkerColor(kRed);
1243 tree->SetMarkerSize(0.8);
1244 cut = "task>=0 && task<1000 && stage==0";
1245 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1246 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1248 hist->SetTitle("Memory in CreateOutputObjects()");
1249 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1250 hist->GetXaxis()->SetTitle("task");
1252 // draw the plot of deltaVM for Terminate for all tasks
1254 tree->SetMarkerStyle(kOpenSquare);
1255 tree->SetMarkerColor(kMagenta);
1256 cut = "task>=0 && task<1000 && stage==2";
1257 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1258 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1260 hist->SetTitle("Memory in Terminate()");
1261 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1262 hist->GetXaxis()->SetTitle("task");
1266 tree->SetMarkerStyle(kFullCircle);
1267 tree->SetMarkerColor(kGreen);
1268 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1269 tree->Draw("VM:event",cut,"", 1234567890, 0);
1270 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1272 hist->SetTitle("Virtual memory");
1273 hist->GetYaxis()->SetTitle("VM [MB]");
1277 tree->SetMarkerStyle(kCircle);
1278 tree->SetMarkerColor(kBlue);
1279 tree->SetMarkerSize(0.5);
1284 if (crtdir) crtdir->cd();
1286 // Validate the output files
1287 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1289 out.open("outputs_valid", ios::out);
1292 if (cdir) cdir->cd();
1294 if (fDebug || IsCollectThroughput()) {
1295 printf("=Analysis %s= Terminate time: %g[sec]\n", GetName(), fInitTimer->RealTime());
1297 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1299 //______________________________________________________________________________
1300 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1302 // Profiles the task having the itop index in the list of top (first level) tasks.
1303 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1305 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1308 ProfileTask(task->GetName(), option);
1311 //______________________________________________________________________________
1312 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1314 // Profile a managed task after the execution of the analysis in case NSysInfo
1316 if (gSystem->AccessPathName("syswatch.root")) {
1317 Error("ProfileTask", "No file syswatch.root found in the current directory");
1320 if (gROOT->IsBatch()) return;
1321 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1323 Error("ProfileTask", "No top task named %s known by the manager.", name);
1326 Int_t itop = fTopTasks->IndexOf(task);
1327 Int_t itask = fTasks->IndexOf(task);
1328 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1329 TDirectory *cdir = gDirectory;
1330 TFile f("syswatch.root");
1331 TTree *tree = (TTree*)f.Get("syswatch");
1333 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1336 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1337 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1338 canvas->Divide(2, 2, 0.01, 0.01);
1342 // VM profile for COO and Terminate methods
1344 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1345 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1346 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1348 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1349 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1350 hist->GetXaxis()->SetTitle("method");
1352 // CPU profile per event
1354 cut = Form("task==%d && stage==1",itop);
1355 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1356 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1358 hist->SetTitle("Execution time per event");
1359 hist->GetYaxis()->SetTitle("CPU/event [s]");
1361 // VM profile for Exec
1363 cut = Form("task==%d && stage==1",itop);
1364 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1365 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1367 hist->SetTitle("Alocated VM[MB] per event");
1368 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1373 if (cdir) cdir->cd();
1376 //______________________________________________________________________________
1377 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1379 // Adds a user task to the global list of tasks.
1381 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1385 if (fTasks->FindObject(task)) {
1386 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1389 task->SetActive(kFALSE);
1393 //______________________________________________________________________________
1394 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1396 // Retreive task by name.
1397 if (!fTasks) return NULL;
1398 return (AliAnalysisTask*)fTasks->FindObject(name);
1401 //______________________________________________________________________________
1402 Int_t AliAnalysisManager::GetTaskIndex(const AliAnalysisTask *task) const
1404 // Returns task inded in the manager's list, -1 if not registered.
1405 if (!fTasks) return -1;
1406 return fTasks->IndexOf(task);
1409 //______________________________________________________________________________
1410 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1411 TClass *datatype, EAliAnalysisContType type, const char *filename)
1413 // Create a data container of a certain type. Types can be:
1414 // kExchangeContainer = 0, used to exchange data between tasks
1415 // kInputContainer = 1, used to store input data
1416 // kOutputContainer = 2, used for writing result to a file
1417 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1418 // the output object to a folder inside the output file
1419 if (fContainers->FindObject(name)) {
1420 Error("CreateContainer","A container named %s already defined !",name);
1423 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1424 fContainers->Add(cont);
1426 case kInputContainer:
1429 case kOutputContainer:
1430 fOutputs->Add(cont);
1431 if (filename && strlen(filename)) {
1432 cont->SetFileName(filename);
1433 cont->SetDataOwned(kFALSE); // data owned by the file
1436 case kParamContainer:
1437 fParamCont->Add(cont);
1438 if (filename && strlen(filename)) {
1439 cont->SetFileName(filename);
1440 cont->SetDataOwned(kFALSE); // data owned by the file
1443 case kExchangeContainer:
1449 //______________________________________________________________________________
1450 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1451 AliAnalysisDataContainer *cont)
1453 // Connect input of an existing task to a data container.
1455 Error("ConnectInput", "Task pointer is NULL");
1458 if (!fTasks->FindObject(task)) {
1460 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1462 Bool_t connected = task->ConnectInput(islot, cont);
1466 //______________________________________________________________________________
1467 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1468 AliAnalysisDataContainer *cont)
1470 // Connect output of an existing task to a data container.
1472 Error("ConnectOutput", "Task pointer is NULL");
1475 if (!fTasks->FindObject(task)) {
1477 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1479 Bool_t connected = task->ConnectOutput(islot, cont);
1483 //______________________________________________________________________________
1484 void AliAnalysisManager::CleanContainers()
1486 // Clean data from all containers that have already finished all client tasks.
1487 TIter next(fContainers);
1488 AliAnalysisDataContainer *cont;
1489 while ((cont=(AliAnalysisDataContainer *)next())) {
1490 if (cont->IsOwnedData() &&
1491 cont->IsDataReady() &&
1492 cont->ClientsExecuted()) cont->DeleteData();
1496 //______________________________________________________________________________
1497 Bool_t AliAnalysisManager::InitAnalysis()
1499 // Initialization of analysis chain of tasks. Should be called after all tasks
1500 // and data containers are properly connected
1501 // Reset flag and remove valid_outputs file if exists
1502 if (fInitOK) return kTRUE;
1503 if (!gSystem->AccessPathName("outputs_valid"))
1504 gSystem->Unlink("outputs_valid");
1505 // Check for top tasks (depending only on input data containers)
1506 if (!fTasks->First()) {
1507 Error("InitAnalysis", "Analysis has no tasks !");
1511 AliAnalysisTask *task;
1512 AliAnalysisDataContainer *cont;
1515 Bool_t iszombie = kFALSE;
1516 Bool_t istop = kTRUE;
1518 while ((task=(AliAnalysisTask*)next())) {
1521 Int_t ninputs = task->GetNinputs();
1522 for (i=0; i<ninputs; i++) {
1523 cont = task->GetInputSlot(i)->GetContainer();
1527 fZombies->Add(task);
1531 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1532 i, task->GetName());
1534 if (iszombie) continue;
1535 // Check if cont is an input container
1536 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1537 // Connect to parent task
1541 fTopTasks->Add(task);
1545 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1548 // Check now if there are orphan tasks
1549 for (i=0; i<ntop; i++) {
1550 task = (AliAnalysisTask*)fTopTasks->At(i);
1555 while ((task=(AliAnalysisTask*)next())) {
1556 if (!task->IsUsed()) {
1558 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1561 // Check the task hierarchy (no parent task should depend on data provided
1562 // by a daughter task)
1563 for (i=0; i<ntop; i++) {
1564 task = (AliAnalysisTask*)fTopTasks->At(i);
1565 if (task->CheckCircularDeps()) {
1566 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1571 // Check that all containers feeding post-event loop tasks are in the outputs list
1572 TIter nextcont(fContainers); // loop over all containers
1573 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1574 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1575 if (cont->HasConsumers()) {
1576 // Check if one of the consumers is post event loop
1577 TIter nextconsumer(cont->GetConsumers());
1578 while ((task=(AliAnalysisTask*)nextconsumer())) {
1579 if (task->IsPostEventLoop()) {
1580 fOutputs->Add(cont);
1587 // Check if all special output containers have a file name provided
1588 TIter nextout(fOutputs);
1589 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1590 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1591 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1595 // Initialize requested branch list if needed
1596 if (!fAutoBranchHandling) {
1598 while ((task=(AliAnalysisTask*)next())) {
1599 if (!task->HasBranches()) {
1600 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\"",
1601 task->GetName(), task->ClassName());
1604 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1605 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1608 TString taskbranches;
1609 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1610 if (taskbranches.IsNull()) {
1611 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1612 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1615 AddBranches(taskbranches);
1622 //______________________________________________________________________________
1623 void AliAnalysisManager::AddBranches(const char *branches)
1625 // Add branches to the existing fRequestedBranches.
1626 TString br(branches);
1627 TObjArray *arr = br.Tokenize(",");
1630 while ((obj=next())) {
1631 if (!fRequestedBranches.Contains(obj->GetName())) {
1632 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1633 fRequestedBranches += obj->GetName();
1639 //______________________________________________________________________________
1640 void AliAnalysisManager::CheckBranches(Bool_t load)
1642 // The method checks the input branches to be loaded during the analysis.
1643 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1644 TObjArray *arr = fRequestedBranches.Tokenize(",");
1647 while ((obj=next())) {
1648 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1650 br = fTree->GetBranch(obj->GetName());
1652 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1657 if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1658 br->GetEntry(GetCurrentEntry());
1664 //______________________________________________________________________________
1665 Bool_t AliAnalysisManager::CheckTasks() const
1667 // Check consistency of tasks.
1668 Int_t ntasks = fTasks->GetEntries();
1670 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1673 // Get the pointer to AliAnalysisTaskSE::Class()
1674 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1675 // Loop all tasks to check if their corresponding library was loaded
1678 while ((obj=next())) {
1679 if (obj->IsA() == badptr) {
1680 Error("CheckTasks", "##################\n \
1681 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1688 //______________________________________________________________________________
1689 void AliAnalysisManager::PrintStatus(Option_t *option) const
1691 // Print task hierarchy.
1693 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1696 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1698 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1699 TIter next(fTopTasks);
1700 AliAnalysisTask *task;
1701 while ((task=(AliAnalysisTask*)next()))
1702 task->PrintTask(option);
1704 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1705 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1707 TString sopt(option);
1710 if (sopt.Contains("ALL"))
1712 if ( fOutputEventHandler )
1714 cout << TString('_',78) << endl;
1715 cout << "OutputEventHandler:" << endl;
1716 fOutputEventHandler->Print(" ");
1721 //______________________________________________________________________________
1722 void AliAnalysisManager::ResetAnalysis()
1724 // Reset all execution flags and clean containers.
1728 //______________________________________________________________________________
1729 void AliAnalysisManager::RunLocalInit()
1731 // Run LocalInit method for all tasks.
1732 TDirectory *cdir = gDirectory;
1733 if (IsTrainInitialized()) return;
1734 TIter nextTask(fTasks);
1735 AliAnalysisTask *task;
1736 while ((task=(AliAnalysisTask*)nextTask())) {
1740 if (cdir) cdir->cd();
1741 TObject::SetBit(kTasksInitialized, kTRUE);
1744 //______________________________________________________________________________
1745 void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1747 // Retrieves name of the file from tree
1750 TFile *file = tree->GetCurrentFile();
1753 TChain *chain = dynamic_cast<TChain*>(tree);
1754 if (!chain || !chain->GetNtrees()) return;
1755 basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1757 basename = gSystem->BaseName(file->GetName());
1759 Int_t index = basename.Index("#");
1760 fname = basename(index+1, basename.Length());
1763 //______________________________________________________________________________
1764 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1766 // Start analysis having a grid handler.
1767 if (!fGridHandler) {
1768 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1769 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1773 return StartAnalysis(type, tree, nentries, firstentry);
1776 //______________________________________________________________________________
1777 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1779 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1780 // MIX. Process nentries starting from firstentry
1782 // Backup current directory and make sure gDirectory points to gROOT
1783 TDirectory *cdir = gDirectory;
1786 Error("StartAnalysis","Analysis manager was not initialized !");
1787 if (cdir) cdir->cd();
1790 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1792 printf("StartAnalysis %s\n",GetName());
1793 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1795 fMaxEntries = nentries;
1797 TString anaType = type;
1799 fMode = kLocalAnalysis;
1800 if (anaType.Contains("file")) fIsRemote = kTRUE;
1801 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1802 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1803 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1804 if (fInputEventHandler) {
1806 InputFileFromTree(tree, fname);
1807 if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1810 if (fMode == kGridAnalysis) {
1812 if (!anaType.Contains("terminate")) {
1813 if (!fGridHandler) {
1814 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1815 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1816 if (cdir) cdir->cd();
1819 // Write analysis manager in the analysis file
1820 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1821 // run local task configuration
1823 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1824 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1825 if (cdir) cdir->cd();
1829 // Terminate grid analysis
1830 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1831 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1832 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1833 if (!fGridHandler->MergeOutputs()) {
1834 // Return if outputs could not be merged or if it alien handler
1835 // was configured for offline mode or local testing.
1836 if (cdir) cdir->cd();
1840 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1841 if (cdir) cdir->cd();
1842 ImportWrappers(NULL);
1844 if (cdir) cdir->cd();
1848 SetEventLoop(kFALSE);
1849 // Enable event loop mode if a tree was provided
1850 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1853 TString ttype = "TTree";
1854 if (tree && tree->IsA() == TChain::Class()) {
1855 chain = (TChain*)tree;
1856 if (!chain || !chain->GetListOfFiles()->First()) {
1857 Error("StartAnalysis", "Cannot process null or empty chain...");
1858 if (cdir) cdir->cd();
1864 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1865 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1866 // Initialize locally all tasks (happens for all modes)
1868 AliAnalysisTask *task;
1872 case kLocalAnalysis:
1873 if (!tree && !fGridHandler) {
1874 TIter nextT(fTasks);
1875 // Call CreateOutputObjects for all tasks
1877 Bool_t dirStatus = TH1::AddDirectoryStatus();
1878 while ((task=(AliAnalysisTask*)nextT())) {
1879 TH1::AddDirectory(kFALSE);
1880 task->CreateOutputObjects();
1881 if (!task->CheckPostData()) {
1882 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1883 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1884 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1886 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1890 TH1::AddDirectory(dirStatus);
1891 if (IsExternalLoop()) {
1892 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1893 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1900 fSelector = new AliAnalysisSelector(this);
1901 // Check if a plugin handler is used
1903 // Get the chain from the plugin
1904 TString dataType = "esdTree";
1905 if (fInputEventHandler) {
1906 dataType = fInputEventHandler->GetDataType();
1910 chain = fGridHandler->GetChainForTestMode(dataType);
1912 Error("StartAnalysis", "No chain for test mode. Aborting.");
1915 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1916 retv = chain->Process(fSelector, "", nentries, firstentry);
1919 // Run tree-based analysis via AliAnalysisSelector
1920 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1921 retv = tree->Process(fSelector, "", nentries, firstentry);
1923 case kProofAnalysis:
1925 // Check if the plugin is used
1927 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1929 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1930 Error("StartAnalysis", "No PROOF!!! Exiting.");
1931 if (cdir) cdir->cd();
1934 line = Form("gProof->AddInput((TObject*)%p);", this);
1935 gROOT->ProcessLine(line);
1938 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1939 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1941 Error("StartAnalysis", "No chain!!! Exiting.");
1942 if (cdir) cdir->cd();
1948 if (!anaType.Contains("terminate")) {
1949 if (!fGridHandler) {
1950 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1951 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1952 if (cdir) cdir->cd();
1955 // Write analysis manager in the analysis file
1956 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1957 // Start the analysis via the handler
1958 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1959 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1960 if (cdir) cdir->cd();
1964 // Terminate grid analysis
1965 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1966 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1967 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1968 if (!fGridHandler->MergeOutputs()) {
1969 // Return if outputs could not be merged or if it alien handler
1970 // was configured for offline mode or local testing.
1971 if (cdir) cdir->cd();
1975 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1976 ImportWrappers(NULL);
1978 if (cdir) cdir->cd();
1980 case kMixingAnalysis:
1981 // Run event mixing analysis
1983 Error("StartAnalysis", "Cannot run event mixing without event pool");
1984 if (cdir) cdir->cd();
1987 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1988 fSelector = new AliAnalysisSelector(this);
1989 while ((chain=fEventPool->GetNextChain())) {
1991 // Call NotifyBinChange for all tasks
1992 while ((task=(AliAnalysisTask*)next()))
1993 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1994 retv = chain->Process(fSelector);
1996 Error("StartAnalysis", "Mixing analysis failed");
1997 if (cdir) cdir->cd();
2001 PackOutput(fSelector->GetOutputList());
2004 if (cdir) cdir->cd();
2008 //______________________________________________________________________________
2009 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
2011 // Start analysis for this manager on a given dataset. Analysis task can be:
2012 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
2014 Error("StartAnalysis","Analysis manager was not initialized !");
2018 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
2019 TString anaType = type;
2021 if (!anaType.Contains("proof")) {
2022 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
2025 fMode = kProofAnalysis;
2027 TString proofProcessOpt;
2028 SetEventLoop(kTRUE);
2029 // Set the dataset flag
2030 TObject::SetBit(kUseDataSet);
2033 // Start proof analysis using the grid handler
2034 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
2035 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
2038 // Check if the plugin is in test mode
2039 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
2040 dataset = "test_collection";
2042 dataset = fGridHandler->GetProofDataSet();
2045 proofProcessOpt = fGridHandler->GetProofProcessOpt();
2048 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
2049 Error("StartAnalysis", "No PROOF!!! Exiting.");
2053 // Initialize locally all tasks
2056 line = Form("gProof->AddInput((TObject*)%p);", this);
2057 gROOT->ProcessLine(line);
2059 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2060 dataset,proofProcessOpt.Data(), nentries, firstentry);
2061 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2062 retv = (Long_t)gROOT->ProcessLine(line);
2066 //______________________________________________________________________________
2067 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2069 // Opens according the option the file specified by cont->GetFileName() and changes
2070 // current directory to cont->GetFolderName(). If the file was already opened, it
2071 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
2072 // be optionally ignored.
2073 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2074 TString filename = cont->GetFileName();
2076 if (filename.IsNull()) {
2077 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2080 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2082 f = mgr->OpenProofFile(cont,option);
2084 // Check first if the file is already opened
2085 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2087 // Check if option "UPDATE" was preserved
2088 TString opt(option);
2090 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2091 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2093 f = TFile::Open(filename, option);
2096 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2100 // Check for a folder request
2101 TString dir = cont->GetFolderName();
2102 if (!dir.IsNull()) {
2103 if (!f->GetDirectory(dir)) f->mkdir(dir);
2108 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2109 cont->SetFile(NULL);
2113 //______________________________________________________________________________
2114 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
2116 // Opens a special output file used in PROOF.
2118 TString filename = cont->GetFileName();
2119 if (cont == fCommonOutput) {
2120 if (fOutputEventHandler) {
2121 if (strlen(extaod)) filename = extaod;
2122 filename = fOutputEventHandler->GetOutputFileName();
2124 else Fatal("OpenProofFile","No output container. Exiting.");
2127 if (fMode!=kProofAnalysis || !fSelector) {
2128 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2131 if (fSpecialOutputLocation.Length()) {
2132 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2134 // Check if option "UPDATE" was preserved
2135 TString opt(option);
2137 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2138 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2140 f = new TFile(filename, option);
2142 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2146 // Check for a folder request
2147 TString dir = cont->GetFolderName();
2149 if (!f->GetDirectory(dir)) f->mkdir(dir);
2154 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2155 cont->SetFile(NULL);
2158 // Check if there is already a proof output file in the output list
2159 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2161 // Get the actual file
2162 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
2163 filename = (const char*)gROOT->ProcessLine(line);
2165 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2167 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2169 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2172 // Check if option "UPDATE" was preserved
2173 TString opt(option);
2175 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2176 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2178 if (cont->IsRegisterDataset()) {
2179 TString dsetName = filename;
2180 dsetName.ReplaceAll(".root", cont->GetTitle());
2181 dsetName.ReplaceAll(":","_");
2182 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2183 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
2185 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2186 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2188 if (fDebug > 1) printf("=== %s\n", line.Data());
2189 gROOT->ProcessLine(line);
2190 line = Form("pf->OpenFile(\"%s\");", option);
2191 gROOT->ProcessLine(line);
2194 gROOT->ProcessLine("pf->Print()");
2195 printf(" == proof file name: %s", f->GetName());
2197 // Add to proof output list
2198 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2199 if (fDebug > 1) printf("=== %s\n", line.Data());
2200 gROOT->ProcessLine(line);
2202 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2206 // Check for a folder request
2207 TString dir = cont->GetFolderName();
2208 if (!dir.IsNull()) {
2209 if (!f->GetDirectory(dir)) f->mkdir(dir);
2214 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2215 cont->SetFile(NULL);
2219 //______________________________________________________________________________
2220 void AliAnalysisManager::ExecAnalysis(Option_t *option)
2222 // Execute analysis.
2223 static Long64_t nentries = 0;
2224 static TTree *lastTree = 0;
2225 static TStopwatch *timer = new TStopwatch();
2226 // Only the first call to Process will trigger a true Notify. Other Notify
2227 // coming before is ignored.
2228 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2229 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2232 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2234 if (fTree && (fTree != lastTree)) {
2235 nentries += fTree->GetEntries();
2238 if (!fNcalls) timer->Start();
2239 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2241 fIOTimer->Start(kTRUE);
2243 TDirectory *cdir = gDirectory;
2244 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2245 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2247 Error("ExecAnalysis", "Analysis manager was not initialized !");
2248 if (cdir) cdir->cd();
2252 AliAnalysisTask *task;
2253 // Check if the top tree is active.
2255 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2256 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2258 // De-activate all tasks
2259 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2260 AliAnalysisDataContainer *cont = fCommonInput;
2261 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2263 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2264 if (cdir) cdir->cd();
2267 cont->SetData(fTree); // This will notify all consumers
2268 Long64_t entry = fTree->GetTree()->GetReadEntry();
2270 // Call BeginEvent() for optional input/output and MC services
2271 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2272 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2273 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2275 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2276 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2278 // Execute the tasks
2279 // TIter next1(cont->GetConsumers());
2281 fIOTime += fIOTimer->RealTime();
2282 fCPUTimer->Start(kTRUE);
2283 TIter next1(fTopTasks);
2285 while ((task=(AliAnalysisTask*)next1())) {
2287 cout << " Executing task " << task->GetName() << endl;
2289 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2290 task->ExecuteTask(option);
2291 if (fStatistics) fStatistics->StopTimer();
2293 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2294 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2298 fCPUTime += fCPUTimer->RealTime();
2299 fIOTimer->Start(kTRUE);
2301 // Call FinishEvent() for optional output and MC services
2302 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2303 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2304 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2305 // Gather system information if requested
2306 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2307 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2308 if (cdir) cdir->cd();
2310 fIOTime += fIOTimer->RealTime();
2313 // The event loop is not controlled by TSelector
2315 // Call BeginEvent() for optional input/output and MC services
2316 fIOTimer->Start(kTRUE);
2317 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2318 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2319 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2321 fIOTime += fIOTimer->RealTime();
2323 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2324 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2325 fCPUTimer->Start(kTRUE);
2326 TIter next2(fTopTasks);
2327 while ((task=(AliAnalysisTask*)next2())) {
2328 task->SetActive(kTRUE);
2330 cout << " Executing task " << task->GetName() << endl;
2332 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2333 task->ExecuteTask(option);
2334 if (fStatistics) fStatistics->StopTimer();
2338 fCPUTime += fCPUTimer->RealTime();
2340 // Call FinishEvent() for optional output and MC services
2341 fIOTimer->Start(kTRUE);
2342 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2343 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2344 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2345 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2346 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2347 if (cdir) cdir->cd();
2349 fIOTime += fIOTimer->RealTime();
2352 //______________________________________________________________________________
2353 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2355 // Check if the stdout is connected to a pipe (C.Holm)
2356 Bool_t ispipe = kFALSE;
2357 out.seekp(0, std::ios_base::cur);
2360 if (errno == ESPIPE) ispipe = kTRUE;
2365 //______________________________________________________________________________
2366 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2368 // Set the input event handler and create a container for it.
2370 fInputEventHandler = handler;
2371 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2374 //______________________________________________________________________________
2375 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2377 // Set the input event handler and create a container for it.
2379 fOutputEventHandler = handler;
2380 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2381 fCommonOutput->SetSpecialOutput();
2384 //______________________________________________________________________________
2385 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2387 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2388 if (TObject::TestBit(kUseProgressBar)) {
2389 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2395 //______________________________________________________________________________
2396 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2398 // Enable a text mode progress bar. Resets debug level to 0.
2399 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2400 TObject::SetBit(kUseProgressBar,flag);
2401 fPBUpdateFreq = freq;
2405 //______________________________________________________________________________
2406 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2408 // This method is used externally to register output files which are not
2409 // connected to any output container, so that the manager can properly register,
2410 // retrieve or merge them when running in distributed mode. The file names are
2411 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2412 if (fExtraFiles.Contains(fname)) return;
2413 if (fExtraFiles.Length()) fExtraFiles += " ";
2414 fExtraFiles += fname;
2417 //______________________________________________________________________________
2418 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2420 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2424 TObject *pof = source->FindObject(filename);
2425 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2426 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2429 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2430 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2431 TString clientUrl(chUrl);
2432 TString fullPath_str(fullPath);
2433 if (clientUrl.Contains("localhost")){
2434 TObjArray* array = fullPath_str.Tokenize ( "//" );
2435 TObjString *strobj = ( TObjString *)array->At(1);
2436 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2437 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2438 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2439 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2440 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2444 else if (clientUrl.Contains("__lite__")) {
2445 // Special case for ProofLite environement - get file info and copy.
2446 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2447 fullPath_str = Form("%s/%s", tmp, fullPath);
2450 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2451 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2453 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2457 //______________________________________________________________________________
2458 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2460 // Fill analysis type in the provided string.
2462 case kLocalAnalysis:
2465 case kProofAnalysis:
2471 case kMixingAnalysis:
2476 //______________________________________________________________________________
2477 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2479 // Validate all output files.
2480 TIter next(fOutputs);
2481 AliAnalysisDataContainer *output;
2482 TDirectory *cdir = gDirectory;
2483 TString openedFiles;
2484 while ((output=(AliAnalysisDataContainer*)next())) {
2485 if (output->IsRegisterDataset()) continue;
2486 TString filename = output->GetFileName();
2487 if (filename == "default") {
2488 if (!fOutputEventHandler) continue;
2489 filename = fOutputEventHandler->GetOutputFileName();
2490 // Main AOD may not be there
2491 if (gSystem->AccessPathName(filename)) continue;
2493 // Check if the file is closed
2494 if (openedFiles.Contains(filename)) continue;;
2495 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2497 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2498 // Clear file list to release object ownership to user.
2502 file = TFile::Open(filename);
2503 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2504 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2505 if (cdir) cdir->cd();
2509 openedFiles += filename;
2512 if (cdir) cdir->cd();
2516 //______________________________________________________________________________
2517 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2519 // Implements a nice text mode progress bar.
2520 static Long64_t icount = 0;
2521 static TString oname;
2522 static TString nname;
2523 static Long64_t ocurrent = 0;
2524 static Long64_t osize = 0;
2525 static Int_t oseconds = 0;
2526 static TStopwatch *owatch = 0;
2527 static Bool_t oneoftwo = kFALSE;
2528 static Int_t nrefresh = 0;
2529 static Int_t nchecks = 0;
2530 static char lastChar = 0;
2531 const char symbol[4] = {'-','\\','|','/'};
2533 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2539 ocurrent = TMath::Abs(current);
2540 osize = TMath::Abs(size);
2541 if (ocurrent > osize) ocurrent=osize;
2546 if ((current % fPBUpdateFreq) != 0) return;
2548 char progress[11] = " ";
2549 Int_t ichar = icount%4;
2554 if (owatch && !last) {
2556 time = owatch->RealTime();
2557 seconds = int(time) % 60;
2558 minutes = (int(time) / 60) % 60;
2559 hours = (int(time) / 60 / 60);
2561 if (oseconds==seconds) {
2565 oneoftwo = !oneoftwo;
2569 if (refresh && oneoftwo) {
2571 if (nchecks <= 0) nchecks = nrefresh+1;
2572 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2573 oname = Form(" == %d%% ==", pctdone);
2575 Double_t percent = 100.0*ocurrent/osize;
2576 Int_t nchar = Int_t(percent/10);
2577 if (nchar>10) nchar=10;
2579 for (i=0; i<nchar; i++) progress[i] = '=';
2580 progress[nchar] = symbol[ichar];
2581 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2582 progress[10] = '\0';
2585 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2586 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2587 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2589 Int_t full = Int_t(ocurrent > 0 ?
2590 time * (float(osize)/ocurrent) + .5 :
2592 Int_t remain = Int_t(full - time);
2593 Int_t rsec = remain % 60;
2594 Int_t rmin = (remain / 60) % 60;
2595 Int_t rhour = (remain / 60 / 60);
2596 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2597 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2599 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2600 if (refresh && oneoftwo) oname = nname;
2601 if (owatch) owatch->Continue();
2610 fprintf(stderr, "\n");
2614 //______________________________________________________________________________
2615 void AliAnalysisManager::DoLoadBranch(const char *name)
2617 // Get tree and load branch if needed.
2618 static Long64_t crtEntry = -100;
2620 if (fAutoBranchHandling || !fTree)
2623 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2625 br = fTree->GetBranch(name);
2627 Error("DoLoadBranch", "Could not find branch %s",name);
2632 if (br->GetReadEntry()==fCurrentEntry) return;
2633 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2635 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2636 if (crtEntry != fCurrentEntry) {
2637 CountEvent(1,0,1,0);
2638 crtEntry = fCurrentEntry;
2641 if (crtEntry != fCurrentEntry) {
2642 CountEvent(1,1,0,0);
2643 crtEntry = fCurrentEntry;
2648 //______________________________________________________________________________
2649 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2651 // Add the statistics task to the manager.
2653 Info("AddStatisticsTask", "Already added");
2656 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2657 gROOT->ProcessLine(line);
2660 //______________________________________________________________________________
2661 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2663 // Bookkeep current event;
2664 if (!fStatistics) return;
2665 fStatistics->AddInput(ninput);
2666 fStatistics->AddProcessed(nprocessed);
2667 fStatistics->AddFailed(nfailed);
2668 fStatistics->AddAccepted(naccepted);
2671 //______________________________________________________________________________
2672 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2674 // Add a line in the statistics message. If available, the statistics message is written
2675 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2677 if (!strlen(line)) return;
2678 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2679 fStatisticsMsg += line;
2682 //______________________________________________________________________________
2683 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2685 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2686 static Bool_t done = kFALSE;
2689 if (!fStatistics) return;
2691 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2692 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2693 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2694 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2695 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2696 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2697 fStatistics->GetNaccepted()), ios::out);
2698 out << fStatisticsMsg << endl;
2702 //______________________________________________________________________________
2703 const char* AliAnalysisManager::GetOADBPath()
2705 // returns the path of the OADB
2706 // this static function just depends on environment variables
2708 static TString oadbPath;
2710 if (gSystem->Getenv("OADB_PATH"))
2711 oadbPath = gSystem->Getenv("OADB_PATH");
2712 else if (gSystem->Getenv("ALICE_ROOT"))
2713 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2715 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2720 //______________________________________________________________________________
2721 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2723 // Define a custom string variable mapped to a global unique name. The variable
2724 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2725 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2727 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2730 Bool_t valid = kFALSE;
2731 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2733 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2736 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2739 //______________________________________________________________________________
2740 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2742 // Static method to retrieve a global variable defined via SetGlobalStr.
2744 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2746 TObject *value = mgr->GetGlobals()->GetValue(key);
2747 if (!value) return 0;
2749 return value->GetName();
2752 //______________________________________________________________________________
2753 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2755 // Define a custom integer variable mapped to a global unique name. The variable
2756 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2757 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2759 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2762 Bool_t valid = kFALSE;
2763 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2765 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2768 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2771 //______________________________________________________________________________
2772 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2774 // Static method to retrieve a global variable defined via SetGlobalInt.
2776 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2778 TObject *value = mgr->GetGlobals()->GetValue(key);
2779 if (!value) return 0;
2781 TString s = value->GetName();
2785 //______________________________________________________________________________
2786 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2788 // Define a custom double precision variable mapped to a global unique name. The variable
2789 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2790 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2792 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2795 Bool_t valid = kFALSE;
2796 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2798 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2801 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2804 //______________________________________________________________________________
2805 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2807 // Static method to retrieve a global variable defined via SetGlobalDbl.
2809 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2811 TObject *value = mgr->GetGlobals()->GetValue(key);
2812 if (!value) return 0;
2814 TString s = value->GetName();
2818 //______________________________________________________________________________
2819 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2821 // Sets Class debug level
2823 if (!fDebugOptions) {
2824 fDebugOptions = new TObjArray();
2825 fDebugOptions->SetOwner(kTRUE);
2828 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2830 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
2831 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2833 TString oldDebugStr = debugOpt->GetTitle();
2834 Int_t oldDebug = oldDebugStr.Atoi();
2835 if (debugLevel > oldDebug) {
2836 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
2837 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2839 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
2844 //______________________________________________________________________________
2845 void AliAnalysisManager::ApplyDebugOptions()
2847 // Apply debug options
2849 if (!fDebugOptions) return;
2851 TIter next(fDebugOptions);
2854 while ((debug=dynamic_cast<TNamed*>(next()))) {
2855 debugLevel = debug->GetTitle();
2856 AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
2857 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2861 //______________________________________________________________________________
2862 Bool_t AliAnalysisManager::IsMacroLoaded(const char * filename)
2864 // Check if a macro was loaded.
2865 return fgMacroNames.Contains(filename);
2868 //______________________________________________________________________________
2869 Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2871 // Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded
2873 TString macroName = gSystem->BaseName(filename);
2874 // Strip appended +, ++, +g, +O
2875 Int_t index = macroName.Index("+");
2876 if (index>0) macroName.Remove(index);
2877 if (fgMacroNames.Contains(macroName)) {
2878 // Macro with the same name loaded already in this root session, do
2883 Int_t ret = gROOT->LoadMacro(filename,error,check);
2884 // In case of error return the error code
2885 if (ret) return ret;
2886 // Append the macro name to the loaded macros list
2887 fgMacroNames += macroName;
2888 fgMacroNames += " ";
2892 //______________________________________________________________________________
2893 void AliAnalysisManager::Lock()
2895 // Security lock. This is to detect NORMAL user errors and not really to
2896 // protect against intentional hacks.
2897 if (fLocked) return;
2899 if (fInputEventHandler) fInputEventHandler->Lock();
2900 if (fOutputEventHandler) fOutputEventHandler->Lock();
2901 if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2902 Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2905 //______________________________________________________________________________
2906 void AliAnalysisManager::UnLock()
2908 // Verbose unlocking. Hackers will be punished ;-) ...
2909 if (!fLocked) return;
2911 if (fInputEventHandler) fInputEventHandler->UnLock();
2912 if (fOutputEventHandler) fOutputEventHandler->UnLock();
2913 if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2914 Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2917 //______________________________________________________________________________
2918 void AliAnalysisManager::Changed()
2920 // All critical setters pass through the Changed method that throws an exception
2921 // in case the lock was set.
2922 if (fLocked) Fatal("Changed","Critical setter called in locked mode");