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>
38 #include <TMethodCall.h>
43 #include <TStopwatch.h>
46 #include "AliAnalysisSelector.h"
47 #include "AliAnalysisGrid.h"
48 #include "AliAnalysisTask.h"
49 #include "AliAnalysisDataContainer.h"
50 #include "AliAnalysisDataSlot.h"
51 #include "AliVEventHandler.h"
52 #include "AliVEventPool.h"
53 #include "AliSysInfo.h"
54 #include "AliAnalysisStatistics.h"
60 ClassImp(AliAnalysisManager)
62 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
63 TString AliAnalysisManager::fgCommonFileName = "";
64 Int_t AliAnalysisManager::fPBUpdateFreq = 1;
66 //______________________________________________________________________________
67 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
70 fInputEventHandler(0),
71 fOutputEventHandler(0),
72 fMCtruthEventHandler(0),
76 fMode(kLocalAnalysis),
81 fSpecialOutputLocation(""),
90 fFileDescriptors(new TObjArray()),
91 fCurrentDescriptor(0),
98 fAutoBranchHandling(kTRUE),
104 fRequestedBranches(),
108 // Default constructor.
109 fgAnalysisManager = this;
110 fgCommonFileName = "AnalysisResults.root";
111 if (TClass::IsCallingNew() != TClass::kDummyNew) {
112 fTasks = new TObjArray();
113 fTopTasks = new TObjArray();
114 fZombies = new TObjArray();
115 fContainers = new TObjArray();
116 fInputs = new TObjArray();
117 fOutputs = new TObjArray();
118 fParamCont = new TObjArray();
119 fGlobals = new TMap();
124 //______________________________________________________________________________
125 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
128 fInputEventHandler(NULL),
129 fOutputEventHandler(NULL),
130 fMCtruthEventHandler(NULL),
135 fInitOK(other.fInitOK),
136 fMustClean(other.fMustClean),
137 fIsRemote(other.fIsRemote),
138 fDebug(other.fDebug),
139 fSpecialOutputLocation(""),
148 fFileDescriptors(new TObjArray()),
149 fCurrentDescriptor(0),
154 fExtraFiles(other.fExtraFiles),
155 fFileInfoLog(other.fFileInfoLog),
156 fAutoBranchHandling(other.fAutoBranchHandling),
159 fNcalls(other.fNcalls),
160 fMaxEntries(other.fMaxEntries),
161 fStatisticsMsg(other.fStatisticsMsg),
162 fRequestedBranches(other.fRequestedBranches),
163 fStatistics(other.fStatistics),
164 fGlobals(other.fGlobals)
167 fTasks = new TObjArray(*other.fTasks);
168 fTopTasks = new TObjArray(*other.fTopTasks);
169 fZombies = new TObjArray(*other.fZombies);
170 fContainers = new TObjArray(*other.fContainers);
171 fInputs = new TObjArray(*other.fInputs);
172 fOutputs = new TObjArray(*other.fOutputs);
173 fParamCont = new TObjArray(*other.fParamCont);
174 fgCommonFileName = "AnalysisResults.root";
175 fgAnalysisManager = this;
178 //______________________________________________________________________________
179 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
182 if (&other != this) {
183 TNamed::operator=(other);
184 fInputEventHandler = other.fInputEventHandler;
185 fOutputEventHandler = other.fOutputEventHandler;
186 fMCtruthEventHandler = other.fMCtruthEventHandler;
187 fEventPool = other.fEventPool;
190 fNSysInfo = other.fNSysInfo;
192 fInitOK = other.fInitOK;
193 fIsRemote = other.fIsRemote;
194 fDebug = other.fDebug;
195 fTasks = new TObjArray(*other.fTasks);
196 fTopTasks = new TObjArray(*other.fTopTasks);
197 fZombies = new TObjArray(*other.fZombies);
198 fContainers = new TObjArray(*other.fContainers);
199 fInputs = new TObjArray(*other.fInputs);
200 fOutputs = new TObjArray(*other.fOutputs);
201 fParamCont = new TObjArray(*other.fParamCont);
202 fDebugOptions = NULL;
203 fFileDescriptors = new TObjArray();
204 fCurrentDescriptor = 0;
206 fCommonOutput = NULL;
209 fExtraFiles = other.fExtraFiles;
210 fFileInfoLog = other.fFileInfoLog;
211 fgCommonFileName = "AnalysisResults.root";
212 fgAnalysisManager = this;
213 fAutoBranchHandling = other.fAutoBranchHandling;
214 fTable.Clear("nodelete");
215 fRunFromPath = other.fRunFromPath;
216 fNcalls = other. fNcalls;
217 fMaxEntries = other.fMaxEntries;
218 fStatisticsMsg = other.fStatisticsMsg;
219 fRequestedBranches = other.fRequestedBranches;
220 fStatistics = other.fStatistics;
221 fGlobals = new TMap();
226 //______________________________________________________________________________
227 AliAnalysisManager::~AliAnalysisManager()
230 if (fTasks) {fTasks->Delete(); delete fTasks;}
231 if (fTopTasks) delete fTopTasks;
232 if (fZombies) delete fZombies;
233 if (fContainers) {fContainers->Delete(); delete fContainers;}
234 if (fInputs) delete fInputs;
235 if (fOutputs) delete fOutputs;
236 if (fParamCont) delete fParamCont;
237 if (fDebugOptions) delete fDebugOptions;
238 if (fGridHandler) delete fGridHandler;
239 if (fInputEventHandler) delete fInputEventHandler;
240 if (fOutputEventHandler) delete fOutputEventHandler;
241 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
242 if (fEventPool) delete fEventPool;
243 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
244 if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
245 if (fFileDescriptors) {fFileDescriptors->Delete(); delete fFileDescriptors;}
248 //______________________________________________________________________________
249 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
251 // Read one entry of the tree or a whole branch.
252 fCurrentEntry = entry;
253 if (!fAutoBranchHandling)
255 if (!fTree) return -1;
256 Long64_t readbytes = fTree->GetTree()->GetEntry(entry, getall);
257 return (Int_t)readbytes;
260 //______________________________________________________________________________
261 Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
263 // Attempt to extract run number from input data path. Works only for paths to
264 // alice data in alien.
265 // sim: /alice/sim/<production>/run_no/...
266 // data: /alice/data/year/period/000run_no/... (ESD or AOD)
267 TString type = "unknown";
269 if (s.Contains("/alice/data")) type = "real";
270 else if (s.Contains("/alice/sim")) type = "simulated";
273 ind1 = s.Index("/00");
275 ind2 = s.Index("/",ind1+1);
276 if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
279 ind1 = s.Index("/LHC");
281 ind1 = s.Index("/",ind1+1);
283 ind2 = s.Index("/",ind1+1);
284 if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
288 Int_t run = srun.Atoi();
289 if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
293 //______________________________________________________________________________
294 Bool_t AliAnalysisManager::Init(TTree *tree)
296 // The Init() function is called when the selector needs to initialize
297 // a new tree or chain. Typically here the branch addresses of the tree
298 // will be set. It is normaly not necessary to make changes to the
299 // generated code, but the routine can be extended by the user if needed.
300 // Init() will be called many times when running with PROOF.
301 Bool_t init = kFALSE;
302 if (!tree) return kFALSE; // Should not happen - protected in selector caller
304 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
306 // Call InitTree of EventHandler
307 if (fOutputEventHandler) {
308 if (fMode == kProofAnalysis) {
309 init = fOutputEventHandler->Init(0x0, "proof");
311 init = fOutputEventHandler->Init(0x0, "local");
314 Error("Init", "Output event handler failed to initialize");
319 if (fInputEventHandler) {
320 if (fMode == kProofAnalysis) {
321 init = fInputEventHandler->Init(tree, "proof");
323 init = fInputEventHandler->Init(tree, "local");
326 Error("Init", "Input event handler failed to initialize tree");
330 // If no input event handler we need to get the tree once
332 if(!tree->GetTree()) {
333 Long64_t readEntry = tree->LoadTree(0);
334 if (readEntry == -2) {
335 Error("Init", "Input tree has no entry. Exiting");
341 if (fMCtruthEventHandler) {
342 if (fMode == kProofAnalysis) {
343 init = fMCtruthEventHandler->Init(0x0, "proof");
345 init = fMCtruthEventHandler->Init(0x0, "local");
348 Error("Init", "MC event handler failed to initialize");
353 if (!fInitOK) InitAnalysis();
354 if (!fInitOK) return kFALSE;
357 AliAnalysisDataContainer *top = fCommonInput;
358 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
360 Error("Init","No top input container !");
364 CheckBranches(kFALSE);
366 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
371 //______________________________________________________________________________
372 void AliAnalysisManager::SlaveBegin(TTree *tree)
374 // The SlaveBegin() function is called after the Begin() function.
375 // When running with PROOF SlaveBegin() is called on each slave server.
376 // The tree argument is deprecated (on PROOF 0 is passed).
377 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
379 // Apply debug options
382 if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
383 static Bool_t isCalled = kFALSE;
384 Bool_t init = kFALSE;
385 Bool_t initOK = kTRUE;
387 TDirectory *curdir = gDirectory;
388 // Call SlaveBegin only once in case of mixing
389 if (isCalled && fMode==kMixingAnalysis) return;
391 // Call Init of EventHandler
392 if (fOutputEventHandler) {
393 if (fMode == kProofAnalysis) {
394 // Merging AOD's in PROOF via TProofOutputFile
395 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
396 init = fOutputEventHandler->Init("proof");
397 if (!init) msg = "Failed to initialize output handler on worker";
399 init = fOutputEventHandler->Init("local");
400 if (!init) msg = "Failed to initialize output handler";
403 if (!fSelector) Error("SlaveBegin", "Selector not set");
404 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
407 if (fInputEventHandler) {
408 fInputEventHandler->SetInputTree(tree);
409 if (fMode == kProofAnalysis) {
410 init = fInputEventHandler->Init("proof");
411 if (!init) msg = "Failed to initialize input handler on worker";
413 init = fInputEventHandler->Init("local");
414 if (!init) msg = "Failed to initialize input handler";
417 if (!fSelector) Error("SlaveBegin", "Selector not set");
418 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
421 if (fMCtruthEventHandler) {
422 if (fMode == kProofAnalysis) {
423 init = fMCtruthEventHandler->Init("proof");
424 if (!init) msg = "Failed to initialize MC handler on worker";
426 init = fMCtruthEventHandler->Init("local");
427 if (!init) msg = "Failed to initialize MC handler";
430 if (!fSelector) Error("SlaveBegin", "Selector not set");
431 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
433 if (curdir) curdir->cd();
437 AliAnalysisTask *task;
438 // Call CreateOutputObjects for all tasks
439 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
440 Bool_t dirStatus = TH1::AddDirectoryStatus();
442 while ((task=(AliAnalysisTask*)next())) {
444 // Start with memory as current dir and make sure by default histograms do not get attached to files.
445 TH1::AddDirectory(kFALSE);
446 task->CreateOutputObjects();
447 if (!task->CheckPostData()) {
448 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
449 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
450 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
452 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
455 TH1::AddDirectory(dirStatus);
456 if (curdir) curdir->cd();
457 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
460 //______________________________________________________________________________
461 Bool_t AliAnalysisManager::Notify()
463 // The Notify() function is called when a new file is opened. This
464 // can be either for a new TTree in a TChain or when when a new TTree
465 // is started when using PROOF. It is normaly not necessary to make changes
466 // to the generated code, but the routine can be extended by the
467 // user if needed. The return value is currently not used.
468 if (!fTree) return kFALSE;
469 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
471 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
472 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
474 TFile *curfile = fTree->GetCurrentFile();
476 Error("Notify","No current file");
479 if (IsCollectThroughput()) {
480 if (fCurrentDescriptor) fCurrentDescriptor->Done();
481 fCurrentDescriptor = new AliAnalysisFileDescriptor(curfile);
482 fFileDescriptors->Add(fCurrentDescriptor);
485 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
486 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
487 if (run && (run != fRunFromPath)) {
489 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
492 AliAnalysisTask *task;
494 // Call Notify of the event handlers
495 if (fInputEventHandler) {
496 fInputEventHandler->Notify(curfile->GetName());
499 if (fOutputEventHandler) {
500 fOutputEventHandler->Notify(curfile->GetName());
503 if (fMCtruthEventHandler) {
504 fMCtruthEventHandler->Notify(curfile->GetName());
507 // Call Notify for all tasks
508 while ((task=(AliAnalysisTask*)next()))
511 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
515 //______________________________________________________________________________
516 Bool_t AliAnalysisManager::Process(Long64_t)
518 // The Process() function is called for each entry in the tree (or possibly
519 // keyed object in the case of PROOF) to be processed. The entry argument
520 // specifies which entry in the currently loaded tree is to be processed.
521 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
522 // to read either all or the required parts of the data. When processing
523 // keyed objects with PROOF, the object is already loaded and is available
524 // via the fObject pointer.
526 // This function should contain the "body" of the analysis. It can contain
527 // simple or elaborate selection criteria, run algorithms on the data
528 // of the event and typically fill histograms.
530 // WARNING when a selector is used with a TChain, you must use
531 // the pointer to the current TTree to call GetEntry(entry).
532 // The entry is always the local entry number in the current tree.
533 // Assuming that fChain is the pointer to the TChain being processed,
534 // use fChain->GetTree()->GetEntry(entry).
536 // This method is obsolete. ExecAnalysis is called instead.
540 //______________________________________________________________________________
541 void AliAnalysisManager::PackOutput(TList *target)
543 // Pack all output data containers in the output list. Called at SlaveTerminate
544 // stage in PROOF case for each slave.
545 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
546 if (IsCollectThroughput()) {
547 if (fCurrentDescriptor) fCurrentDescriptor->Done();
548 fFileDescriptors->Print();
549 if (fFileInfoLog.IsNull()) fFileInfoLog = "fileinfo.log";
551 out.open(fFileInfoLog, std::ios::out);
552 if (out.bad()) Error("SavePrimitive", "Bad file name: %s", fFileInfoLog.Data());
554 TIter nextflog(fFileDescriptors);
556 while ((log=nextflog())) log->SavePrimitive(out,"");
560 Error("PackOutput", "No target. Exiting.");
563 TDirectory *cdir = gDirectory;
565 if (fInputEventHandler) fInputEventHandler ->Terminate();
566 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
567 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
570 // Call FinishTaskOutput() for each event loop task (not called for
571 // post-event loop tasks - use Terminate() fo those)
572 TIter nexttask(fTasks);
573 AliAnalysisTask *task;
574 while ((task=(AliAnalysisTask*)nexttask())) {
575 if (!task->IsPostEventLoop()) {
576 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
577 task->FinishTaskOutput();
579 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
582 // Write statistics message on the workers.
583 if (fStatistics) WriteStatisticsMsg(fNcalls);
585 if (fMode == kProofAnalysis) {
586 TIter next(fOutputs);
587 AliAnalysisDataContainer *output;
588 Bool_t isManagedByHandler = kFALSE;
591 while ((output=(AliAnalysisDataContainer*)next())) {
592 // Do not consider outputs of post event loop tasks
593 isManagedByHandler = kFALSE;
594 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
595 const char *filename = output->GetFileName();
596 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
597 isManagedByHandler = kTRUE;
598 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
599 filename = fOutputEventHandler->GetOutputFileName();
601 // Check if data was posted to this container. If not, issue an error.
602 if (!output->GetData() && !isManagedByHandler) {
603 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
606 if (!output->IsSpecialOutput()) {
608 if (strlen(filename) && !isManagedByHandler) {
609 // Backup current folder
610 TDirectory *opwd = gDirectory;
611 // File resident outputs.
612 // Check first if the file exists.
613 TString openoption = "RECREATE";
614 Bool_t firsttime = kTRUE;
615 if (filestmp.FindObject(output->GetFileName())) {
618 filestmp.Add(new TNamed(output->GetFileName(),""));
620 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
621 // TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
622 // Save data to file, then close.
623 if (output->GetData()->InheritsFrom(TCollection::Class())) {
624 // If data is a collection, we set the name of the collection
625 // as the one of the container and we save as a single key.
626 TCollection *coll = (TCollection*)output->GetData();
627 coll->SetName(output->GetName());
628 // coll->Write(output->GetName(), TObject::kSingleKey);
630 if (output->GetData()->InheritsFrom(TTree::Class())) {
631 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
632 // Save data to file, then close.
633 TTree *tree = (TTree*)output->GetData();
634 // Check if tree is in memory
635 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
639 // output->GetData()->Write();
642 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
644 // printf(" file %s listing content:\n", filename);
647 // Clear file list to release object ownership to user.
650 output->SetFile(NULL);
651 // Restore current directory
652 if (opwd) opwd->cd();
654 // Memory-resident outputs
655 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
657 AliAnalysisDataWrapper *wrap = 0;
658 if (isManagedByHandler) {
659 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
660 wrap->SetName(output->GetName());
662 else wrap =output->ExportData();
663 // Output wrappers must NOT delete data after merging - the user owns them
664 wrap->SetDeleteData(kFALSE);
667 // Special outputs. The file must be opened and connected to the container.
668 TDirectory *opwd = gDirectory;
669 TFile *file = output->GetFile();
671 AliAnalysisTask *producer = output->GetProducer();
673 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
674 output->GetFileName(), output->GetName(), producer->ClassName());
677 TString outFilename = file->GetName();
678 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
679 if (isManagedByHandler) {
680 // Terminate IO for files managed by the output handler
681 // file->Write() moved to AOD handler (A.G. 11.01.10)
682 // if (file) file->Write();
683 if (file && fDebug > 2) {
684 printf(" handled file %s listing content:\n", file->GetName());
687 fOutputEventHandler->TerminateIO();
690 // Release object ownership to users after writing data to file
691 if (output->GetData()->InheritsFrom(TCollection::Class())) {
692 // If data is a collection, we set the name of the collection
693 // as the one of the container and we save as a single key.
694 TCollection *coll = (TCollection*)output->GetData();
695 coll->SetName(output->GetName());
696 coll->Write(output->GetName(), TObject::kSingleKey);
698 if (output->GetData()->InheritsFrom(TTree::Class())) {
699 TTree *tree = (TTree*)output->GetData();
700 tree->SetDirectory(file);
703 output->GetData()->Write();
707 printf(" file %s listing content:\n", output->GetFileName());
710 // Clear file list to release object ownership to user.
713 output->SetFile(NULL);
715 // Restore current directory
716 if (opwd) opwd->cd();
717 // Check if a special output location was provided or the output files have to be merged
718 if (strlen(fSpecialOutputLocation.Data())) {
719 TString remote = fSpecialOutputLocation;
721 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
722 if (remote.BeginsWith("alien:")) {
723 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
724 remote += outFilename;
725 remote.ReplaceAll(".root", Form("_%d.root", gid));
727 remote += Form("%s_%d_", gSystem->HostName(), gid);
728 remote += outFilename;
731 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
732 output->GetName(), remote.Data());
733 TFile::Cp ( outFilename.Data(), remote.Data() );
734 // Copy extra outputs
735 if (fExtraFiles.Length() && isManagedByHandler) {
736 TObjArray *arr = fExtraFiles.Tokenize(" ");
738 TIter nextfilename(arr);
739 while ((os=(TObjString*)nextfilename())) {
740 outFilename = os->GetString();
741 remote = fSpecialOutputLocation;
743 if (remote.BeginsWith("alien://")) {
744 remote += outFilename;
745 remote.ReplaceAll(".root", Form("_%d.root", gid));
747 remote += Form("%s_%d_", gSystem->HostName(), gid);
748 remote += outFilename;
751 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
752 outFilename.Data(), remote.Data());
753 TFile::Cp ( outFilename.Data(), remote.Data() );
758 // No special location specified-> use TProofOutputFile as merging utility
759 // The file at this output slot must be opened in CreateOutputObjects
760 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
765 if (cdir) cdir->cd();
766 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
769 //______________________________________________________________________________
770 void AliAnalysisManager::ImportWrappers(TList *source)
772 // Import data in output containers from wrappers coming in source.
773 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
774 TIter next(fOutputs);
775 AliAnalysisDataContainer *cont;
776 AliAnalysisDataWrapper *wrap;
778 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
779 TDirectory *cdir = gDirectory;
780 while ((cont=(AliAnalysisDataContainer*)next())) {
782 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
783 if (cont->IsRegisterDataset()) continue;
784 const char *filename = cont->GetFileName();
785 Bool_t isManagedByHandler = kFALSE;
786 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
787 isManagedByHandler = kTRUE;
788 filename = fOutputEventHandler->GetOutputFileName();
790 if (cont->IsSpecialOutput() || inGrid) {
791 if (strlen(fSpecialOutputLocation.Data())) continue;
792 // Copy merged file from PROOF scratch space.
793 // In case of grid the files are already in the current directory.
795 if (isManagedByHandler && fExtraFiles.Length()) {
796 // Copy extra registered dAOD files.
797 TObjArray *arr = fExtraFiles.Tokenize(" ");
799 TIter nextfilename(arr);
800 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
803 if (!GetFileFromWrapper(filename, source)) continue;
805 // Normally we should connect data from the copied file to the
806 // corresponding output container, but it is not obvious how to do this
807 // automatically if several objects in file...
808 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
809 if (!f) f = TFile::Open(filename, "READ");
811 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
816 // Cd to the directory pointed by the container
817 TString folder = cont->GetFolderName();
818 if (!folder.IsNull()) f->cd(folder);
819 // Try to fetch first an object having the container name.
820 obj = gDirectory->Get(cont->GetName());
822 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",
823 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
826 wrap = new AliAnalysisDataWrapper(obj);
827 wrap->SetDeleteData(kFALSE);
829 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
831 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
836 printf(" Importing data for container %s\n", cont->GetName());
837 if (strlen(filename)) printf(" -> file %s\n", filename);
840 cont->ImportData(wrap);
842 if (cdir) cdir->cd();
843 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
846 //______________________________________________________________________________
847 void AliAnalysisManager::UnpackOutput(TList *source)
849 // Called by AliAnalysisSelector::Terminate only on the client.
850 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
852 Error("UnpackOutput", "No target. Exiting.");
855 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
857 if (fMode == kProofAnalysis) ImportWrappers(source);
859 TIter next(fOutputs);
860 AliAnalysisDataContainer *output;
861 while ((output=(AliAnalysisDataContainer*)next())) {
862 if (!output->GetData()) continue;
863 // Check if there are client tasks that run post event loop
864 if (output->HasConsumers()) {
865 // Disable event loop semaphore
866 output->SetPostEventLoop(kTRUE);
867 TObjArray *list = output->GetConsumers();
868 Int_t ncons = list->GetEntriesFast();
869 for (Int_t i=0; i<ncons; i++) {
870 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
871 task->CheckNotify(kTRUE);
872 // If task is active, execute it
873 if (task->IsPostEventLoop() && task->IsActive()) {
874 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
880 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
883 //______________________________________________________________________________
884 void AliAnalysisManager::Terminate()
886 // The Terminate() function is the last function to be called during
887 // a query. It always runs on the client, it can be used to present
888 // the results graphically.
889 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
890 TDirectory *cdir = gDirectory;
892 AliAnalysisTask *task;
893 AliAnalysisDataContainer *output;
896 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
897 // Call Terminate() for tasks
899 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
900 // Save all the canvases produced by the Terminate
901 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
905 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
907 if (TObject::TestBit(kSaveCanvases)) {
908 if (!gROOT->IsBatch()) {
909 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
911 while (timer.CpuTime()<5) {
913 gSystem->ProcessEvents();
916 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
917 if (iend==0) continue;
919 for (Int_t ipict=0; ipict<iend; ipict++) {
920 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
921 if (!canvas) continue;
922 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
924 gROOT->GetListOfCanvases()->Delete();
928 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
929 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
930 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
932 TObjArray *allOutputs = new TObjArray();
934 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
935 if (!IsSkipTerminate())
936 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
937 TIter next1(allOutputs);
938 TString handlerFile = "";
939 TString extraOutputs = "";
940 if (fOutputEventHandler) {
941 handlerFile = fOutputEventHandler->GetOutputFileName();
942 extraOutputs = fOutputEventHandler->GetExtraOutputs();
946 while ((output=(AliAnalysisDataContainer*)next1())) {
947 // Special outputs or grid files have the files already closed and written.
949 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
950 if (fMode == kProofAnalysis) {
951 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
953 const char *filename = output->GetFileName();
954 TString openoption = "RECREATE";
955 if (!(strcmp(filename, "default"))) continue;
956 if (!strlen(filename)) continue;
957 if (!output->GetData()) continue;
958 TDirectory *opwd = gDirectory;
959 TFile *file = output->GetFile();
960 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
962 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
963 Bool_t firsttime = kTRUE;
964 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
967 filestmp.Add(new TNamed(filename,""));
969 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
970 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
971 file = new TFile(filename, openoption);
973 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
974 openoption = file->GetOption();
975 if (openoption == "READ") {
976 if (fDebug>1) printf("...reopening in UPDATE mode\n");
977 file->ReOpen("UPDATE");
980 if (file->IsZombie()) {
981 Error("Terminate", "Cannot open output file %s", filename);
984 output->SetFile(file);
986 // Check for a folder request
987 TString dir = output->GetFolderName();
989 if (!file->GetDirectory(dir)) file->mkdir(dir);
992 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
993 if (output->GetData()->InheritsFrom(TCollection::Class())) {
994 // If data is a collection, we set the name of the collection
995 // as the one of the container and we save as a single key.
996 TCollection *coll = (TCollection*)output->GetData();
997 coll->SetName(output->GetName());
998 coll->Write(output->GetName(), TObject::kSingleKey);
1000 if (output->GetData()->InheritsFrom(TTree::Class())) {
1001 TTree *tree = (TTree*)output->GetData();
1002 tree->SetDirectory(gDirectory);
1005 output->GetData()->Write();
1008 if (opwd) opwd->cd();
1012 TString copiedFiles;
1013 while ((output=(AliAnalysisDataContainer*)next1())) {
1014 // Close all files at output
1015 TDirectory *opwd = gDirectory;
1016 if (output->GetFile()) {
1017 // Clear file list to release object ownership to user.
1018 // output->GetFile()->Clear();
1019 output->GetFile()->Close();
1020 // Copy merged outputs in alien if requested
1021 if (fSpecialOutputLocation.BeginsWith("alien://")) {
1022 if (copiedFiles.Contains(output->GetFile()->GetName())) {
1023 if (opwd) opwd->cd();
1024 output->SetFile(NULL);
1027 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
1028 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
1029 TFile::Cp(output->GetFile()->GetName(),
1030 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
1031 copiedFiles += output->GetFile()->GetName();
1033 output->SetFile(NULL);
1035 if (opwd) opwd->cd();
1038 //Write statistics information on the client
1039 if (fStatistics) WriteStatisticsMsg(fNcalls);
1041 TDirectory *crtdir = gDirectory;
1042 TFile f("syswatch.root", "RECREATE");
1045 if (!f.IsZombie()) {
1046 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1047 tree->SetName("syswatch");
1048 tree->SetMarkerStyle(kCircle);
1049 tree->SetMarkerColor(kBlue);
1050 tree->SetMarkerSize(0.5);
1051 if (!gROOT->IsBatch()) {
1052 tree->SetAlias("event", "id0");
1053 tree->SetAlias("task", "id1");
1054 tree->SetAlias("stage", "id2");
1055 // Already defined aliases
1056 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1057 // tree->SetAlias("T","stampSec-first");
1058 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1059 // tree->SetAlias("VM","pI.fMemVirtual");
1060 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1061 Int_t npads = 1 /*COO plot for all tasks*/ +
1062 fTopTasks->GetEntries() /*Exec plot per task*/ +
1063 1 /*Terminate plot for all tasks*/ +
1066 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1067 if (npads<iopt*(iopt+1))
1068 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1070 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1072 // draw the plot of deltaVM for Exec for each task
1073 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1074 task = (AliAnalysisTask*)fTopTasks->At(itask);
1076 cut = Form("task==%d && stage==1", itask);
1077 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1078 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1080 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1081 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1084 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1086 tree->SetMarkerStyle(kFullTriangleUp);
1087 tree->SetMarkerColor(kRed);
1088 tree->SetMarkerSize(0.8);
1089 cut = "task>=0 && task<1000 && stage==0";
1090 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1091 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1093 hist->SetTitle("Memory in CreateOutputObjects()");
1094 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1095 hist->GetXaxis()->SetTitle("task");
1097 // draw the plot of deltaVM for Terminate for all tasks
1099 tree->SetMarkerStyle(kOpenSquare);
1100 tree->SetMarkerColor(kMagenta);
1101 cut = "task>=0 && task<1000 && stage==2";
1102 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1103 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1105 hist->SetTitle("Memory in Terminate()");
1106 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1107 hist->GetXaxis()->SetTitle("task");
1111 tree->SetMarkerStyle(kFullCircle);
1112 tree->SetMarkerColor(kGreen);
1113 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1114 tree->Draw("VM:event",cut,"", 1234567890, 0);
1115 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1117 hist->SetTitle("Virtual memory");
1118 hist->GetYaxis()->SetTitle("VM [MB]");
1122 tree->SetMarkerStyle(kCircle);
1123 tree->SetMarkerColor(kBlue);
1124 tree->SetMarkerSize(0.5);
1129 if (crtdir) crtdir->cd();
1131 // Validate the output files
1132 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1134 out.open("outputs_valid", ios::out);
1137 if (cdir) cdir->cd();
1138 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1140 //______________________________________________________________________________
1141 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1143 // Profiles the task having the itop index in the list of top (first level) tasks.
1144 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1146 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1149 ProfileTask(task->GetName(), option);
1152 //______________________________________________________________________________
1153 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1155 // Profile a managed task after the execution of the analysis in case NSysInfo
1157 if (gSystem->AccessPathName("syswatch.root")) {
1158 Error("ProfileTask", "No file syswatch.root found in the current directory");
1161 if (gROOT->IsBatch()) return;
1162 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1164 Error("ProfileTask", "No top task named %s known by the manager.", name);
1167 Int_t itop = fTopTasks->IndexOf(task);
1168 Int_t itask = fTasks->IndexOf(task);
1169 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1170 TDirectory *cdir = gDirectory;
1171 TFile f("syswatch.root");
1172 TTree *tree = (TTree*)f.Get("syswatch");
1174 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1177 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1178 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1179 canvas->Divide(2, 2, 0.01, 0.01);
1183 // VM profile for COO and Terminate methods
1185 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1186 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1187 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1189 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1190 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1191 hist->GetXaxis()->SetTitle("method");
1193 // CPU profile per event
1195 cut = Form("task==%d && stage==1",itop);
1196 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1197 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1199 hist->SetTitle("Execution time per event");
1200 hist->GetYaxis()->SetTitle("CPU/event [s]");
1202 // VM profile for Exec
1204 cut = Form("task==%d && stage==1",itop);
1205 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1206 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1208 hist->SetTitle("Alocated VM[MB] per event");
1209 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1214 if (cdir) cdir->cd();
1217 //______________________________________________________________________________
1218 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1220 // Adds a user task to the global list of tasks.
1222 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1226 if (fTasks->FindObject(task)) {
1227 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1230 task->SetActive(kFALSE);
1234 //______________________________________________________________________________
1235 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1237 // Retreive task by name.
1238 if (!fTasks) return NULL;
1239 return (AliAnalysisTask*)fTasks->FindObject(name);
1242 //______________________________________________________________________________
1243 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1244 TClass *datatype, EAliAnalysisContType type, const char *filename)
1246 // Create a data container of a certain type. Types can be:
1247 // kExchangeContainer = 0, used to exchange data between tasks
1248 // kInputContainer = 1, used to store input data
1249 // kOutputContainer = 2, used for writing result to a file
1250 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1251 // the output object to a folder inside the output file
1252 if (fContainers->FindObject(name)) {
1253 Error("CreateContainer","A container named %s already defined !",name);
1256 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1257 fContainers->Add(cont);
1259 case kInputContainer:
1262 case kOutputContainer:
1263 fOutputs->Add(cont);
1264 if (filename && strlen(filename)) {
1265 cont->SetFileName(filename);
1266 cont->SetDataOwned(kFALSE); // data owned by the file
1269 case kParamContainer:
1270 fParamCont->Add(cont);
1271 if (filename && strlen(filename)) {
1272 cont->SetFileName(filename);
1273 cont->SetDataOwned(kFALSE); // data owned by the file
1276 case kExchangeContainer:
1282 //______________________________________________________________________________
1283 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1284 AliAnalysisDataContainer *cont)
1286 // Connect input of an existing task to a data container.
1288 Error("ConnectInput", "Task pointer is NULL");
1291 if (!fTasks->FindObject(task)) {
1293 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1295 Bool_t connected = task->ConnectInput(islot, cont);
1299 //______________________________________________________________________________
1300 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1301 AliAnalysisDataContainer *cont)
1303 // Connect output of an existing task to a data container.
1305 Error("ConnectOutput", "Task pointer is NULL");
1308 if (!fTasks->FindObject(task)) {
1310 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1312 Bool_t connected = task->ConnectOutput(islot, cont);
1316 //______________________________________________________________________________
1317 void AliAnalysisManager::CleanContainers()
1319 // Clean data from all containers that have already finished all client tasks.
1320 TIter next(fContainers);
1321 AliAnalysisDataContainer *cont;
1322 while ((cont=(AliAnalysisDataContainer *)next())) {
1323 if (cont->IsOwnedData() &&
1324 cont->IsDataReady() &&
1325 cont->ClientsExecuted()) cont->DeleteData();
1329 //______________________________________________________________________________
1330 Bool_t AliAnalysisManager::InitAnalysis()
1332 // Initialization of analysis chain of tasks. Should be called after all tasks
1333 // and data containers are properly connected
1334 // Reset flag and remove valid_outputs file if exists
1335 if (fInitOK) return kTRUE;
1336 if (!gSystem->AccessPathName("outputs_valid"))
1337 gSystem->Unlink("outputs_valid");
1338 // Check for top tasks (depending only on input data containers)
1339 if (!fTasks->First()) {
1340 Error("InitAnalysis", "Analysis has no tasks !");
1344 AliAnalysisTask *task;
1345 AliAnalysisDataContainer *cont;
1348 Bool_t iszombie = kFALSE;
1349 Bool_t istop = kTRUE;
1351 while ((task=(AliAnalysisTask*)next())) {
1354 Int_t ninputs = task->GetNinputs();
1355 for (i=0; i<ninputs; i++) {
1356 cont = task->GetInputSlot(i)->GetContainer();
1360 fZombies->Add(task);
1364 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1365 i, task->GetName());
1367 if (iszombie) continue;
1368 // Check if cont is an input container
1369 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1370 // Connect to parent task
1374 fTopTasks->Add(task);
1378 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1381 // Check now if there are orphan tasks
1382 for (i=0; i<ntop; i++) {
1383 task = (AliAnalysisTask*)fTopTasks->At(i);
1388 while ((task=(AliAnalysisTask*)next())) {
1389 if (!task->IsUsed()) {
1391 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1394 // Check the task hierarchy (no parent task should depend on data provided
1395 // by a daughter task)
1396 for (i=0; i<ntop; i++) {
1397 task = (AliAnalysisTask*)fTopTasks->At(i);
1398 if (task->CheckCircularDeps()) {
1399 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1404 // Check that all containers feeding post-event loop tasks are in the outputs list
1405 TIter nextcont(fContainers); // loop over all containers
1406 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1407 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1408 if (cont->HasConsumers()) {
1409 // Check if one of the consumers is post event loop
1410 TIter nextconsumer(cont->GetConsumers());
1411 while ((task=(AliAnalysisTask*)nextconsumer())) {
1412 if (task->IsPostEventLoop()) {
1413 fOutputs->Add(cont);
1420 // Check if all special output containers have a file name provided
1421 TIter nextout(fOutputs);
1422 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1423 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1424 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1428 // Initialize requested branch list if needed
1429 if (!fAutoBranchHandling) {
1431 while ((task=(AliAnalysisTask*)next())) {
1432 if (!task->HasBranches()) {
1433 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\"",
1434 task->GetName(), task->ClassName());
1437 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1438 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1441 TString taskbranches;
1442 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1443 if (taskbranches.IsNull()) {
1444 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1445 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1448 AddBranches(taskbranches);
1455 //______________________________________________________________________________
1456 void AliAnalysisManager::AddBranches(const char *branches)
1458 // Add branches to the existing fRequestedBranches.
1459 TString br(branches);
1460 TObjArray *arr = br.Tokenize(",");
1463 while ((obj=next())) {
1464 if (!fRequestedBranches.Contains(obj->GetName())) {
1465 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1466 fRequestedBranches += obj->GetName();
1472 //______________________________________________________________________________
1473 void AliAnalysisManager::CheckBranches(Bool_t load)
1475 // The method checks the input branches to be loaded during the analysis.
1476 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1477 TObjArray *arr = fRequestedBranches.Tokenize(",");
1480 while ((obj=next())) {
1481 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1483 br = fTree->GetBranch(obj->GetName());
1485 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1490 if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1491 br->GetEntry(GetCurrentEntry());
1497 //______________________________________________________________________________
1498 Bool_t AliAnalysisManager::CheckTasks() const
1500 // Check consistency of tasks.
1501 Int_t ntasks = fTasks->GetEntries();
1503 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1506 // Get the pointer to AliAnalysisTaskSE::Class()
1507 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1508 // Loop all tasks to check if their corresponding library was loaded
1511 while ((obj=next())) {
1512 if (obj->IsA() == badptr) {
1513 Error("CheckTasks", "##################\n \
1514 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1521 //______________________________________________________________________________
1522 void AliAnalysisManager::PrintStatus(Option_t *option) const
1524 // Print task hierarchy.
1526 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1529 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1531 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1532 TIter next(fTopTasks);
1533 AliAnalysisTask *task;
1534 while ((task=(AliAnalysisTask*)next()))
1535 task->PrintTask(option);
1537 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1538 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1540 TString sopt(option);
1543 if (sopt.Contains("ALL"))
1545 if ( fOutputEventHandler )
1547 cout << TString('_',78) << endl;
1548 cout << "OutputEventHandler:" << endl;
1549 fOutputEventHandler->Print(" ");
1554 //______________________________________________________________________________
1555 void AliAnalysisManager::ResetAnalysis()
1557 // Reset all execution flags and clean containers.
1561 //______________________________________________________________________________
1562 void AliAnalysisManager::RunLocalInit()
1564 // Run LocalInit method for all tasks.
1565 TDirectory *cdir = gDirectory;
1566 if (IsTrainInitialized()) return;
1567 TIter nextTask(fTasks);
1568 AliAnalysisTask *task;
1569 while ((task=(AliAnalysisTask*)nextTask())) {
1573 if (cdir) cdir->cd();
1574 TObject::SetBit(kTasksInitialized, kTRUE);
1577 //______________________________________________________________________________
1578 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1580 // Start analysis having a grid handler.
1581 if (!fGridHandler) {
1582 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1583 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1587 return StartAnalysis(type, tree, nentries, firstentry);
1590 //______________________________________________________________________________
1591 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1593 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1594 // MIX. Process nentries starting from firstentry
1596 // Backup current directory and make sure gDirectory points to gROOT
1597 TDirectory *cdir = gDirectory;
1600 Error("StartAnalysis","Analysis manager was not initialized !");
1601 if (cdir) cdir->cd();
1604 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1606 printf("StartAnalysis %s\n",GetName());
1607 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1609 fMaxEntries = nentries;
1611 TString anaType = type;
1613 fMode = kLocalAnalysis;
1614 if (anaType.Contains("file")) fIsRemote = kTRUE;
1615 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1616 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1617 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1619 if (fMode == kGridAnalysis) {
1621 if (!anaType.Contains("terminate")) {
1622 if (!fGridHandler) {
1623 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1624 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1625 if (cdir) cdir->cd();
1628 // Write analysis manager in the analysis file
1629 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1630 // run local task configuration
1632 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1633 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1634 if (cdir) cdir->cd();
1638 // Terminate grid analysis
1639 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1640 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1641 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1642 if (!fGridHandler->MergeOutputs()) {
1643 // Return if outputs could not be merged or if it alien handler
1644 // was configured for offline mode or local testing.
1645 if (cdir) cdir->cd();
1649 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1650 if (cdir) cdir->cd();
1651 ImportWrappers(NULL);
1653 if (cdir) cdir->cd();
1657 SetEventLoop(kFALSE);
1658 // Enable event loop mode if a tree was provided
1659 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1662 TString ttype = "TTree";
1663 if (tree && tree->IsA() == TChain::Class()) {
1664 chain = (TChain*)tree;
1665 if (!chain || !chain->GetListOfFiles()->First()) {
1666 Error("StartAnalysis", "Cannot process null or empty chain...");
1667 if (cdir) cdir->cd();
1673 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1674 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1675 // Initialize locally all tasks (happens for all modes)
1677 AliAnalysisTask *task;
1681 case kLocalAnalysis:
1682 if (!tree && !fGridHandler) {
1683 TIter nextT(fTasks);
1684 // Call CreateOutputObjects for all tasks
1686 Bool_t dirStatus = TH1::AddDirectoryStatus();
1687 while ((task=(AliAnalysisTask*)nextT())) {
1688 TH1::AddDirectory(kFALSE);
1689 task->CreateOutputObjects();
1690 if (!task->CheckPostData()) {
1691 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1692 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1693 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1695 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1699 TH1::AddDirectory(dirStatus);
1700 if (IsExternalLoop()) {
1701 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1702 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1709 fSelector = new AliAnalysisSelector(this);
1710 // Check if a plugin handler is used
1712 // Get the chain from the plugin
1713 TString dataType = "esdTree";
1714 if (fInputEventHandler) {
1715 dataType = fInputEventHandler->GetDataType();
1719 chain = fGridHandler->GetChainForTestMode(dataType);
1721 Error("StartAnalysis", "No chain for test mode. Aborting.");
1724 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1725 retv = chain->Process(fSelector, "", nentries, firstentry);
1728 // Run tree-based analysis via AliAnalysisSelector
1729 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1730 retv = tree->Process(fSelector, "", nentries, firstentry);
1732 case kProofAnalysis:
1734 // Check if the plugin is used
1736 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1738 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1739 Error("StartAnalysis", "No PROOF!!! Exiting.");
1740 if (cdir) cdir->cd();
1743 line = Form("gProof->AddInput((TObject*)%p);", this);
1744 gROOT->ProcessLine(line);
1747 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1748 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1750 Error("StartAnalysis", "No chain!!! Exiting.");
1751 if (cdir) cdir->cd();
1757 if (!anaType.Contains("terminate")) {
1758 if (!fGridHandler) {
1759 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1760 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1761 if (cdir) cdir->cd();
1764 // Write analysis manager in the analysis file
1765 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1766 // Start the analysis via the handler
1767 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1768 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1769 if (cdir) cdir->cd();
1773 // Terminate grid analysis
1774 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1775 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1776 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1777 if (!fGridHandler->MergeOutputs()) {
1778 // Return if outputs could not be merged or if it alien handler
1779 // was configured for offline mode or local testing.
1780 if (cdir) cdir->cd();
1784 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1785 ImportWrappers(NULL);
1787 if (cdir) cdir->cd();
1789 case kMixingAnalysis:
1790 // Run event mixing analysis
1792 Error("StartAnalysis", "Cannot run event mixing without event pool");
1793 if (cdir) cdir->cd();
1796 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1797 fSelector = new AliAnalysisSelector(this);
1798 while ((chain=fEventPool->GetNextChain())) {
1800 // Call NotifyBinChange for all tasks
1801 while ((task=(AliAnalysisTask*)next()))
1802 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1803 retv = chain->Process(fSelector);
1805 Error("StartAnalysis", "Mixing analysis failed");
1806 if (cdir) cdir->cd();
1810 PackOutput(fSelector->GetOutputList());
1813 if (cdir) cdir->cd();
1817 //______________________________________________________________________________
1818 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1820 // Start analysis for this manager on a given dataset. Analysis task can be:
1821 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1823 Error("StartAnalysis","Analysis manager was not initialized !");
1827 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1828 TString anaType = type;
1830 if (!anaType.Contains("proof")) {
1831 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1834 fMode = kProofAnalysis;
1836 SetEventLoop(kTRUE);
1837 // Set the dataset flag
1838 TObject::SetBit(kUseDataSet);
1841 // Start proof analysis using the grid handler
1842 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1843 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1846 // Check if the plugin is in test mode
1847 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1848 dataset = "test_collection";
1850 dataset = fGridHandler->GetProofDataSet();
1854 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1855 Error("StartAnalysis", "No PROOF!!! Exiting.");
1859 // Initialize locally all tasks
1862 line = Form("gProof->AddInput((TObject*)%p);", this);
1863 gROOT->ProcessLine(line);
1865 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1866 dataset, nentries, firstentry);
1867 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1868 retv = (Long_t)gROOT->ProcessLine(line);
1872 //______________________________________________________________________________
1873 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1875 // Opens according the option the file specified by cont->GetFileName() and changes
1876 // current directory to cont->GetFolderName(). If the file was already opened, it
1877 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1878 // be optionally ignored.
1879 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1880 TString filename = cont->GetFileName();
1882 if (filename.IsNull()) {
1883 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1886 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1888 f = mgr->OpenProofFile(cont,option);
1890 // Check first if the file is already opened
1891 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1893 // Check if option "UPDATE" was preserved
1894 TString opt(option);
1896 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1897 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1899 f = TFile::Open(filename, option);
1902 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1906 // Check for a folder request
1907 TString dir = cont->GetFolderName();
1908 if (!dir.IsNull()) {
1909 if (!f->GetDirectory(dir)) f->mkdir(dir);
1914 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1915 cont->SetFile(NULL);
1919 //______________________________________________________________________________
1920 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1922 // Opens a special output file used in PROOF.
1924 TString filename = cont->GetFileName();
1925 if (cont == fCommonOutput) {
1926 if (fOutputEventHandler) {
1927 if (strlen(extaod)) filename = extaod;
1928 filename = fOutputEventHandler->GetOutputFileName();
1930 else Fatal("OpenProofFile","No output container. Exiting.");
1933 if (fMode!=kProofAnalysis || !fSelector) {
1934 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1937 if (fSpecialOutputLocation.Length()) {
1938 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1940 // Check if option "UPDATE" was preserved
1941 TString opt(option);
1943 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1944 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1946 f = new TFile(filename, option);
1948 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1952 // Check for a folder request
1953 TString dir = cont->GetFolderName();
1955 if (!f->GetDirectory(dir)) f->mkdir(dir);
1960 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1961 cont->SetFile(NULL);
1964 // Check if there is already a proof output file in the output list
1965 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1967 // Get the actual file
1968 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1969 filename = (const char*)gROOT->ProcessLine(line);
1971 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1973 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1975 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1978 // Check if option "UPDATE" was preserved
1979 TString opt(option);
1981 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1982 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1984 if (cont->IsRegisterDataset()) {
1985 TString dsetName = filename;
1986 dsetName.ReplaceAll(".root", cont->GetTitle());
1987 dsetName.ReplaceAll(":","_");
1988 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1989 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1991 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1992 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1994 if (fDebug > 1) printf("=== %s\n", line.Data());
1995 gROOT->ProcessLine(line);
1996 line = Form("pf->OpenFile(\"%s\");", option);
1997 gROOT->ProcessLine(line);
2000 gROOT->ProcessLine("pf->Print()");
2001 printf(" == proof file name: %s", f->GetName());
2003 // Add to proof output list
2004 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2005 if (fDebug > 1) printf("=== %s\n", line.Data());
2006 gROOT->ProcessLine(line);
2008 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2012 // Check for a folder request
2013 TString dir = cont->GetFolderName();
2014 if (!dir.IsNull()) {
2015 if (!f->GetDirectory(dir)) f->mkdir(dir);
2020 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2021 cont->SetFile(NULL);
2025 //______________________________________________________________________________
2026 void AliAnalysisManager::ExecAnalysis(Option_t *option)
2028 // Execute analysis.
2029 static Long64_t nentries = 0;
2030 static TTree *lastTree = 0;
2031 static TStopwatch *timer = new TStopwatch();
2032 // Only the first call to Process will trigger a true Notify. Other Notify
2033 // coming before is ignored.
2034 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2035 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2038 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2040 if (fTree && (fTree != lastTree)) {
2041 nentries += fTree->GetEntries();
2044 if (!fNcalls) timer->Start();
2045 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2048 TDirectory *cdir = gDirectory;
2049 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2050 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2052 Error("ExecAnalysis", "Analysis manager was not initialized !");
2053 if (cdir) cdir->cd();
2057 AliAnalysisTask *task;
2058 // Check if the top tree is active.
2060 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2061 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2063 // De-activate all tasks
2064 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2065 AliAnalysisDataContainer *cont = fCommonInput;
2066 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2068 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2069 if (cdir) cdir->cd();
2072 cont->SetData(fTree); // This will notify all consumers
2073 Long64_t entry = fTree->GetTree()->GetReadEntry();
2075 // Call BeginEvent() for optional input/output and MC services
2076 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2077 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2078 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2080 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2081 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2083 // Execute the tasks
2084 // TIter next1(cont->GetConsumers());
2085 TIter next1(fTopTasks);
2087 while ((task=(AliAnalysisTask*)next1())) {
2089 cout << " Executing task " << task->GetName() << endl;
2091 task->ExecuteTask(option);
2093 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2094 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2098 // Call FinishEvent() for optional output and MC services
2099 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2100 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2101 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2102 // Gather system information if requested
2103 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2104 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2105 if (cdir) cdir->cd();
2108 // The event loop is not controlled by TSelector
2110 // Call BeginEvent() for optional input/output and MC services
2111 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2112 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2113 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2115 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2116 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2117 TIter next2(fTopTasks);
2118 while ((task=(AliAnalysisTask*)next2())) {
2119 task->SetActive(kTRUE);
2121 cout << " Executing task " << task->GetName() << endl;
2123 task->ExecuteTask(option);
2127 // Call FinishEvent() for optional output and MC services
2128 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2129 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2130 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2131 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2132 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2133 if (cdir) cdir->cd();
2136 //______________________________________________________________________________
2137 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2139 // Check if the stdout is connected to a pipe (C.Holm)
2140 Bool_t ispipe = kFALSE;
2141 out.seekp(0, std::ios_base::cur);
2144 if (errno == ESPIPE) ispipe = kTRUE;
2149 //______________________________________________________________________________
2150 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2152 // Set the input event handler and create a container for it.
2153 fInputEventHandler = handler;
2154 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2157 //______________________________________________________________________________
2158 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2160 // Set the input event handler and create a container for it.
2161 fOutputEventHandler = handler;
2162 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2163 fCommonOutput->SetSpecialOutput();
2166 //______________________________________________________________________________
2167 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2169 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2170 if (TObject::TestBit(kUseProgressBar)) {
2171 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2177 //______________________________________________________________________________
2178 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2180 // Enable a text mode progress bar. Resets debug level to 0.
2181 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2182 TObject::SetBit(kUseProgressBar,flag);
2183 fPBUpdateFreq = freq;
2187 //______________________________________________________________________________
2188 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2190 // This method is used externally to register output files which are not
2191 // connected to any output container, so that the manager can properly register,
2192 // retrieve or merge them when running in distributed mode. The file names are
2193 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2194 if (fExtraFiles.Contains(fname)) return;
2195 if (fExtraFiles.Length()) fExtraFiles += " ";
2196 fExtraFiles += fname;
2199 //______________________________________________________________________________
2200 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2202 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2206 TObject *pof = source->FindObject(filename);
2207 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2208 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2211 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2212 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2213 TString clientUrl(chUrl);
2214 TString fullPath_str(fullPath);
2215 if (clientUrl.Contains("localhost")){
2216 TObjArray* array = fullPath_str.Tokenize ( "//" );
2217 TObjString *strobj = ( TObjString *)array->At(1);
2218 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2219 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2220 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2221 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2222 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2226 else if (clientUrl.Contains("__lite__")) {
2227 // Special case for ProofLite environement - get file info and copy.
2228 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2229 fullPath_str = Form("%s/%s", tmp, fullPath);
2232 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2233 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2235 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2239 //______________________________________________________________________________
2240 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2242 // Fill analysis type in the provided string.
2244 case kLocalAnalysis:
2247 case kProofAnalysis:
2253 case kMixingAnalysis:
2258 //______________________________________________________________________________
2259 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2261 // Validate all output files.
2262 TIter next(fOutputs);
2263 AliAnalysisDataContainer *output;
2264 TDirectory *cdir = gDirectory;
2265 TString openedFiles;
2266 while ((output=(AliAnalysisDataContainer*)next())) {
2267 if (output->IsRegisterDataset()) continue;
2268 TString filename = output->GetFileName();
2269 if (filename == "default") {
2270 if (!fOutputEventHandler) continue;
2271 filename = fOutputEventHandler->GetOutputFileName();
2272 // Main AOD may not be there
2273 if (gSystem->AccessPathName(filename)) continue;
2275 // Check if the file is closed
2276 if (openedFiles.Contains(filename)) continue;;
2277 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2279 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2280 // Clear file list to release object ownership to user.
2284 file = TFile::Open(filename);
2285 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2286 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2287 if (cdir) cdir->cd();
2291 openedFiles += filename;
2294 if (cdir) cdir->cd();
2298 //______________________________________________________________________________
2299 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2301 // Implements a nice text mode progress bar.
2302 static Long64_t icount = 0;
2303 static TString oname;
2304 static TString nname;
2305 static Long64_t ocurrent = 0;
2306 static Long64_t osize = 0;
2307 static Int_t oseconds = 0;
2308 static TStopwatch *owatch = 0;
2309 static Bool_t oneoftwo = kFALSE;
2310 static Int_t nrefresh = 0;
2311 static Int_t nchecks = 0;
2312 static char lastChar = 0;
2313 const char symbol[4] = {'-','\\','|','/'};
2315 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2321 ocurrent = TMath::Abs(current);
2322 osize = TMath::Abs(size);
2323 if (ocurrent > osize) ocurrent=osize;
2328 if ((current % fPBUpdateFreq) != 0) return;
2330 char progress[11] = " ";
2331 Int_t ichar = icount%4;
2336 if (owatch && !last) {
2338 time = owatch->RealTime();
2339 seconds = int(time) % 60;
2340 minutes = (int(time) / 60) % 60;
2341 hours = (int(time) / 60 / 60);
2343 if (oseconds==seconds) {
2347 oneoftwo = !oneoftwo;
2351 if (refresh && oneoftwo) {
2353 if (nchecks <= 0) nchecks = nrefresh+1;
2354 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2355 oname = Form(" == %d%% ==", pctdone);
2357 Double_t percent = 100.0*ocurrent/osize;
2358 Int_t nchar = Int_t(percent/10);
2359 if (nchar>10) nchar=10;
2361 for (i=0; i<nchar; i++) progress[i] = '=';
2362 progress[nchar] = symbol[ichar];
2363 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2364 progress[10] = '\0';
2367 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2368 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2369 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2371 Int_t full = Int_t(ocurrent > 0 ?
2372 time * (float(osize)/ocurrent) + .5 :
2374 Int_t remain = Int_t(full - time);
2375 Int_t rsec = remain % 60;
2376 Int_t rmin = (remain / 60) % 60;
2377 Int_t rhour = (remain / 60 / 60);
2378 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2379 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2381 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2382 if (refresh && oneoftwo) oname = nname;
2383 if (owatch) owatch->Continue();
2392 fprintf(stderr, "\n");
2396 //______________________________________________________________________________
2397 void AliAnalysisManager::DoLoadBranch(const char *name)
2399 // Get tree and load branch if needed.
2400 static Long64_t crtEntry = -100;
2402 if (fAutoBranchHandling || !fTree)
2405 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2407 br = fTree->GetBranch(name);
2409 Error("DoLoadBranch", "Could not find branch %s",name);
2414 if (br->GetReadEntry()==fCurrentEntry) return;
2415 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2417 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2418 if (crtEntry != fCurrentEntry) {
2419 CountEvent(1,0,1,0);
2420 crtEntry = fCurrentEntry;
2423 if (crtEntry != fCurrentEntry) {
2424 CountEvent(1,1,0,0);
2425 crtEntry = fCurrentEntry;
2430 //______________________________________________________________________________
2431 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2433 // Add the statistics task to the manager.
2435 Info("AddStatisticsTask", "Already added");
2438 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2439 gROOT->ProcessLine(line);
2442 //______________________________________________________________________________
2443 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2445 // Bookkeep current event;
2446 if (!fStatistics) return;
2447 fStatistics->AddInput(ninput);
2448 fStatistics->AddProcessed(nprocessed);
2449 fStatistics->AddFailed(nfailed);
2450 fStatistics->AddAccepted(naccepted);
2453 //______________________________________________________________________________
2454 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2456 // Add a line in the statistics message. If available, the statistics message is written
2457 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2459 if (!strlen(line)) return;
2460 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2461 fStatisticsMsg += line;
2464 //______________________________________________________________________________
2465 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2467 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2468 static Bool_t done = kFALSE;
2471 if (!fStatistics) return;
2473 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2474 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2475 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2476 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2477 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2478 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2479 fStatistics->GetNaccepted()), ios::out);
2480 out << fStatisticsMsg << endl;
2484 //______________________________________________________________________________
2485 const char* AliAnalysisManager::GetOADBPath()
2487 // returns the path of the OADB
2488 // this static function just depends on environment variables
2490 static TString oadbPath;
2492 if (gSystem->Getenv("OADB_PATH"))
2493 oadbPath = gSystem->Getenv("OADB_PATH");
2494 else if (gSystem->Getenv("ALICE_ROOT"))
2495 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2497 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2502 //______________________________________________________________________________
2503 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2505 // Define a custom string variable mapped to a global unique name. The variable
2506 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2507 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2509 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2512 Bool_t valid = kFALSE;
2513 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2515 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2518 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2521 //______________________________________________________________________________
2522 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2524 // Static method to retrieve a global variable defined via SetGlobalStr.
2526 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2528 TObject *value = mgr->GetGlobals()->GetValue(key);
2529 if (!value) return 0;
2531 return value->GetName();
2534 //______________________________________________________________________________
2535 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2537 // Define a custom integer variable mapped to a global unique name. The variable
2538 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2539 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2541 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2544 Bool_t valid = kFALSE;
2545 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2547 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2550 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2553 //______________________________________________________________________________
2554 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2556 // Static method to retrieve a global variable defined via SetGlobalInt.
2558 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2560 TObject *value = mgr->GetGlobals()->GetValue(key);
2561 if (!value) return 0;
2563 TString s = value->GetName();
2567 //______________________________________________________________________________
2568 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2570 // Define a custom double precision variable mapped to a global unique name. The variable
2571 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2572 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2574 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2577 Bool_t valid = kFALSE;
2578 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2580 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2583 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2586 //______________________________________________________________________________
2587 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2589 // Static method to retrieve a global variable defined via SetGlobalDbl.
2591 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2593 TObject *value = mgr->GetGlobals()->GetValue(key);
2594 if (!value) return 0;
2596 TString s = value->GetName();
2600 //______________________________________________________________________________
2601 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2603 // Sets Class debug level
2605 if (!fDebugOptions) {
2606 fDebugOptions = new TObjArray();
2607 fDebugOptions->SetOwner(kTRUE);
2610 // substracting DebugOffset, beacuse of AliLog::SetClassDebugLevel()
2611 debugLevel -= AliLog::kDebug-1;
2613 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2615 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel+AliLog::kDebug-1,className).Data());
2616 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2618 TString oldDebugStr = debugOpt->GetTitle();
2619 Int_t oldDebug = oldDebugStr.Atoi();
2620 if (debugLevel > oldDebug) {
2621 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel+AliLog::kDebug-1,className,oldDebug+AliLog::kDebug-1).Data());
2622 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2624 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel+AliLog::kDebug-1,className,oldDebug+AliLog::kDebug-1).Data());
2629 //______________________________________________________________________________
2630 void AliAnalysisManager::ApplyDebugOptions()
2632 // Apply debug options
2634 if (!fDebugOptions) return;
2636 TIter next(fDebugOptions);
2639 while ((debug=dynamic_cast<TNamed*>(next()))) {
2640 debugLevel = debug->GetTitle();
2641 AliInfo(TString::Format("ApplyDebugOptions : Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()+AliLog::kDebug-1).Data());
2642 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());