end-of-line normalization
[u/mrichter/AliRoot.git] / PWGPP / TRD / AliTRDrecoTask.cxx
1 ///////////////////////////////////////////////////////
2 //
3 // Basic class for Performance/Calibration TRD tasks
4 // 
5 // It performs generic tasks like :
6 //   - data file manegment
7 //   - reference container management
8 //   - debug container management
9 //   - interaction with AliAnalysisManager
10 //   - Plot functor loop
11 //
12 // Author: Alexandru Bercuci <A.Bercuci@gsi.de>, 10/09/2008
13 //
14 /////////////////////////////////////////////////////////
15
16 #include "TClass.h"
17 #include "TMethod.h"
18 #include "TMethodCall.h"
19 #include "TMethodArg.h"
20 #include "TFile.h"
21 #include "TChain.h"
22 #include "TList.h"
23 #include "TMap.h"
24 #include "TH1.h"
25 #include "TH2.h"
26 #include "TH3.h"
27 #include "TF1.h"
28 #include "TObjArray.h"
29 #include "TDirectory.h"
30 #include "TTreeStream.h"
31 #include "TBox.h"
32 #include "TLatex.h"
33 #include "TVectorT.h"
34
35 #include "AliLog.h"
36 #include "AliAnalysisTask.h"
37 #include "AliAnalysisManager.h"
38 #include "AliExternalTrackParam.h"
39
40 #include "info/AliTRDchmbInfo.h"
41 #include "info/AliTRDeventInfo.h"
42 #include "info/AliTRDtrendingManager.h"
43 #include "AliTRDrecoTask.h"
44 #include "AliTRDtrackV1.h"
45 #include "AliTRDpidUtil.h"
46
47 ClassImp(AliTRDrecoTask)
48
49 Float_t AliTRDrecoTask::fgPt[AliTRDrecoTask::fgNPt+1] = {0.};
50 TTreeSRedirector* AliTRDrecoTask::fgDebugStream(NULL);
51 TH1* AliTRDrecoTask::fgProjector(NULL);
52 //_______________________________________________________
53 AliTRDrecoTask::AliTRDrecoTask()
54   : AliAnalysisTaskSE()
55   ,fNRefFigures(0)
56   ,fDets(NULL)
57   ,fDetsV(NULL)
58   ,fContainer(NULL)
59   ,fEvent(NULL)
60   ,fTracks(NULL)
61   ,fClusters(NULL)
62   ,fkClusters(NULL)
63   ,fkTrack(NULL)
64   ,fkMC(NULL)
65   ,fkESD(NULL)
66   ,fSpecies(-6)
67   ,fTriggerSlot(0)
68   ,fPt(-1.)
69   ,fPhi(0.)
70   ,fEta(0.)
71   ,fNpt(0)
72   ,fTriggerList(NULL)
73   ,fPlotFuncList(NULL)
74   ,fDetFuncList(NULL)
75   ,fRunTerminate(kFALSE)
76 {
77 // Default constructor
78   snprintf(fNameId, 10, "no name");
79 }
80
81 //_______________________________________________________
82 AliTRDrecoTask::AliTRDrecoTask(const char *name, const char *title)
83   : AliAnalysisTaskSE(name)
84   ,fNRefFigures(0)
85   ,fDets(NULL)
86   ,fDetsV(NULL)
87   ,fContainer(NULL)
88   ,fEvent(NULL)
89   ,fTracks(NULL)
90   ,fClusters(NULL)
91   ,fkClusters(NULL)
92   ,fkTrack(NULL)
93   ,fkMC(NULL)
94   ,fkESD(NULL)
95   ,fSpecies(-6)
96   ,fTriggerSlot(0)
97   ,fPt(-1.)
98   ,fPhi(0.)
99   ,fEta(0.)
100   ,fNpt(0)
101   ,fTriggerList(NULL)
102   ,fPlotFuncList(NULL)
103   ,fDetFuncList(NULL)
104   ,fRunTerminate(kFALSE)
105 {
106 // Constructor for all derived performance tasks
107
108   SetTitle(title);
109   snprintf(fNameId, 10, "no name");
110   DefineInput (1, TObjArray::Class()); // track list
111   DefineInput (2, AliTRDeventInfo::Class()); // event info object
112   DefineInput (3, TObjArray::Class()); // cluster list object
113   DefineOutput(1, TObjArray::Class()); // histogram list
114 }
115
116 //_______________________________________________________
117 AliTRDrecoTask::~AliTRDrecoTask() 
118 {
119
120   // Generic task destructor
121
122   AliDebug(2, Form(" Ending task %s[%s]", GetName(), GetTitle()));
123  if(fgDebugStream){
124     delete fgDebugStream;
125     fgDebugStream = NULL;
126   }
127
128   if(fgProjector){
129     delete fgProjector;
130     fgProjector = NULL;
131   }
132
133   if(fPlotFuncList){
134     fPlotFuncList->Delete();
135     delete fPlotFuncList;
136     fPlotFuncList = NULL;
137   }
138   if(fDetFuncList){
139     fDetFuncList->Delete();
140     delete fDetFuncList;
141     fDetFuncList = NULL;
142   }
143   
144   if(fDets){
145     if(fDets->IsOwner()) fDets->Delete();
146     delete fDets;
147     fDets = NULL;
148   }
149   if(fDetsV) delete fDetsV; fDetsV=NULL;
150   if(fTriggerList){fTriggerList->Delete(); delete fTriggerList;}
151
152   if(fContainer && !(AliAnalysisManager::GetAnalysisManager() && AliAnalysisManager::GetAnalysisManager()->IsProofMode())){
153     if(fContainer->IsOwner()) fContainer->Delete();
154     delete fContainer;
155     fContainer = NULL;
156   }
157
158 /*  if(fgTrendPoint){
159     TFile::Open("TRD.PerformanceTrend.root", "UPDATE");
160     fgTrendPoint->Write();
161     delete fgTrendPoint;
162     fgTrendPoint=NULL;
163     gFile->Close();
164   }*/
165 }
166
167 //_______________________________________________________
168 Int_t AliTRDrecoTask::GetNRefFigures() const  
169
170   if(!fNRefFigures) AliWarning("No reference plots available.");
171   return fNRefFigures; 
172
173
174 //____________________________________________________________________
175 Int_t AliTRDrecoTask::GetPtBin(Float_t pt)
176 {
177 // Get significant (very low, low, medium, high, very high) pt bin
178
179   Int_t ipt(0);
180   while(ipt<fNpt){
181     if(pt<fgPt[ipt]) break;
182     ipt++;
183   }
184   return ipt-1;
185 }
186
187 //_______________________________________________________
188 Bool_t AliTRDrecoTask::MakeMomSegmentation()
189 {
190   switch(fNpt){
191   case fgNPt:
192     fgPt[0]=0.3;
193     for(Int_t j(1); j<=fgNPt; j++) fgPt[j]=fgPt[j-1]+(TMath::Exp(j*j*2.e-3)-1.);
194     AliDebug(2, "Using debug momentum segmentation");
195     break;
196   case 4:
197     fgPt[0]=0.5; fgPt[1]=0.8; fgPt[2]=1.5; fgPt[3]=5.;
198     AliDebug(2, "Using default momentum segmentation");
199     break;
200   default:
201     AliError(Form("Momentum segmentation %d not supported.", fNpt));
202     fNpt=0;
203     return kFALSE;
204   }
205   return kTRUE;
206 }
207
208 //_______________________________________________________
209 void AliTRDrecoTask::UserCreateOutputObjects()
210 {
211   if(!HasFunctorList()) InitFunctorList();
212   if(DebugLevel()) fNpt = fgNPt;
213   else fNpt = 4;
214   MakeMomSegmentation();
215
216   fContainer = Histos();
217   PostData(1, fContainer);
218 }
219
220 //_______________________________________________________
221 void AliTRDrecoTask::UserExec(Option_t *)
222 {
223 // Loop over Plot functors published by particular tasks
224
225   fTracks   = dynamic_cast<TObjArray *>(GetInputData(1));
226   fEvent    = dynamic_cast<AliTRDeventInfo *>(GetInputData(2));
227   fTriggerSlot=0;
228   if(fTriggerList && fEvent){
229     for(Int_t itrig(0); itrig<fTriggerList->GetEntries(); itrig++){
230       if(!fEvent->GetFiredTriggerClasses().Contains(((TObjString*)(*fTriggerList)[itrig])->GetName())) continue;
231       //printf("\"%s\" selected\n", ((TObjString*)(*fTriggerList)[itrig])->GetName());
232       SETBIT(fTriggerSlot,itrig);
233     }
234     if(!fTriggerSlot){
235       AliDebug(2, Form("Triggers[%s] not used for %s", fEvent->GetFiredTriggerClasses().Data(),  GetName()));
236       return;
237     }
238   }
239   fClusters = dynamic_cast<TObjArray*>(GetInputData(3));
240
241   if(!fPlotFuncList){
242     AliWarning("No track functor list defined for the task");
243     return;
244   }
245   if(!fEvent || !fTracks) return;
246   if(!fTracks->GetEntriesFast()) return;
247   else AliDebug(2, Form("Tracks[%d] for %s", fTracks->GetEntriesFast(), GetName()));
248
249   Int_t itrk(-1);
250   AliTRDtrackInfo *trackInfo(NULL);
251   TIter plotIter(fPlotFuncList);
252   TObjArrayIter trackIter(fTracks);
253   while((trackInfo = dynamic_cast<AliTRDtrackInfo*>(trackIter()))){
254     itrk++; fPt=-1; fEta=0.; fPhi=0.; fSpecies=-6;
255     fkMC    = trackInfo->GetMCinfo();
256     fkESD   = trackInfo->GetESDinfo();
257     if((fkTrack = trackInfo->GetTrack())){
258       // cache properties of the track at TRD entrance
259       // check input track status
260       AliExternalTrackParam *tin(NULL);
261       if(!(tin = fkTrack->GetTrackIn())) AliDebug(2, Form("Missing TRD track[%d] :: entry point.", itrk));
262       else {
263         fPt   = tin->Pt();
264         fEta  = tin->Eta();
265         Double_t xyz[3];
266         if(!tin->GetXYZ(xyz)) AliDebug(2, Form("Failed TRD track[%d] :: global track postion", itrk));
267         else fPhi  = TMath::ATan2(xyz[1], xyz[0]);
268         fSpecies= fkTrack->Charge()*(AliTRDpidUtil::Mass2Pid(fkTrack->GetMass())+1);
269       }
270     } else AliDebug(2, Form("Missing TRD track[%d].", itrk));
271
272     TMethodCall *plot(NULL);
273     plotIter.Reset();
274     while((plot=dynamic_cast<TMethodCall*>(plotIter()))) plot->Execute(this);
275   }
276   if(!fClusters) return;
277   if(!fDetFuncList){
278     AliDebug(1, "No detector functor list defined for task");
279     return;
280   }
281   TIter detIter(fDetFuncList);
282   for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
283     if(!(fkClusters = (TObjArray*)fClusters->At(idet))) continue;
284     TMethodCall *det(NULL);
285     detIter.Reset();
286     while((det=dynamic_cast<TMethodCall*>(detIter()))) det->Execute(this);
287   }
288 }
289
290 //_______________________________________________________
291 Bool_t AliTRDrecoTask::GetRefFigure(Int_t /*ifig*/)
292 {
293   AliWarning("Retrieving reference figures not implemented.");
294   return kFALSE;
295 }
296
297 //_______________________________________________________
298 Bool_t AliTRDrecoTask::PutTrendValue(const Char_t *name, Double_t val, Double_t err)
299 {
300 // Generic publisher for trend values
301
302   AliTRDtrendingManager *tm = AliTRDtrendingManager::Instance();
303   if(!tm){
304     AliError("Wrong usage of the trending functionality. Could not instantiate AliTRDtrendingManager singleton.");
305     return kFALSE;
306   }
307   tm->AddValue(Form("%s_%s", GetName(), name), val, err);
308   return kTRUE;
309 }
310
311 //_______________________________________________________
312 void AliTRDrecoTask::InitFunctorList()
313 {
314 // Initialize list of functors
315
316   TClass *c = this->IsA();
317   if(fPlotFuncList) fPlotFuncList->Clear();
318   if(fDetFuncList) fDetFuncList->Clear();
319
320   TMethod *m(NULL);
321   TIter methIter(c->GetListOfMethods());
322   while((m=dynamic_cast<TMethod*>(methIter()))){
323     TString name(m->GetName());
324     if(name.BeginsWith("Plot")){
325       if(!fPlotFuncList) fPlotFuncList = new TList();
326       fPlotFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));
327     } else if(name.BeginsWith("Det")){
328       if(!fDetFuncList) fDetFuncList = new TList();
329       fDetFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));
330     }
331   }
332 }
333
334 //_______________________________________________________
335 Bool_t AliTRDrecoTask::Load(const Char_t *file, const Char_t *dir)
336 {
337 // Generic container loader
338
339   if(!TFile::Open(file)){
340     AliWarning(Form("Couldn't open file %s.", file));
341     return kFALSE;
342   }
343   if(!gFile->cd(dir)){
344     AliWarning(Form("Couldn't cd to %s in %s.", dir, file));
345     gFile->Close();
346     return kFALSE;
347   }
348   if(!(fContainer = (TObjArray*)gDirectory->Get(GetName()))){
349     AliWarning("Missing histogram container.");
350     gFile->Close();
351     return kFALSE;
352   }
353   gFile->Close();
354   return kTRUE;
355 }
356
357 //________________________________________________________
358 Bool_t AliTRDrecoTask::LoadDetectorMap(const Char_t *file, const Char_t *dir)
359 {
360 // Load detector map.
361
362   if(!TFile::Open(file)){
363     AliWarning(Form("Couldn't open file %s.", file));
364     return kFALSE;
365   }
366   if(!gFile->cd(dir)){
367     AliWarning(Form("Couldn't cd to %s in %s.", dir, file));
368     gFile->Close();
369     return kFALSE;
370   }
371   TObjArray *info = NULL;
372   if(!(info = (TObjArray*)gDirectory->Get("TRDinfoGen"))){
373     AliWarning("Missing TRDinfoGen container.");
374     gFile->Close();
375     return kFALSE;
376   }
377
378   if(info->FindObject("Chambers Status"))
379     fDets = (TObjArray*)((TObjArray*)info->FindObject("Chambers Status"))->Clone();
380
381   if(!fDets){
382     if(!info->At(4) || strcmp("TObjArray", info->At(4)->IsA()->GetName())) AliError("Looking for old style chamber status map. Failed.");
383     else {
384       AliWarning("Looking for old style chamber status map.");
385       fDetsV = (TObjArray*)((TObjArray*)info->At(4))->Clone();
386     }
387   }
388   gFile->Close();
389   info->Delete(); delete info;
390   return kTRUE;
391 }
392
393
394 //________________________________________________________
395 Bool_t AliTRDrecoTask::Save(TObjArray * const results){
396   //
397   // Store the output graphs in a ROOT file
398   // Input TObject array will not be written as Key to the file,
399   // only content itself
400   //
401
402   TDirectory *cwd = gDirectory;
403   if(!TFile::Open(Form("TRD.Result%s.root", GetName()), "RECREATE")) return kFALSE;
404
405   TIterator *iter = results->MakeIterator();
406   TObject *inObject = NULL, *outObject = NULL;
407   while((inObject = iter->Next())){
408     outObject = inObject->Clone();
409     outObject->Write(NULL, TObject::kSingleKey);
410   }
411   delete iter;
412   gFile->Close(); delete gFile;
413   cwd->cd(); 
414   return kTRUE;
415 }
416
417 //_______________________________________________________
418 Bool_t AliTRDrecoTask::PostProcess()
419 {
420 // To be implemented by particular tasks
421
422   AliWarning("Post processing of reference histograms not implemented.");
423   return kTRUE;
424 }
425
426 //_______________________________________________________
427 void AliTRDrecoTask::MakeDetectorPlot(Int_t ly, const Option_t *opt)
428 {
429 // Draw chamber boundaries in eta/phi plots with misalignments
430 // based on info collected by AliTRDinfoGen
431
432   if(!fDets){
433     AliWarning("NEW Detector map and status not available. Try OLD");
434     MakeDetectorPlotOLD(ly, opt);
435     return;
436   }
437   AliTRDchmbInfo *ci(NULL);
438   for(Int_t idet(0); idet<fDets->GetEntriesFast(); idet++){
439     if(!(ci = (AliTRDchmbInfo*)fDets->At(idet))) continue;
440     if(AliTRDgeometry::GetLayer(ci->GetDetector()) != ly) continue;
441     ci->Draw(opt);
442   }
443 }
444
445 //_______________________________________________________
446 void AliTRDrecoTask::MakeDetectorPlotOLD(Int_t ly, const Option_t *opt)
447 {
448 // Draw chamber boundaries in eta/phi plots with misalignments
449 // based on info collected by AliTRDinfoGen OLD data storage
450
451   if(!fDetsV){
452     AliError("OLD Detector map and status not available.");
453     return;
454   }
455   if(!fDetsV->GetEntries()){
456     AliError("OLD Detector map and status not filled.");
457     return;
458   }
459
460   Float_t xmin(0.), xmax(0.);
461   TBox *gdet = new TBox();
462   gdet->SetLineColor(kBlack);gdet->SetFillColor(kBlack);
463   Int_t style[] = {0, 3003};
464   for(Int_t idet(0); idet<540; idet++){
465     if(idet%6 != ly) continue;
466     TVectorF *det((TVectorF*)fDetsV->At(idet));
467     if(!det) continue;
468     Int_t iopt = Int_t((*det)[4]);
469     if(strcmp(opt, "eta")==0){
470       xmin=(*det)[0]; xmax=(*det)[2];
471     } else if(strcmp(opt, "pad")==0){
472       Int_t stk(AliTRDgeometry::GetStack(idet));
473       xmin=-0.6+16*(4-stk)-(stk<2?4:0); xmax=xmin+(stk==2?12:16)-0.2;
474     } else continue;
475     AliDebug(2, Form("det[%03d] 0[%+4.1f(%+4.1f) %+4.1f] 1[%+4.1f(%+4.1f) %+4.1f] opt[%d]", idet, xmin, (*det)[0], (*det)[1], xmax, (*det)[2], (*det)[3], iopt));
476     if(iopt==1){
477       gdet->SetFillStyle(style[1]);gdet->SetFillColor(kBlack);
478       gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);
479     } else {
480       gdet->SetFillStyle(style[0]);
481       gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);
482       if(iopt==2){
483         gdet->SetFillStyle(style[1]);gdet->SetFillColor(kGreen);
484         gdet->DrawBox(xmin, (*det)[1], xmax, 0.5*((*det)[3]+(*det)[1]));
485       } else if(iopt==3){
486         gdet->SetFillStyle(style[1]);gdet->SetFillColor(kRed);
487         gdet->DrawBox(xmin, 0.5*((*det)[3]+(*det)[1]), xmax, (*det)[3]);
488       } else if(iopt!=0) AliError(Form("Wrong chmb. status[%d] for det[%03d]", iopt, idet));
489     }
490   }
491   Float_t dsm = TMath::TwoPi()/AliTRDgeometry::kNsector;
492   xmin=0.;
493   if(strcmp(opt, "pad")==0) xmin=38.;
494   TLatex *sm = new TLatex(); sm->SetTextAlign(22);sm->SetTextColor(kBlack); sm->SetTextFont(32);sm->SetTextSize(0.03);
495   for(Int_t is(0); is<AliTRDgeometry::kNsector; is++) sm->DrawLatex(xmin, -TMath::Pi()+(is+0.5)*dsm, Form("%02d", is>=9?(is-9):(is+9)));
496 }
497
498
499 //_______________________________________________________
500 void AliTRDrecoTask::MakeSummary()
501 {
502 // To be implemented by particular tasks
503   AliWarning("Summary not available");
504 }
505
506 //_______________________________________________________
507 void AliTRDrecoTask::SetDebugLevel(Int_t level)
508 {
509 // Generic debug handler
510
511   AliAnalysisTaskSE::SetDebugLevel(level);
512   if(DebugLevel()>=1 && !fgDebugStream){
513     AliInfo(Form("Debug Level for Task %s set to %d", GetName(), level));
514     TDirectory *savedir = gDirectory;
515     fgDebugStream = new TTreeSRedirector("TRD.DebugPerformance.root", "RECREATE");
516     savedir->cd();
517   }
518 }
519
520 //____________________________________________________________________
521 void AliTRDrecoTask::Terminate(Option_t *)
522 {
523   //
524   // Terminate
525   //
526
527   if(fgDebugStream){ 
528     delete fgDebugStream;
529     fgDebugStream = NULL;
530   }
531   fContainer = dynamic_cast<TObjArray *>(GetOutputData(1));
532   if(fContainer && fRunTerminate){
533     PostProcess();
534     MakeSummary();
535   }
536 }
537
538 //________________________________________________________
539 Float_t AliTRDrecoTask::SetNormZ(TH2 *h2, Int_t bxmin, Int_t bxmax, Int_t bymin, Int_t bymax, Float_t thr)
540 {
541 // Normalize histo content to the mean value in the range specified by bin ranges
542 // [bxmin, bxmax] on the x axis and [bymin, bymax] on the y axis.
543 // Optionally a threshold "thr" can be specified to disregard entries with no meaning
544
545   Float_t s = 0., c=0.; Int_t is(0);
546   for(Int_t ix(bxmin); ix<=(bxmax>0?bxmax:(h2->GetXaxis()->GetNbins())); ix++){
547     for(Int_t iy(bymin); iy<=(bymax>0?bymax:(h2->GetYaxis()->GetNbins())); iy++){
548       if((c = h2->GetBinContent(ix, iy))<thr) continue;
549       s += c; is++;
550     }
551   }
552   s/= (is?is:1);
553   for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){
554     for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){
555       if((c = h2->GetBinContent(ix, iy))<thr) h2->SetBinContent(ix, iy, thr-1000);
556       else h2->SetBinContent(ix, iy, 100.*(c/s-1.));
557     }
558   }
559   return s;
560 }
561
562 //________________________________________________________
563 void AliTRDrecoTask::SetRangeZ(TH2 *h2, Float_t min, Float_t max, Float_t thr)
564 {
565 // Set range on Z axis such to avoid outliers
566
567   Float_t c(0.), dz(1.e-3*(max-min));
568   for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){
569     for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){
570       if((c = h2->GetBinContent(ix, iy))<thr) continue;
571       if(c<=min) h2->SetBinContent(ix, iy, min+dz);
572     }
573   }
574   h2->GetZaxis()->SetRangeUser(min, max);
575 }
576
577 //________________________________________________________
578 Float_t AliTRDrecoTask::GetMeanStat(TH1 *h, Float_t cut, Int_t opt, Float_t *sigma)
579 {
580 // Return mean number of entries/bin of histogram "h".
581 // If optionally sigma is allocated than it is also filled with sigma paramter of the gauss fit 
582 //
583 // Option "opt" is given the following values are accepted:
584 //   -1 : consider only entries less than "cut"
585 //   1  : consider only entries greater than "cut"
586 //   0  : no "cut" [dafault]
587 // Error codes
588 //   -999. : statistics too low [20]
589 //   -998. : fit failed
590
591   const Int_t kvd(100000);
592   Float_t v[kvd];
593   Int_t nbx(h->GetNbinsX()), nby(h->GetNbinsY()), nbz(h->GetNbinsZ());
594   Int_t nv(0); Float_t xmin(1.e5), xmax(-xmin);
595   for(Int_t ix(1); ix<=nbx; ix++){
596     for(Int_t iy(1); iy<=nby; iy++){
597       for(Int_t iz(1); iz<=nbz; iz++){
598         Float_t c = h->GetBinContent(ix, iy, iz);
599         if(opt*(c-cut)<0.) continue;
600         v[nv++] = c;
601         if(c<xmin) xmin = c;
602         if(c>xmax) xmax = c;
603         if(nv==kvd){
604           printf("W - AliTRDrecoTask::GetMeanStat() :: Unreliable results for %s[%s]. Statical allocation exceeded.\n", h->GetName(), h->GetTitle());
605           break;
606         }
607       }
608       if(nv==kvd) break;
609     }
610     if(nv==kvd) break;
611   }
612   if(nv<10){
613     //printf("W - AliTRDrecoTask::GetMeanStat() :: Failed for %s[%s]. Statical undefined [%d].\n", h->GetName(), h->GetTitle(), nv);
614     return -999.;
615   }
616   if(fgProjector) delete fgProjector;
617   fgProjector = new TH1F("hProjector", "", 20, 0.5*(3*xmin-xmax), 0.5*(3*xmax - xmin));
618   for(Int_t iv(0); iv<nv; iv++) fgProjector->Fill(v[iv]);
619   TF1 f("f", "gaus", xmin, xmax);
620   f.SetParameter(0, fgProjector->Integral());
621   f.SetParameter(1, fgProjector->GetMean()); f.SetParLimits(1, xmin, xmax);
622   f.SetParameter(2, fgProjector->GetRMS());
623   if(fgProjector->Fit(&f, "WQ0", "goff")) return -998.;
624   if(sigma) *sigma = f.GetParameter(2);
625   return f.GetParameter(1);
626 }
627
628 //________________________________________________________
629 Int_t AliTRDrecoTask::Rebin(TH2 *h, Int_t n, Int_t rebinX[], Int_t rebinY[], Int_t nstat)
630 {
631 // Rebin histo "h" according to "rebinning" strategy "n" steps such to obtain mean statistics per bin over "nstat"
632
633   Int_t irebin(0);
634   while(irebin<n && GetMeanStat(h, .5, 1)<nstat){
635     h->Rebin2D(rebinX[irebin], rebinY[irebin]);
636     irebin++;
637   }
638   return irebin;
639 }
640
641 //________________________________________________________
642 AliTRDrecoTask::AliTRDrecoProjection::AliTRDrecoProjection()
643   :TNamed()
644   ,fH(NULL)
645   ,fNrebin(0)
646 {
647   // constructor
648   fRebin[0] = NULL;fRebin[1] = NULL;
649   memset(fAx, 0, 3*sizeof(Int_t));
650   memset(fRange, 0, 4*sizeof(Float_t));
651 }
652
653 //________________________________________________________
654 AliTRDrecoTask::AliTRDrecoProjection::~AliTRDrecoProjection()
655 {
656   // destructor
657   if(fH) delete fH;
658   if(fRebin[0]) delete [] fRebin[0];
659   if(fRebin[1]) delete [] fRebin[1];
660 }
661
662 //________________________________________________________
663 void AliTRDrecoTask::AliTRDrecoProjection::Build(const Char_t *n, const Char_t *t, Int_t ix, Int_t iy, Int_t iz, TAxis *aa[])
664 {
665 // check and build (if neccessary) projection determined by axis "ix", "iy" and "iz"
666   if(!aa[ix] || !aa[iy] || !aa[iz]) return;
667   TAxis *ax(aa[ix]), *ay(aa[iy]), *az(aa[iz]);
668   // check ax definiton to protect against older versions of the data
669   if(ax->GetNbins()<=0 || (ax->GetXmax()-ax->GetXmin())<=0.){
670     AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax()));
671     return;
672   }
673   if(ay->GetNbins()<=0 || (ay->GetXmax()-ay->GetXmin())<=0.){
674     AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax()));
675     return;
676   }
677   if(az->GetNbins()<=0 || (az->GetXmax()-az->GetXmin())<=0.){
678     AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));
679     return;
680   }
681   SetNameTitle(n,t);
682   fH = new TH3I(n, Form("%s;%s;%s;%s", t, ax->GetTitle(), ay->GetTitle(), az->GetTitle()),
683     ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
684     ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),
685     az->GetNbins(), az->GetXmin(), az->GetXmax());
686   fAx[0] = ix; fAx[1] = iy; fAx[2] = iz;
687   fRange[0] = az->GetXmin()/3.; fRange[1] = az->GetXmax()/3.;
688   AliDebug(2, Form("H3(%s, %s) :: %s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]", n, t,
689     ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
690     ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),
691     az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));
692 }
693
694 //________________________________________________________
695 AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator=(const AliTRDrecoProjection& rhs)
696 {
697 // copy projections
698   if(this == &rhs) return *this;
699
700   TNamed::operator=(rhs);
701   if(fNrebin){fNrebin=0; delete [] fRebin[0]; delete [] fRebin[1];}
702   if(rhs.fNrebin) SetRebinStrategy(rhs.fNrebin, rhs.fRebin[0], rhs.fRebin[1]);
703   memcpy(fAx, rhs.fAx, 3*sizeof(Int_t));
704   memcpy(fRange, rhs.fRange, 4*sizeof(Float_t));
705   if(fH) delete fH;
706   if(rhs.fH) fH=(TH3I*)rhs.fH->Clone(Form("%s_CLONE", rhs.fH->GetName()));
707   return *this;
708 }
709
710 //________________________________________________________
711 AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator+=(const AliTRDrecoProjection& other)
712 {
713 // increment projections
714   if(!fH || !other.fH) return *this;
715   AliDebug(2, Form("%s+=%s [%s+=%s]", GetName(), other.GetName(), fH->GetName(), (other.fH)->GetName()));
716   fH->Add(other.fH);
717   return *this;
718 }
719
720 //________________________________________________________
721 void AliTRDrecoTask::AliTRDrecoProjection::Increment(Int_t bin[], Double_t v)
722 {
723 // increment bin with value "v" pointed by general coord in "bin"
724   if(!fH) return;
725   AliDebug(4, Form("  %s[%2d]", fH->GetName(), Int_t(v)));
726   fH->AddBinContent(fH->GetBin(bin[fAx[0]],bin[fAx[1]],bin[fAx[2]]), Int_t(v));
727 }
728
729 //________________________________________________________
730 Double_t AliTRDrecoTask::AliTRDrecoProjection::GetTrendValue(const Int_t mid, Double_t *e, Double_t *s, Double_t *se) const
731 {
732 //   Return result of fitting the main distribution (represented on the z axis) with the function selected
733 // "mid". Optionally return the Mean and RMS of the distribution pointing to "m" and "s"
734
735   if(!fH){
736     AliDebug(1, Form("Missing 3D in %s", GetName()));
737     return -999.;
738   }
739   TH1 *h1s(NULL);
740   if(!(h1s = (TH1D*)fH->Project3D("z"))){
741     AliDebug(1, Form("Failed Project3D(\"z\") in %s", GetName()));
742     return -999.;
743   }
744   Int_t ne((Int_t)h1s->Integral());
745   if(ne<30){
746     AliDebug(1, Form("Statistics too low[%2d] in %s", ne, GetName()));
747     delete h1s;
748     return -999.;
749   }
750   TAxis *az(h1s->GetXaxis());
751   Float_t mn(h1s->GetMean()), rms(h1s->GetRMS()),
752           v(mn),  // main trending value (mean, mu, MPV)
753           ve(rms),// dispersion (RMS, sigma, landau 2nd param)
754           ev(h1s->GetMeanError()), // error on v
755           eve(h1s->GetRMSError());// error on ve
756   if(mid==1){
757     TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());
758     fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, mn); fg.SetParameter(2, rms);
759     h1s->Fit(&fg, "WQ0");
760     v = fg.GetParameter(1); ev = fg.GetParError(1);
761     ve= fg.GetParameter(2); eve= fg.GetParError(2);
762   } else if (mid==2) {
763     TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());
764     fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, mn); fl.SetParameter(2, rms);
765     h1s->Fit(&fl, "WQ0");
766     v = fl.GetMaximumX(); ev = fl.GetParError(1);
767     ve= fl.GetParameter(2);eve= fl.GetParError(2);
768   }
769   if(e)  *e  = ev;
770   if(s)  *s  = ve;
771   if(se) *se = eve;
772   AliDebug(2, Form("[%d] %s(%4d) = M{%f+-%f} S{%f+-%f}", mid, fH->GetName(), (Int_t)h1s->Integral(), v, ev, ve, eve));
773
774   delete h1s;
775   return v;
776 }
777
778 //________________________________________________________
779 TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2Dbin(Int_t bin, Bool_t mc)
780 {
781 // dumb 2D projection for bin including under/over flow. Default all [bin==-1]
782
783   TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());
784   Int_t nbins(az->GetNbins());
785   TH2F *h2(NULL);
786   if(bin<0) h2 = new TH2F(Form("%s_2D", fH->GetName()),
787                 Form("%s;%s;%s;Entries", fH->GetTitle(), ax->GetTitle(), ay->GetTitle()),
788                 ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
789                 ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
790   else h2 = new TH2F(Form("%s%d_2D", fH->GetName(), bin),
791                 Form("%s | #it{%4.2f<=p_{t}^{%s}[GeV/c]<%4.2f};%s;%s;Entries", fH->GetTitle(),
792                 bin?fgPt[bin-1]:0., mc?"MC":"", bin>nbins?99.99:fgPt[bin], ax->GetTitle(), ay->GetTitle()),
793                 ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
794                 ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
795   for(Int_t ix(1); ix<=ax->GetNbins(); ix++){
796     for(Int_t iy(1); iy<=ay->GetNbins(); iy++){
797       Int_t ibin = h2->GetBin(ix, iy);
798       for(Int_t iz(0); iz<=az->GetNbins()+1; iz++){
799         if(bin<0) h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));
800         else if(bin==iz){
801           h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));
802           break;
803         }
804       }
805     }
806   }
807   return h2;
808 }
809
810 //________________________________________________________
811 TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2D(const Int_t nstat, const Int_t ncol, const Int_t mid, Bool_t del)
812 {
813 // build the 2D projection and adjust binning
814
815   const Char_t *title[] = {"Mean", "#mu", "MPV"};
816   if(!fH){
817     AliDebug(1, Form("Missing 3D in %s", GetName()));
818     return NULL;
819   }
820   TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());
821   TH2D *h2s(NULL), *hyx(NULL);
822   if(!(h2s = (TH2D*)fH->Project3D("yx"))){
823     AliDebug(1, Form("Failed Project3D(\"yx\") in %s", GetName()));
824     return NULL;
825   }
826   // save a copy of the original distribution
827   if(!del){
828     hyx = (TH2D*)h2s->Clone();
829     hyx->SetName(Form("%sEn", fH->GetName()));
830   }
831   Int_t irebin(Rebin(h2s, fNrebin, fRebin[0], fRebin[1], nstat)), dxBin(1), dyBin(1);
832   for(Int_t ir(0); ir<irebin; ir++){dxBin*=fRebin[0][ir]; dyBin*=fRebin[1][ir];}
833   Int_t nx(h2s->GetNbinsX()), ny(h2s->GetNbinsY());
834   delete h2s;
835   if(mid<0) return NULL;
836
837   // start projection
838   TH1 *h(NULL); Int_t n(0);
839   Float_t dz=(fRange[1]-fRange[1])/ncol;
840   TString titlez(az->GetTitle()); TObjArray *tokenTitle(titlez.Tokenize(" "));
841   Int_t nt(tokenTitle->GetEntriesFast());
842   TH2 *h2(NULL);
843   if((h2 = (TH2*)gDirectory->Get(Form("%s_2D", fH->GetName())))) delete h2; // avoid ROOT warning messages
844   h2 = new TH2F(Form("%s_2D", fH->GetName()),
845             Form("%s;%s;%s;%s(%s) %s", fH->GetTitle(), ax->GetTitle(), ay->GetTitle(), title[mid], nt>0?(*tokenTitle)[0]->GetName():"", nt>1?(*tokenTitle)[1]->GetName():""),
846             nx, ax->GetXmin(), ax->GetXmax(), ny, ay->GetXmin(), ay->GetXmax());
847   tokenTitle->Delete(); delete tokenTitle;
848   h2->SetContour(ncol);
849   h2->GetZaxis()->CenterTitle();
850   h2->GetZaxis()->SetTitleOffset(1.4);
851   h2->GetZaxis()->SetRangeUser(fRange[0], fRange[1]);
852   AliDebug(2, Form("%s[%s] nx[%d] ny[%d]", h2->GetName(), h2->GetTitle(), nx, ny));
853   for(Int_t iy(0); iy<ny; iy++){
854     for(Int_t ix(0); ix<nx; ix++){
855       h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin);
856       Int_t ne((Int_t)h->Integral());
857       //printf("  x[%2d %2d] y[%2d %2d] ne[%4d]\n", ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin, ne);
858       if(ne<nstat/2){
859         h2->SetBinContent(ix+1, iy+1, -999);
860         h2->SetBinError(ix+1, iy+1, 1.);
861         n++;
862       }else{
863         // redo the projection by adding 1 bin @ left and 1 bin @ right for smoothing
864         h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin, (ix+1)*dxBin+1, iy*dyBin, (iy+1)*dyBin+1);
865         Float_t v(h->GetMean()), ve(h->GetRMS());
866         if(mid==1){
867           TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());
868           fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, v); fg.SetParameter(2, ve);
869           h->Fit(&fg, "WQ0");
870           v = fg.GetParameter(1); ve = fg.GetParameter(2);
871         } else if (mid==2) {
872           TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());
873           fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, v); fl.SetParameter(2, ve);
874           h->Fit(&fl, "WQ0");
875           v = fl.GetMaximumX(); ve = fl.GetParameter(2);
876 /*          TF1 fgle("gle", "[0]*TMath::Landau(x, [1], [2], 1)*TMath::Exp(-[3]*x/[1])", az->GetXmin(), az->GetXmax());
877           fgle.SetParameter(0, fl.GetParameter(0));
878           fgle.SetParameter(1, fl.GetParameter(1));
879           fgle.SetParameter(2, fl.GetParameter(2));
880           fgle.SetParameter(3, 1.);fgle.SetParLimits(3, 0., 5.);
881           h->Fit(&fgle, "WQ");
882           v = fgle.GetMaximumX(); ve = fgle.GetParameter(2);*/
883         }
884         if(v<fRange[0]) h2->SetBinContent(ix+1, iy+1, fRange[0]+0.1*dz);
885         else h2->SetBinContent(ix+1, iy+1, v);
886         h2->SetBinError(ix+1, iy+1, ve);
887       }
888     }
889   }
890   if(h) delete h;
891   if(n==nx*ny){  // clean empty projections
892     AliDebug(1, Form("Empty projection in %s", GetName()));
893     delete h2; h2=NULL;
894   }
895   return h2;
896 }
897
898 //________________________________________________________
899 void AliTRDrecoTask::AliTRDrecoProjection::SetRebinStrategy(Int_t n, Int_t rebx[], Int_t reby[])
900 {
901 // define rebinning strategy for this projection
902   fNrebin = n;
903   fRebin[0] = new Int_t[n]; memcpy(fRebin[0], rebx, n*sizeof(Int_t));
904   fRebin[1] = new Int_t[n]; memcpy(fRebin[1], reby, n*sizeof(Int_t));
905 }
906
907 //________________________________________________________
908 void AliTRDrecoTask::SetTriggerList(const Char_t *tl)
909 {
910 // Store list of triggers to be monitored
911   TString stl(tl);
912   if(fTriggerList){ fTriggerList->Delete(); delete fTriggerList;}
913   TObjArray *atl = stl.Tokenize(" ");
914   fTriggerList = (TObjArray*)atl->Clone("");
915   atl->Delete(); delete atl;
916   AliInfo("Running only for triggers::");
917   fTriggerList->Print();
918 }
919
920