2 * @file TupleSelector.C
3 * @author Christian Holm Christensen <cholm@nbi.dk>
4 * @date Thu Nov 13 14:12:11 2014
6 * @brief A selector to draw stuff from the a track tuple as made by
9 * This class assumes that the files with the TTree's created by
10 * AliFMDMCTrackELoss lives in tuple/forward_tuple_N.root.
12 * The trees are made by AliFMDMCTrackELoss, which in turn is embedded
13 * in a AliFMDMCTrackInspector object. This code, which also does
14 * fits of the MC 'true' energy loss spectra is contained in the task
15 * AliFMDMCTrackInspectorTask. This task can be executed via the
16 * train MakeFMDMCTrackTrain.C
18 * To run this selector do
22 Run(Bool_t proof=true, Long64_t maxEvents=-1)
24 const char* fwd = "${ALICE_ROOT}/PWGLF/FORWARD/analysis2";
25 gSystem->AddIncludePath("-I${ALICE_ROOT}/include");
26 gROOT->Macro(Form("%s/scripts/LoadLibs.C"));
27 gROOT->LoadMacro(Form("%s/TupleSelector.C++g",fwd));
29 if (proof) TupleSelector::Proof(maxEvents);
30 else TupleSelector::Run(maxEvents);
34 * Here, $ANA_SRC is assumed to point to the source directory of
35 * PWGLF/FORWARD/analysis2
41 #include <TSelector.h>
48 # include <TLegendEntry.h>
53 # include <TClonesArray.h>
56 # include <TOutputListSelectorDataMap.h>
60 # include <TDirectory.h>
61 # include <TSystemDirectory.h>
64 # include <TFileCollection.h>
65 # include <THashList.h>
67 # include <TQConnection.h>
70 # include <TStopwatch.h>
71 # include "AliFMDMCTrackELoss.h"
73 // Forward declarations of types in the interface, and to trigger
74 // autoloading of some libraries
84 class TSystemDirectory;
88 class AliFMDMCTrackELoss;
89 class AliFMDMCTrackELoss::Hit;
92 //====================================================================
94 * Container of primary/secondary histograms
96 struct Spectra : public TObject
108 : TObject(), fName(""), fPrimary(0), fSecondary(0)
116 * @param bins Bin definition
118 Spectra(const char* name,
127 fPrimary = new TH1D(Form("primary%s", name),
128 title, bins.GetSize()-1,
130 fPrimary->SetXTitle("#beta#gamma");
131 fPrimary->SetMarkerColor(color);
132 fPrimary->SetLineColor(color);
133 fPrimary->SetMarkerStyle(20);
134 fPrimary->SetFillStyle(0);
135 fPrimary->SetDirectory(0);
138 fSecondary = static_cast<TH1*>(fPrimary->Clone(Form("secondary%s",name)));
139 fSecondary->SetMarkerStyle(24);
140 fSecondary->SetMarkerSize(1.2);
141 fSecondary->SetDirectory(0);
146 * @param o Object to copy from
148 Spectra(const Spectra& o)
155 fPrimary = static_cast<TH1*>(o.fPrimary->Clone());
157 fSecondary = static_cast<TH1*>(o.fSecondary->Clone());
164 if (fPrimary) delete fPrimary;
165 if (fSecondary) delete fSecondary;
170 * @param o Object to assign from
172 * @return Reference to this
174 Spectra& operator=(const Spectra& o)
176 if (&o == this) return *this;
178 TObject::operator=(o);
180 if (fPrimary) { delete fPrimary; fPrimary = 0; }
181 if (fSecondary) { delete fSecondary; fSecondary = 0; }
183 fPrimary = static_cast<TH1*>(o.fPrimary->Clone());
185 fSecondary = static_cast<TH1*>(o.fSecondary->Clone());
194 const char* GetName() const { return fName.Data(); }
196 * Fill into histogram
198 * @param primary true if for primary
199 * @param x What to fill
201 void Fill(Bool_t primary, Double_t x)
203 if (primary) fPrimary->Fill(x);
204 else fSecondary->Fill(x);
209 * @param primary If true, get histogram for primaries, otherwise
212 * @return Pointer to histogram (possibly null)
214 TH1* Hist(Bool_t primary) const
216 return (primary ? fPrimary : fSecondary);
219 * Add the histograms to a stack and legend
221 * @param stack Stack to add to
224 virtual void Stack(THStack* stack, TLegend* leg)
226 TH1* hists[] = { fPrimary, fSecondary, 0 };
227 for (Int_t i = 0; i < 2; i++) {
228 if (!hists[i]) continue;
230 Int_t n = hists[i]->GetEntries();
231 if (n <= 0) continue;
234 hists[i]->Scale(1. / n, "width");
235 stack->Add(hists[i]);
237 if (i != 0) continue;
240 leg->AddEntry(hists[i], hists[i]->GetTitle(), "p");
243 TLegendEntry* e = leg->AddEntry("",
244 (i == 0 ? "Primary" : "Secondary"),
246 e->SetMarkerStyle(hists[i]->GetMarkerStyle());
247 e->SetFillStyle(hists[i]->GetFillStyle());
248 e->SetFillColor(kBlack);
253 * Merge this object with similar objects in the list.
255 * @param list list of objects
257 * @return Number of merged objects
259 Long64_t Merge(TCollection *list)
264 while ((obj = nxt())) {
265 if (!obj->IsA()->InheritsFrom(this->IsA())) {
266 Warning("Merge", "Will not merge a Spectra with a %s",
267 obj->IsA()->GetName());
270 Spectra* oth = static_cast<Spectra*>(obj);
273 // Info("Merge", "%s merged %lld entries", fName.Data(), cnt);
276 Bool_t Add(const Spectra* oth)
278 if (!oth->fName.EqualTo(fName)) {
279 Warning("Merge", "Will not merge %s with %s",
280 oth->fName.Data(), fName.Data());
283 // Int_t nPrmOld = fPrimary->GetEntries();
284 // Int_t nSecOld = fPrimary->GetEntries();
286 fPrimary ->Add(oth->fPrimary);
287 fSecondary->Add(oth->fSecondary);
289 // Int_t nPrmNow = fPrimary->GetEntries();
290 // Int_t nSecNow = fPrimary->GetEntries();
292 // Info("Add", "%s: %d/%d merged to %d/%d",
293 // fName.Data(), nPrmOld, nSecOld, nPrmNow, nSecNow);
299 * @param option Not used
301 void ls(Option_t* option="") const
304 gROOT->IncreaseDirLevel();
305 TH1* hists[] = { fPrimary,
308 for (Int_t i = 0; i < 2; i++) if (hists[i]) hists[i]->ls();
309 gROOT->DecreaseDirLevel();
314 * @param dir Parent directory
316 void Store(TDirectory* dir)
318 TDirectory* out = dir->mkdir(fName);
320 fPrimary->Clone("primary")->Write();
321 fSecondary->Clone("secondary")->Write();
326 //====================================================================
328 * Container to type histograms
330 struct Type : public Spectra
335 Type() : Spectra() {}
343 Type(const char* name,
346 : Spectra() // Do not use the base class ctor
349 fPrimary = new TH1D(Form("primary%s", name),
351 fPrimary->SetXTitle("particle type");
352 fPrimary->SetMarkerColor(color);
353 fPrimary->SetMarkerStyle(20);
354 fPrimary->SetFillColor(color);
355 fPrimary->SetFillStyle(3001);
356 fPrimary->SetLineColor(color);
357 fPrimary->SetDirectory(0);
359 fPrimary->GetXaxis()->SetBinLabel(1, "e^{#pm}");
360 fPrimary->GetXaxis()->SetBinLabel(2, "#pi^{#pm}");
361 fPrimary->GetXaxis()->SetBinLabel(3, "K^{#pm}");
362 fPrimary->GetXaxis()->SetBinLabel(4, "p/#bar{p}");
363 fPrimary->GetXaxis()->SetBinLabel(5, "strange");
364 fPrimary->GetXaxis()->SetBinLabel(6, "other");
367 static_cast<TH1*>(fPrimary->Clone(Form("secondary%s",name)));
368 fSecondary->SetMarkerStyle(24);
369 fSecondary->SetMarkerSize(1.2);
370 fSecondary->SetFillStyle(3002);
371 fSecondary->SetDirectory(0);
376 //====================================================================
377 struct Ring : public TObject
380 /** Detector number */
382 /** Ring identifier */
386 /** Collection of spectra */
389 /** Enumeration of our spectra */
414 Ring(UShort_t d, Char_t r)
417 fName(Form("FMD%d%c", d, r)),
420 Color_t color = AliForwardUtil::RingColor(fD, fR);
421 TArrayD bgArray(601);
422 AliForwardUtil::MakeLogScale(300, -2, 5, bgArray);
424 fSpectra = new TObjArray(kNSpectra);
425 fSpectra->SetOwner(true);
426 fSpectra->AddAt(new Spectra("BetaGamma", fName, color, bgArray),
428 fSpectra->AddAt(new Spectra("BetaGammaPi", fName, color, bgArray),
430 fSpectra->AddAt(new Spectra("BetaGammaElectron", fName, color, bgArray),
432 fSpectra->AddAt(new Type("Type", fName, color), kTypes);
438 * @param r Other to copy from
447 if (r.fSpectra) fSpectra = new TObjArray(*r.fSpectra);
450 * Assignment operator
452 * @param r Other to assign from
454 * @return Reference to this obect
456 Ring& operator=(const Ring& r)
458 if (&r == this) return *this;
463 if (fSpectra) { delete fSpectra; fSpectra = 0; }
464 if (r.fSpectra) fSpectra = new TObjArray(*r.fSpectra);
468 const char* GetName() const { return fName.Data(); }
472 * @param which Identifier
474 * @return Pointer to Spectra object or null
476 Spectra* Get(UInt_t which)
478 if (!fSpectra) return 0;
480 if (i > fSpectra->GetEntriesFast()) return 0;
481 return static_cast<Spectra*>(fSpectra->At(i));
486 * @param which Identifier
488 * @return Pointer to Spectra object or null
490 const Spectra* Get(UInt_t which) const
492 if (!fSpectra) return 0;
494 if (i > fSpectra->GetEntriesFast()) return 0;
495 return static_cast<Spectra*>(fSpectra->At(i));
500 * @param hit Hit structure
502 void Fill(AliFMDMCTrackELoss::Hit* hit)
504 Bool_t prim = hit->IsPrimary();
505 Int_t apdg = hit->AbsPdg();
506 Int_t mfl = Int_t(apdg/TMath::Power(10,Int_t(TMath::Log10(apdg))));
507 Int_t type = (hit->IsElectron() ? 1 :
510 hit->IsProton() ? 4 :
513 Get(kBetaGamma) ->Fill(prim, hit->BetaGamma());
514 Get(kTypes) ->Fill(prim, type);
515 if (hit->IsPion() || hit->IsProton() || hit->IsKaon() || apdg > 100)
516 Get(kBetaGammaPi) ->Fill(prim, hit->BetaGamma());
517 if (hit->IsElectron())
518 Get(kBetaGammaElectron)->Fill(prim, hit->BetaGamma());
524 * @param primary If true, for primaries
525 * @param which Which histogram to get
527 * @return Histogram or null
529 TH1* Hist(Bool_t primary, UShort_t which) const
531 const Spectra* spe = Get(which);
533 return spe->Hist(primary);
536 * Merge this object with similar objects in the list.
538 * @param list list of objects
540 * @return Number of merged objects
542 Long64_t Merge(TCollection *list)
547 while ((obj = nxt())) {
548 if (!obj->IsA()->InheritsFrom(this->IsA())) {
549 Warning("Merge", "Will not merge a Ring with a %s",
550 obj->IsA()->GetName());
553 Ring* oth = static_cast<Ring*>(obj);
554 if (oth->fD != fD || oth->fR != fR) {
555 Warning("Merge", "Will not merge FMD%d%c with FMD%d%c",
556 fD, fR, oth->fD, oth->fR);
561 // fSpectra->Merge(oth->fSpectra);
562 TIter thsNext(fSpectra);
563 TIter othNext(oth->fSpectra);
564 Spectra* thsSpec = 0;
565 Spectra* othSpec = 0;
567 while ((thsSpec = static_cast<Spectra*>(thsNext())) &&
568 (othSpec = static_cast<Spectra*>(othNext())))
569 thsSpec->Add(othSpec);
574 // Info("Merge", "FMD%d%c merged %lld entries", fD, fR, cnt);
577 void Draw(Option_t* opt="")
579 Info("Draw", "Should draw rings here");
585 * @param option Not used
587 void ls(Option_t* option="") const
590 gROOT->IncreaseDirLevel();
591 if (fSpectra) fSpectra->ls(option);
592 gROOT->DecreaseDirLevel();
597 * @param dir Parent directory
599 void Store(TDirectory* dir)
601 TDirectory* out = dir->mkdir(fName);
603 TIter next(fSpectra);
605 while ((spec = static_cast<Spectra*>(next())))
613 //====================================================================
614 struct Monitor : public TObject, public TQObject
620 fName = gProof->GetSessionTag();
621 gDirectory->Add(this);
622 // _must_ specify signal _exactly_ like below, or we won't be called
623 Bool_t ret = gProof->Connect("Feedback(TList *objs)", "Monitor", this,
624 "Feedback(TList *objs)");
626 Warning("Monitor", "Failed to connect to Proof");
631 gProof->Disconnect("Feedback(TList *objs)",this,
632 "Feedback(TList* objs)");
634 void SetName(const char* name) { fName = name; }
635 const char* GetName() const { return fName.Data(); }
636 void Feedback(TList* objs)
638 Info("Feedback", "Got a list of objects (%p)", objs);
647 //====================================================================
648 struct TupleSelector : public TSelector
650 TString fTitle; //! Must not be persistent
651 TTree* fTree; //! Must not be persistent
652 TClonesArray* fHits; //! Must not be persistent
653 Int_t fI; //! Not persistent
654 TObjArray* fRings; //! Not persistent
659 * @param name Optional title
661 TupleSelector(const char* name="") :
662 fTitle(name), fTree(0), fHits(0), fI(0), fRings(0)
665 fTitle = gSystem->BaseName(gSystem->WorkingDirectory());
666 // SetOption("fb=rings");
669 const char* GetName() const { return fTitle.Data(); }
675 * Get index for a particular ring
680 * @return Index, or 0xFFFF
682 UShort_t Index(UShort_t d, Char_t r) const
684 Bool_t inner = (r == 'i' || r == 'I');
687 case 2: return (inner ? 1 : 2);
688 case 3: return (inner ? 4 : 3);
690 ::Warning("", "Unknown ring FMD%d%c", d, r);
693 void Init(TTree* tree)
695 Info("Init", "Got a tree: %p", tree);
698 Warning("Init", "No tree passed");
703 fHits = new TClonesArray("AliFMDMCTrackELoss::Hit");
704 fTree->SetBranchAddress("hits", &fHits);
706 void Begin(TTree* tree)
708 Info("Begin", "Called w/tree @ %p", tree);
709 // if (tree) SlaveBegin(tree);
715 * @param tree Tree to process
717 void SlaveBegin(TTree* tree)
719 Info("SlaveBegin", "Got a tree: %p", tree);
720 fRings = new TObjArray(5);
721 fRings->SetName("rings");
722 fRings->SetOwner(true);
723 fRings->AddAt(new Ring(1,'I'), Index(1,'I'));
724 fRings->AddAt(new Ring(2,'I'), Index(2,'I'));
725 fRings->AddAt(new Ring(2,'O'), Index(2,'O'));
726 fRings->AddAt(new Ring(3,'O'), Index(3,'O'));
727 fRings->AddAt(new Ring(3,'I'), Index(3,'I'));
729 fOutput->Add(fRings);
731 // In case of local mode, we get the tree here,
732 // and init isn't called
740 * @name Event processing
744 TFile* file = (fTree ? fTree->GetCurrentFile() : 0);
745 Info("Notify","processing file: %p (%s)",
746 file, (file ? file->GetName() : "nil"));
754 * @return true on success
756 Bool_t Process(Long64_t entry)
759 Warning("Process", "No tree");
762 if (!fTree->GetTree()) {
763 Warning("Process", "No real tree");
767 fTree->GetTree()->GetEntry(entry);
769 // if (fI % 100 == 0) {
770 // printf("Event # %6d (%6d hits)\r", fI, fHits->GetEntries());
773 // Printf("Event # %7d, %6d hits", fI, fHits->GetEntries());
776 AliFMDMCTrackELoss::Hit* hit = 0;
777 while ((hit = static_cast<AliFMDMCTrackELoss::Hit*>(next())))
787 * @return Pointer to ring object or null
789 Ring* Get(UShort_t d, Char_t r)
791 return static_cast<Ring*>(fRings->At(Index(d,r)));
799 * @return Pointer to constant ring object or null
801 const Ring* Get(UShort_t d, Char_t r) const
803 return static_cast<Ring*>(fRings->At(Index(d,r)));
806 * Fill in to a ring object
808 * @param hit Hit information
810 void Fill(AliFMDMCTrackELoss::Hit* hit)
812 Ring* r = Get(hit->D(), hit->R());
819 * @name Final processing
821 void SlaveTerminate()
830 Printf("\nDone (rings=%p)", fRings);
833 fRings = static_cast<TObjArray*>(fOutput->FindObject("rings"));
835 Error("Terminate", "No rings in output array");
840 TFile* out = TFile::Open("tuple_summary.root", "RECREATE");
843 PlotOne(Ring::kBetaGamma, "#beta#gamma - all", out);
844 PlotOne(Ring::kBetaGammaPi, "#beta#gamma - Hadrons", out);
845 PlotOne(Ring::kBetaGammaElectron,"#beta#gamma - e^{#pm}", out);
846 PlotOne(Ring::kTypes, "Relative abundance", out);
854 void PlotOne(UShort_t which, const char* title,
855 TDirectory* dir=0, Option_t* opt="")
857 static Int_t cnt = 1;
858 const char* name = Form("c%02d", cnt++);
860 TCanvas* c = new TCanvas(name, title, 1000, 1000);
863 c->SetTopMargin(0.01);
864 c->SetRightMargin(0.03);
866 TLegend* leg = new TLegend(0.65, 0.65, 0.975, 0.975);
867 leg->SetFillStyle(0);
868 leg->SetBorderSize(0);
871 THStack* stack = new THStack(name, title);
872 for (Int_t i = 0; i < 5; i++) {
873 Ring* ring = static_cast<Ring*>(fRings->At(i));
874 Spectra* spec = ring->Get(which);
876 Warning("PlotOne", "No spectra for %d", which);
881 spec->Stack(stack, leg);
884 if (xTitle.IsNull() && spec->Hist(true))
885 xTitle = spec->Hist(true)->GetXaxis()->GetTitle();
887 // If we're not at the last one continue
890 // Add primary/secondary entry to legend
895 if (!stack->GetHists() ||
896 stack->GetHists()->GetEntries() < 0) {
897 Warning("PlotOne", "No histograms added");
900 stack->Draw(Form("nostack %s", opt));
901 stack->GetHistogram()->SetXTitle(xTitle);
902 stack->GetHistogram()->GetListOfFunctions()->Add(leg);
906 if (which != Ring::kTypes) {
911 TLatex* ltx = new TLatex(0.02, 0.02, fTitle);
913 ltx->SetTextColor(kRed+2);
914 ltx->SetTextAlign(11);
915 ltx->SetTextSize(0.02);
917 stack->GetHistogram()->GetListOfFunctions()->Add(ltx);
921 stack->Clone()->Write();
929 c->Print(Form("%s.pdf", name));
934 * @param dir Parent directory
936 void Store(TDirectory* dir)
938 TDirectory* out = dir->mkdir(fTitle);
942 while ((ring = static_cast<Ring*>(next())))
950 * @name Other interface
953 * Get the version of the selector
957 Int_t Version() const { return 1; }
961 * @return Number of processedd events
963 Long64_t GetStatus() const { return fI; }
967 //------------------------------------------------------------------
970 * @name Service functions
972 //------------------------------------------------------------------
974 * Get a chain or data set from the given file
976 * @param file File to look in
978 * @return Pointer to object or null
980 static TObject* GetChainOrDataSet(const char* file)
982 if (gSystem->AccessPathName(file)) return 0;
984 TFile* in = TFile::Open(file, "READ");
987 TObject* ret = in->Get("tree");
993 if (ret->IsA()->InheritsFrom(TChain::Class()))
994 static_cast<TChain*>(ret)->SetDirectory(0);
995 else if (ret->IsA()->InheritsFrom(TDSet::Class()))
996 static_cast<TDSet*>(ret)->SetDirectory(0);
998 ::Warning("GetChainOrDataSet", "Found object is a %s",
999 ret->IsA()->GetName());
1005 //------------------------------------------------------------------
1009 * @param src Source directory
1010 * @param recursive Whether to scan recursively
1011 * @param verbose Be verbose
1013 * @return Data set or null
1015 static TDSet* MakeDataSet(const TString& src=".",
1016 Bool_t recursive=false,
1017 Bool_t verbose=false)
1019 TString dsFile(Form("%s/dataset.root", src.Data()));
1020 TDSet* dataset = static_cast<TDSet*>(GetChainOrDataSet(dsFile));
1022 /// dataset->Print("a");
1026 TChain* c = DoMakeChain(src, recursive, verbose);
1029 dataset = new TDSet(*c, false);
1030 dataset->SetName("tree");
1031 dataset->SetLookedUp();
1032 dataset->Validate();
1036 TFile* out = TFile::Open(dsFile, "RECREATE");
1038 dataset->SetDirectory(0);
1045 //------------------------------------------------------------------
1049 * @param src Source directory
1050 * @param recursive Whether to scan recursively
1051 * @param verbose Be verbose
1053 * @return Chain or null
1055 static TChain* MakeChain(const TString& src=".",
1056 Bool_t recursive=false,
1057 Bool_t verbose=false)
1059 TString chFile(Form("%s/chain.root", src.Data()));
1060 if (!gSystem->AccessPathName(chFile)) {
1061 TFile* in = TFile::Open(chFile, "READ");
1063 TChain* ret = static_cast<TChain*>(in->Get("tree"));
1065 ret->SetDirectory(0);
1066 // ret->GetListOfFiles()->ls();
1069 if (ret) return ret;
1073 TChain* chain = DoMakeChain(src, recursive, verbose);
1075 TFile* out = TFile::Open(chFile, "RECREATE");
1077 chain->SetDirectory(0);
1083 //------------------------------------------------------------------
1087 * @param src Source directory
1088 * @param recursive Whether to scan recursively
1089 * @param verbose Be verbose
1091 * @return Chain or null
1093 static TChain* DoMakeChain(const TString& src=".",
1094 Bool_t recursive=false,
1095 Bool_t verbose=false)
1097 TChain* chain = new TChain("tree");
1098 TString savdir(gSystem->WorkingDirectory());
1099 TSystemDirectory d(gSystem->BaseName(src.Data()), src.Data());
1100 if (!ScanDirectory(&d, chain, "forward_tree_*", recursive, verbose)) {
1104 else if (!chain->GetListOfFiles() ||
1105 chain->GetListOfFiles()->GetEntries() <= 0) {
1112 //------------------------------------------------------------------
1114 * Scan directory @a dir (possibly recursive) for tree files to add
1115 * to the chain. This does not follow sym-links
1117 * @param dir Directory to scan
1118 * @param chain Chain to add to
1119 * @param pattern File name pattern
1120 * @param anchor Anchor (tree name)
1121 * @param flags Flags
1123 * @return true if any files where added
1125 static Bool_t ScanDirectory(TSystemDirectory* dir,
1127 const TString& pattern,
1132 ::Error("ScanDirectory", "No diretory passed");
1135 if (verbose) ::Info("ScanDirectory", "Scanning %s", dir->GetName());
1138 TRegexp wild(pattern, true);
1139 TString oldDir(gSystem->WorkingDirectory());
1140 TList* files = dir->GetListOfFiles();
1142 if (!gSystem->ChangeDirectory(oldDir)) {
1143 ::Error("ScanDirectory", "Failed to go back to %s",
1148 ::Warning("ScanDirectory", "No files");
1155 // Sort list of files and check if we should add it
1158 TSystemFile* file = 0;
1159 while ((file = static_cast<TSystemFile*>(next()))) {
1160 TString name(file->GetName());
1161 TString title(file->GetTitle());
1162 TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
1163 if (file->IsA()->InheritsFrom(TSystemDirectory::Class())) full = title;
1166 if (name.EqualTo(".")||name.EqualTo("..")) {
1167 // Ignore special links
1168 if (verbose) ::Info("ScanDirectory", "Ignoring special %s",
1173 if (verbose) ::Info("ScanDirectory", "Looking at %s", full.Data());
1176 if (gSystem->GetPathInfo(full.Data(), fs)) {
1177 ::Warning("ScanDirectory", "Cannot stat %s (%s)",
1178 full.Data(), gSystem->WorkingDirectory());
1181 // Check if this is a directory
1182 if (file->IsDirectory(full)) {
1183 if (verbose) ::Info("ScanDirectory", "Got a directory: %s",
1186 // if (title[0] == '/')
1187 TSystemDirectory* d = new TSystemDirectory(file->GetName(),
1189 if (ScanDirectory(d, chain, pattern, recursive, verbose))
1196 // If this is not a root file, ignore
1197 if (!name.EndsWith(".root") &&
1198 !name.EndsWith(".zip",TString::kIgnoreCase)) {
1199 if (verbose) ::Info("ScanDirectory", "Ignoring non-ROOT or ZIP %s",
1204 // If this file does not contain AliESDs, ignore
1205 if (!name.Contains(wild)) {
1206 if (verbose) ::Info("ScanDirectory", "%s does not match %s",
1207 name.Data(), pattern.Data());
1212 ::Info("::ScanDirectory", "Candidate %s", full.Data());
1213 toAdd.Add(new TObjString(full));
1215 TIter nextAdd(&toAdd);
1218 while ((s = static_cast<TObjString*>(nextAdd()))) {
1219 // Info("ChainBuilder::ScanDirectory",
1220 // "Adding %s", s->GetString().Data());
1221 TString fn = s->GetString();
1222 if (!CheckFile(fn, chain, true/*verbose*/)) continue;
1226 if (added > 0) ret = true;
1227 if (verbose) ::Info("ScanDirectory", "Added %d files", added);
1229 gSystem->ChangeDirectory(oldDir);
1232 //------------------------------------------------------------------
1234 * Check if we can add a file to the chain
1236 * @param path Full path to file
1237 * @param chain Chain
1239 * @return true on success, false otherwise
1241 static Bool_t CheckFile(const TString& path,
1245 // Info("", "Checking %s", path.Data());
1248 gSystem->RedirectOutput("/dev/null", "w");
1249 TFile* test = TFile::Open(fn, "READ");
1250 gSystem->RedirectOutput(0);
1252 ::Warning("CheckFile", "Failed to open %s", fn.Data());
1257 TObject* o = test->Get(chain->GetName());
1258 TTree* t = dynamic_cast<TTree*>(o);
1259 TFileCollection* c = dynamic_cast<TFileCollection*>(o);
1261 Int_t n = t->GetEntries();
1265 if (verbose) ::Info("CheckFile", "Added file %s (%d)", fn.Data(), n);
1267 chain->AddFileInfoList(c->GetList());
1269 if (verbose) ::Info("CheckFile", "Added file collection %s", fn.Data());
1271 // Let's try to find a TFileCollection
1272 TList* l = test->GetListOfKeys();
1275 while ((k = static_cast<TKey*>(next()))) {
1276 TString cl(k->GetClassName());
1277 if (!cl.EqualTo("TFileCollection")) continue;
1278 c = dynamic_cast<TFileCollection*>(k->ReadObj());
1280 ::Warning("CheckFile", "Returned collection invalid");
1283 // Info("", "Adding file collection");
1284 chain->AddFileInfoList(c->GetList());
1286 if (verbose) ::Info("CheckFile", "Added file collection %s", fn.Data());
1292 ::Warning("CheckFile",
1293 "The file %s does not contain the tree %s "
1294 "or a file collection",
1295 path.Data(), chain->GetName());
1300 * Run this selector on a chain locally
1302 * @param maxEvents Maximum number of events
1303 * @param title Optional title
1304 * @param maxFiles Maximum number of files to put in chain
1306 * @return true on sucess
1308 static Bool_t Run(Long64_t maxEvents=-1,
1309 const char* title="")
1313 TChain* chain = MakeChain("tuple");
1315 ::Error("Run", "No chain!");
1319 TupleSelector* s = new TupleSelector(title);
1320 Int_t status= chain->Process(s, "", maxEvents);
1325 * Run this selector on a chain in Proof
1327 * @param maxEvents Maximum number of events
1328 * @param title Optional title
1329 * @param maxFiles Maximum number of files to put in chain
1331 * @return true on sucess
1333 static Bool_t Proof(Long64_t maxEvents,
1335 const char* title="")
1339 TProof::Reset("lite:///?workers=8");
1340 TProof::Open("lite:///?workers=8");
1341 gProof->ClearCache();
1342 TString ali = gSystem->ExpandPathName("$(ALICE_ROOT)");
1343 TString fwd = ali + "/PWGLF/FORWARD/analysis2";
1344 gProof->AddIncludePath(Form("%s/include", ali.Data()));
1345 gProof->Load(Form("%s/scripts/LoadLibs.C",fwd.Data()), true);
1346 gProof->Exec("LoadLibs()");
1347 // gROOT->ProcessLine("gProof->SetLogLevel(5);");
1348 gProof->Load(Form("%s/scripts/TupleSelector.C+%s", fwd.Data(), opt),true);
1350 TDSet* dataset = MakeDataSet("tuple");
1352 ::Error("Proof", "No dataset");
1356 TupleSelector* s = new TupleSelector(title);
1357 gProof->AddFeedback("rings");
1358 gProof->Process(dataset, s, "", maxEvents);
1360 return true; // status >= 0;
1364 ClassDef(TupleSelector,2);
1370 TupleSelector(const TupleSelector&); // {}
1372 * Assignment operator
1374 * @return Reference to this object
1376 TupleSelector& operator=(const TupleSelector&); // { return *this; }