]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG4/JetTasks/AliAnalysisHelperJetTasks.cxx
added option for variable binning depending on the dataset for high pt QA and spectra...
[u/mrichter/AliRoot.git] / PWG4 / JetTasks / AliAnalysisHelperJetTasks.cxx
1
2 #include "TROOT.h"
3 #include "TDirectory.h"
4 #include "TKey.h"
5 #include "TList.h"
6 #include "TSystem.h"
7 #include "TH1F.h"
8 #include "TProfile.h"
9 #include "THnSparse.h"
10 #include "TFile.h"
11 #include "TString.h"
12 #include "AliMCEvent.h"
13 #include "AliLog.h"
14 #include "AliESDEvent.h"
15 #include "AliAODJet.h"
16 #include "AliAODEvent.h"
17 #include "AliStack.h"
18 #include "AliGenEventHeader.h"
19 #include "AliGenCocktailEventHeader.h"
20 #include <AliGenDPMjetEventHeader.h>
21 #include "AliGenPythiaEventHeader.h"
22 #include <fstream>
23 #include <iostream>
24 #include "AliAnalysisHelperJetTasks.h"
25 #include "TMatrixDSym.h"
26 #include "TMatrixDSymEigen.h"
27 #include "TVector.h"
28
29 ClassImp(AliAnalysisHelperJetTasks)
30
31 Int_t AliAnalysisHelperJetTasks::fgLastProcessType = -1;
32
33  
34 AliGenPythiaEventHeader*  AliAnalysisHelperJetTasks::GetPythiaEventHeader(AliMCEvent *mcEvent){
35   
36   AliGenEventHeader* genHeader = mcEvent->GenEventHeader();
37   AliGenPythiaEventHeader* pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
38   if(!pythiaGenHeader){
39     // cocktail ??
40     AliGenCocktailEventHeader* genCocktailHeader = dynamic_cast<AliGenCocktailEventHeader*>(genHeader);
41     
42     if (!genCocktailHeader) {
43       AliWarningGeneral(Form(" %s:%d",(char*)__FILE__,__LINE__),"Unknown header type (not Pythia or Cocktail)");
44       //      AliWarning(Form("%s %d: Unknown header type (not Pythia or Cocktail)",(char*)__FILE__,__LINE__));
45       return 0;
46     }
47     TList* headerList = genCocktailHeader->GetHeaders();
48     for (Int_t i=0; i<headerList->GetEntries(); i++) {
49       pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(headerList->At(i));
50       if (pythiaGenHeader)
51         break;
52     }
53     if(!pythiaGenHeader){
54       AliWarningGeneral(Form(" %s:%d",(char*)__FILE__,__LINE__),"Pythia event header not found");
55       return 0;
56     }
57   }
58   return pythiaGenHeader;
59
60 }
61
62
63 void AliAnalysisHelperJetTasks::PrintStack(AliMCEvent *mcEvent,Int_t iFirst,Int_t iLast,Int_t iMaxPrint){
64
65   AliStack *stack = mcEvent->Stack();
66   if(!stack){
67     Printf("%s%d No Stack available",(char*)__FILE__,__LINE__);
68     return;
69   }
70
71   static Int_t iCount = 0;
72   if(iCount>iMaxPrint)return;
73   Int_t nStack = stack->GetNtrack();
74   if(iLast == 0)iLast = nStack;
75   else if(iLast > nStack)iLast = nStack;
76
77
78   Printf("####################################################################");
79   for(Int_t np = iFirst;np<iLast;++np){
80     TParticle *p = stack->Particle(np);
81     Printf("Nr.%d --- Status %d ---- Mother1 %d Mother2 %d Daughter1 %d Daughter2 %d ",
82            np,p->GetStatusCode(),p->GetMother(0),p->GetMother(1),p->GetDaughter(0),p->GetDaughter(1));
83     Printf("Eta %3.3f Phi %3.3f ",p->Eta(),p->Phi()); 
84     p->Print();    
85     Printf("---------------------------------------");
86   }
87   iCount++;
88 }
89
90
91
92
93 void AliAnalysisHelperJetTasks::GetClosestJets(AliAODJet *genJets,const Int_t &kGenJets,
94                                                AliAODJet *recJets,const Int_t &kRecJets,
95                                                Int_t *iGenIndex,Int_t *iRecIndex,
96                                                Int_t iDebug,Float_t maxDist){
97
98   //
99   // Relate the two input jet Arrays
100   //
101
102   //
103   // The association has to be unique
104   // So check in two directions
105   // find the closest rec to a gen
106   // and check if there is no other rec which is closer
107   // Caveat: Close low energy/split jets may disturb this correlation
108
109
110   // Idea: search in two directions generated e.g (a--e) and rec (1--3)
111   // Fill a matrix with Flags (1 for closest rec jet, 2 for closest rec jet
112   // in the end we have something like this
113   //    1   2   3
114   // ------------
115   // a| 3   2   0
116   // b| 0   1   0
117   // c| 0   0   3
118   // d| 0   0   1
119   // e| 0   0   1
120   // Topology
121   //   1     2
122   //     a         b        
123   //
124   //  d      c
125   //        3     e
126   // Only entries with "3" match from both sides
127
128   // In case we have more jets than kmaxjets only the 
129   // first kmaxjets are searched
130   // all other are -1
131   // use kMaxJets for a test not to fragemnt the memory...
132
133   for(int i = 0;i < kGenJets;++i)iGenIndex[i] = -1;
134   for(int j = 0;j < kRecJets;++j)iRecIndex[j] = -1;
135
136
137   
138   const int kMode = 3;
139
140   const Int_t nGenJets = TMath::Min(kMaxJets,kGenJets);
141   const Int_t nRecJets = TMath::Min(kMaxJets,kRecJets);
142
143   if(nRecJets==0||nGenJets==0)return;
144
145   // UShort_t *iFlag = new UShort_t[nGenJets*nRecJets];
146   UShort_t iFlag[kMaxJets*kMaxJets];
147   for(int i = 0;i < nGenJets;++i){
148     for(int j = 0;j < nRecJets;++j){
149       iFlag[i*nGenJets+j] = 0;
150     }
151   }
152
153
154
155   // find the closest distance to the generated
156   for(int ig = 0;ig<nGenJets;++ig){
157     Float_t dist = maxDist;
158     if(iDebug>1)Printf("Gen (%d) p_T %3.3f eta %3.3f ph %3.3f ",ig,genJets[ig].Pt(),genJets[ig].Eta(),genJets[ig].Phi());
159     for(int ir = 0;ir<nRecJets;++ir){
160       Double_t dR = genJets[ig].DeltaR(&recJets[ir]);
161       if(iDebug>1)Printf("Rec (%d) p_T %3.3f eta %3.3f ph %3.3f ",ir,recJets[ir].Pt(),recJets[ir].Eta(),recJets[ir].Phi());
162       if(iDebug>1)Printf("Distance (%d)--(%d) %3.3f ",ig,ir,dR);
163       if(dR<dist){
164         iRecIndex[ig] = ir;
165         dist = dR;
166       } 
167     }
168     if(iRecIndex[ig]>=0)iFlag[ig*nGenJets+iRecIndex[ig]]+=1;
169     // reset...
170     iRecIndex[ig] = -1;
171   }
172   // other way around
173   for(int ir = 0;ir<nRecJets;++ir){
174     Float_t dist = maxDist;
175     for(int ig = 0;ig<nGenJets;++ig){
176       Double_t dR = genJets[ig].DeltaR(&recJets[ir]);
177       if(dR<dist){
178         iGenIndex[ir] = ig;
179         dist = dR;
180       } 
181     }
182     if(iGenIndex[ir]>=0)iFlag[iGenIndex[ir]*nGenJets+ir]+=2;
183     // reset...
184     iGenIndex[ir] = -1;
185   }
186
187   // check for "true" correlations
188
189   if(iDebug>1)Printf(">>>>>> Matrix");
190
191   for(int ig = 0;ig<nGenJets;++ig){
192     for(int ir = 0;ir<nRecJets;++ir){
193       // Print
194       if(iDebug>1)printf("Flag[%d][%d] %d ",ig,ir,iFlag[ig*nGenJets+ir]);
195
196       if(kMode==3){
197         // we have a uniqie correlation
198         if(iFlag[ig*nGenJets+ir]==3){
199           iGenIndex[ir] = ig;
200           iRecIndex[ig] = ir;
201         }
202       }
203       else{
204         // we just take the correlation from on side
205         if((iFlag[ig*nGenJets+ir]&2)==2){
206           iGenIndex[ir] = ig;
207         }
208         if((iFlag[ig*nGenJets+ir]&1)==1){
209           iRecIndex[ig] = ir;
210         }
211       }
212     }
213     if(iDebug>1)printf("\n");
214   }
215 }
216
217
218
219 void  AliAnalysisHelperJetTasks::MergeOutput(char* cFiles, char* cDir, char *cList,char *cOutFile,Bool_t bUpdate){
220
221   // This is used to merge the analysis-output from different 
222   // data samples/pt_hard bins
223   // in case the eventweigth was set to xsection/ntrials already, this
224   // is not needed. Both methods only work in case we do not mix different 
225   // pt_hard bins, and do not have overlapping bins
226
227   const Int_t nMaxBins = 12;
228   // LHC08q jetjet100: Mean = 1.42483e-03, RMS = 6.642e-05
229   // LHC08r jetjet50: Mean = 2.44068e-02, RMS = 1.144e-03
230   // LHC08v jetjet15-50: Mean = 2.168291 , RMS = 7.119e-02
231   // const Float_t xsection[nBins] = {2.168291,2.44068e-02};
232
233   Float_t xsection[nMaxBins];
234   Float_t nTrials[nMaxBins];
235   Float_t sf[nMaxBins];
236   TList *lIn[nMaxBins];
237   TDirectory *dIn[nMaxBins];
238   TFile *fIn[nMaxBins];
239
240   ifstream in1;
241   in1.open(cFiles);
242
243   char cFile[120];
244   Int_t ibTotal = 0;
245   while(in1>>cFile){
246     fIn[ibTotal] = TFile::Open(cFile);
247     if(strlen(cDir)==0){
248       dIn[ibTotal] = gDirectory;
249     }
250     else{
251       dIn[ibTotal] = (TDirectory*)fIn[ibTotal]->Get(cDir);
252     }
253     if(!dIn[ibTotal]){
254       Printf("%s:%d No directory %s found, exiting...",__FILE__,__LINE__,cDir);
255       fIn[ibTotal]->ls();
256       return;
257     }
258
259     lIn[ibTotal] = (TList*)dIn[ibTotal]->Get(cList);
260     Printf("Merging file %s %s",cFile, cDir);
261     if(!lIn[ibTotal]){
262       Printf("%s:%d No list %s found, exiting...",__FILE__,__LINE__,cList);
263       fIn[ibTotal]->ls();
264       return;
265     }
266     TH1* hTrials = (TH1F*)lIn[ibTotal]->FindObject("fh1Trials");
267     if(!hTrials){
268       Printf("%s:%d fh1PtHard_Trials not found in list, exiting...",__FILE__,__LINE__);
269       return;
270     }
271     TProfile* hXsec = (TProfile*)lIn[ibTotal]->FindObject("fh1Xsec");
272     if(!hXsec){
273       Printf("%s:%d fh1Xsec  not found in list, exiting...",__FILE__,__LINE__);
274       return;
275     }
276     xsection[ibTotal] = hXsec->GetBinContent(1);
277     nTrials[ibTotal] = hTrials->Integral();
278     sf[ibTotal] = xsection[ibTotal]/ nTrials[ibTotal];
279     ibTotal++;
280   }
281
282   if(ibTotal==0){
283     Printf("%s:%d No files found for mergin, exiting",__FILE__,__LINE__);
284     return;
285   }
286
287   TFile *fOut = 0;
288   if(bUpdate)fOut = new TFile(cOutFile,"UPDATE");
289   else fOut = new TFile(cOutFile,"RECREATE");
290   TDirectory *dOut = fOut->mkdir(dIn[0]->GetName());
291   dOut->cd();
292   TList *lOut = new TList();
293   lOut->SetName(lIn[0]->GetName());
294
295   // for the start scale all...
296   for(int ie = 0; ie < lIn[0]->GetEntries();++ie){
297     TH1 *h1Add = 0;
298     THnSparse *hnAdd = 0;
299     for(int ib = 0;ib < ibTotal;++ib){
300       // dynamic cast does not work with cint
301       TObject *h = lIn[ib]->At(ie);
302       if(h->InheritsFrom("TH1")){
303         TH1 *h1 = (TH1*)h;
304         if(ib==0){
305           h1Add = (TH1*)h1->Clone(h1->GetName());
306           h1Add->Scale(sf[ib]);
307         }
308         else{
309           h1Add->Add(h1,sf[ib]);
310         }
311       }
312       else if(h->InheritsFrom("THnSparse")){
313         THnSparse *hn = (THnSparse*)h;
314         if(ib==0){
315           hnAdd = (THnSparse*)hn->Clone(hn->GetName());
316           hnAdd->Scale(sf[ib]);
317         }
318         else{
319           hnAdd->Add(hn,sf[ib]);
320         }
321       }
322       
323
324     }// ib
325     if(h1Add)lOut->Add(h1Add);
326     else if(hnAdd)lOut->Add(hnAdd);
327   }
328   dOut->cd();
329   lOut->Write(lOut->GetName(),TObject::kSingleKey);
330   fOut->Close();
331 }
332
333 Bool_t AliAnalysisHelperJetTasks::PythiaInfoFromFile(const char* currFile,Float_t &fXsec,Float_t &fTrials){
334   //
335   // get the cross section and the trails either from pyxsec.root or from pysec_hists.root
336   // This is to called in Notify and should provide the path to the AOD/ESD file
337
338   TString file(currFile);  
339   fXsec = 0;
340   fTrials = 1;
341
342   if(file.Contains("root_archive.zip#")){
343     Ssiz_t pos1 = file.Index("root_archive",12,TString::kExact);
344     Ssiz_t pos = file.Index("#",1,pos1,TString::kExact);
345     file.Replace(pos+1,20,"");
346   }
347   else {
348     // not an archive take the basename....
349     file.ReplaceAll(gSystem->BaseName(file.Data()),"");
350   }
351   Printf("%s",file.Data());
352   
353  
354    
355
356   TFile *fxsec = TFile::Open(Form("%s%s",file.Data(),"pyxsec.root")); // problem that we cannot really test the existance of a file in a archive so we have to lvie with open error message from root
357   if(!fxsec){
358     // next trial fetch the histgram file
359     fxsec = TFile::Open(Form("%s%s",file.Data(),"pyxsec_hists.root"));
360     if(!fxsec){
361         // not a severe condition but inciate that we have no information
362       return kFALSE;
363     }
364     else{
365       // find the tlist we want to be independtent of the name so use the Tkey
366       TKey* key = (TKey*)fxsec->GetListOfKeys()->At(0); 
367       if(!key){
368         fxsec->Close();
369         return kFALSE;
370       }
371       TList *list = dynamic_cast<TList*>(key->ReadObj());
372       if(!list){
373         fxsec->Close();
374         return kFALSE;
375       }
376       fXsec = ((TProfile*)list->FindObject("h1Xsec"))->GetBinContent(1);
377       fTrials  = ((TH1F*)list->FindObject("h1Trials"))->GetBinContent(1);
378       fxsec->Close();
379     }
380   } // no tree pyxsec.root
381   else {
382     TTree *xtree = (TTree*)fxsec->Get("Xsection");
383     if(!xtree){
384       fxsec->Close();
385       return kFALSE;
386     }
387     UInt_t   ntrials  = 0;
388     Double_t  xsection  = 0;
389     xtree->SetBranchAddress("xsection",&xsection);
390     xtree->SetBranchAddress("ntrials",&ntrials);
391     xtree->GetEntry(0);
392     fTrials = ntrials;
393     fXsec = xsection;
394     fxsec->Close();
395   }
396   return kTRUE;
397 }
398
399 Bool_t AliAnalysisHelperJetTasks::PrintDirectorySize(const char* currFile){
400
401   TFile *fIn = TFile::Open(currFile);
402   if(!fIn){
403     // not a severe condition but inciate that we have no information
404     return kFALSE;
405   }
406   // find the tlists we want to be independtent of the name so use the Tkey
407   TList* keyList = fIn->GetListOfKeys();
408   Float_t memorySize = 0;
409   Float_t diskSize = 0;
410
411   for(int i = 0;i < keyList->GetEntries();i++){
412     TKey* ikey = (TKey*)keyList->At(i); 
413     
414     //    TList *list = dynamic_cast<TList*>(key->ReadObj());
415     //    TNamed *name = dynamic_cast<TNamed*>(ikey->ReadObj());
416     TDirectory *dir =  dynamic_cast<TDirectory*>(ikey->ReadObj());
417     
418
419
420
421     if(dir){
422       Printf("%03d    : %60s %8d %8d ",i,dir->GetName(),ikey->GetObjlen(),ikey->GetNbytes());
423       TList * dirKeyList = dir->GetListOfKeys();
424       for(int j = 0;j<dirKeyList->GetEntries();j++){
425         TKey* jkey = (TKey*)dirKeyList->At(j); 
426         TList *list =  dynamic_cast<TList*>(jkey->ReadObj());
427
428         memorySize += (Float_t)jkey->GetObjlen()/1024./1024.;
429         diskSize +=  (Float_t)jkey->GetNbytes()/1024./1024.;
430         if(list){
431           Printf("%03d/%03d: %60s %5.2f MB %5.2f MB",i,j,list->GetName(),(Float_t)jkey->GetObjlen()/1024./1024.,(Float_t)jkey->GetNbytes()/1024./1024.);
432         }
433         else{
434           Printf("%03d/%03d: %60s %5.2f MB %5.2f MB",i,j,jkey->GetName(),(Float_t)jkey->GetObjlen()/1024./1024.,(Float_t)jkey->GetNbytes()/1024./1024.);
435         }
436       }
437     }
438   }
439   Printf("Total %5.2f MB %5.2f MB",memorySize,diskSize);
440   return kTRUE;
441 }
442
443
444 Bool_t  AliAnalysisHelperJetTasks::Selected(Bool_t bSet,Bool_t bNew){
445   static Bool_t bSelected = kTRUE; // if service task is not run we acccpet all
446   if(bSet){
447     bSelected = bNew;
448   }
449   return bSelected;
450 }
451
452 Bool_t  AliAnalysisHelperJetTasks::IsCosmic(){
453   return ((SelectInfo()&kIsCosmic)==kIsCosmic);
454 }
455
456 Bool_t  AliAnalysisHelperJetTasks::IsPileUp(){
457   return ((SelectInfo()&kIsPileUp)==kIsPileUp);
458 }
459
460
461 Bool_t  AliAnalysisHelperJetTasks::TestSelectInfo(UInt_t iMask){
462   return ((SelectInfo()&iMask)==iMask);
463 }
464
465
466 UInt_t  AliAnalysisHelperJetTasks::SelectInfo(Bool_t bSet,UInt_t iNew){
467   static UInt_t iSelectInfo = 0; //
468   if(bSet){
469     iSelectInfo = iNew;
470   }
471   return iSelectInfo;
472 }
473
474
475 //___________________________________________________________________________________________________________
476
477 Bool_t AliAnalysisHelperJetTasks::GetEventShapes(TVector3 &n01, TVector3 * pTrack, Int_t nTracks, Double_t * eventShapes)
478 {       
479   // ***
480   // Event shape calculation
481   // sona.pochybova@cern.ch
482
483   const Int_t kTracks = 1000;
484   if(nTracks>kTracks)return kFALSE;
485
486   //variables for thrust calculation
487   TVector3 pTrackPerp[kTracks];
488   Double_t psum2 = 0;
489
490   TVector3 psum;
491   TVector3 psum02;
492   TVector3 psum03;
493
494   Double_t psum1 = 0;
495   Double_t psum102 = 0;
496   Double_t psum103 = 0;
497
498   Double_t thrust[kTracks];
499   Double_t th = -3;
500   Double_t thrust02[kTracks];
501   Double_t th02 = -4;
502   Double_t thrust03[kTracks];
503   Double_t th03 = -5;
504
505   //Sphericity calculation variables
506   TMatrixDSym m(3);
507   Double_t s00 = 0;
508   Double_t s01 = 0;
509   Double_t s02 = 0;
510   
511   Double_t s10 = 0;
512   Double_t s11 = 0;
513   Double_t s12 = 0;
514   
515   Double_t s20 = 0;
516   Double_t s21 = 0;
517   Double_t s22 = 0;
518   
519   Double_t ptot = 0;
520   
521   Double_t c = -10;
522
523 //
524 //loop for thrust calculation  
525 //
526     
527   for(Int_t i = 0; i < nTracks; i++)
528     {
529       pTrackPerp[i].SetXYZ(pTrack[i].X(), pTrack[i].Y(), 0);
530       psum2 += pTrackPerp[i].Mag();
531     }
532
533   //additional starting axis    
534   TVector3 n02;
535   n02 = pTrack[1].Unit();
536   n02.SetZ(0.);   
537   TVector3 n03;
538   n03 = pTrack[2].Unit();
539   n03.SetZ(0.);
540
541   //switches for calculating thrust for different starting points
542   Int_t switch1 = 1;
543   Int_t switch2 = 1;
544   Int_t switch3 = 1;
545
546   //indexes for iteration of different starting points
547   Int_t l1 = 0;
548   Int_t l2 = 0;
549   Int_t l3 = 0;
550
551   //maximal number of iterations
552   //  Int_t nMaxIter = 100;
553  
554   for(Int_t k = 0; k < nTracks; k++)
555     {  
556       
557       if(switch1 == 1){
558         psum.SetXYZ(0., 0., 0.);
559         psum1 = 0;
560         for(Int_t i = 0; i < nTracks; i++)
561           {
562             psum1 += (TMath::Abs(n01.Dot(pTrackPerp[i])));
563             if (n01.Dot(pTrackPerp[i]) > 0) psum += pTrackPerp[i];
564             if (n01.Dot(pTrackPerp[i]) < 0) psum -= pTrackPerp[i];
565           }
566         thrust[l1] = psum1/psum2;
567       }
568
569       if(switch2 == 1){
570         psum02.SetXYZ(0., 0., 0.);
571         psum102 = 0;
572         for(Int_t i = 0; i < nTracks; i++)
573           {
574             psum102 += (TMath::Abs(n02.Dot(pTrackPerp[i])));
575             if (n02.Dot(pTrackPerp[i]) > 0) psum02 += pTrackPerp[i];
576             if (n02.Dot(pTrackPerp[i]) < 0) psum02 -= pTrackPerp[i];
577           }
578         thrust02[l2] = psum102/psum2;
579       }
580       
581       if(switch3 == 1){
582         psum03.SetXYZ(0., 0., 0.);
583         psum103 = 0;
584         for(Int_t i = 0; i < nTracks; i++)
585           {
586             psum103 += (TMath::Abs(n03.Dot(pTrackPerp[i])));
587             if (n03.Dot(pTrackPerp[i]) > 0) psum03 += pTrackPerp[i];
588             if (n03.Dot(pTrackPerp[i]) < 0) psum03 -= pTrackPerp[i];
589           }
590         thrust03[l3] = psum103/psum2;
591       }
592
593       //check whether thrust value converged    
594       if(TMath::Abs(th-thrust[l1]) < 10e-7){
595         switch1 = 0;
596       }
597       
598       if(TMath::Abs(th02-thrust02[l2]) < 10e-7){
599         switch2 = 0;
600       }
601
602       if(TMath::Abs(th03-thrust03[l3]) < 10e-7){
603         switch3 = 0;
604       }
605
606       //if it didn't, continue with the calculation
607       if(switch1 == 1){
608         th = thrust[l1]; 
609         n01 = psum.Unit();
610         l1++;
611       }
612
613       if(switch2 == 1){
614         th02 = thrust02[l2];
615         n02 = psum02.Unit();
616         l2++;
617       }
618
619       if(switch3 == 1){
620         th03 = thrust03[l3];
621         n03 = psum03.Unit();
622         l3++;
623       }
624
625       //if thrust values for all starting direction converged check if to the same value
626       if(switch2 == 0 && switch1 == 0 && switch3 == 0){
627         if(TMath::Abs(th-th02) < 10e-7 && TMath::Abs(th-th03) < 10e-7 && TMath::Abs(th02-th03) < 10e-7){
628           eventShapes[0] = th;
629           AliInfoGeneral(Form(" %s:%d",(char*)__FILE__,__LINE__),Form("===== THRUST VALUE FOUND AT %d :: %f\n", k, th));
630           break;
631         }
632         //if they did not, reset switches
633         else{
634           switch1 = 1;
635           //      th = -1.;
636           switch2 = 1;
637           //      th02 = -2.;
638           switch3 = 1;
639           //      th03 = -4.;
640         }
641       }
642
643       //      Printf("========== %d +++ th :: %f=============\n", l1, th);
644       //      Printf("========== %d +++ th2 :: %f=============\n", l2, th02);
645       //      Printf("========== %d +++ th3 :: %f=============\n", l3, th03);
646       
647     }
648
649   //if no common limitng value was found, take the maximum and take the corresponding thrust axis
650   if(switch1 == 1 && switch2 == 1 && switch3 == 1){
651     eventShapes[0] = TMath::Max(thrust[l1-1], thrust02[l2-1]);
652     eventShapes[0] = TMath::Max(eventShapes[0], thrust03[l3-1]);
653     if(TMath::Abs(eventShapes[0]-thrust[l1-1]) < 10e-7)
654       n01 = n01;
655     if(TMath::Abs(eventShapes[0]-thrust02[l2-1]) < 10e-7)
656       n01 = n02;
657     if(TMath::Abs(eventShapes[0]-thrust03[l3-1]) < 10e-7)
658       n01 = n03;
659     Printf("NO LIMITING VALUE FOUND :: MAXIMUM = %f\n", eventShapes[0]);
660   }
661
662 //
663 //other event shapes variables
664 //
665   for(Int_t j = 0; j < nTracks; j++)
666     {  
667       s00 = s00 + (pTrack[j].Px()*pTrack[j].Px())/pTrack[j].Mag();
668       s01 = s01 + (pTrack[j].Px()*pTrack[j].Py())/pTrack[j].Mag();
669       s02 = s02 + (pTrack[j].Px()*pTrack[j].Pz())/pTrack[j].Mag();
670       
671       s10 = s10 + (pTrack[j].Py()*pTrack[j].Px())/pTrack[j].Mag();
672       s11 = s11 + (pTrack[j].Py()*pTrack[j].Py())/pTrack[j].Mag();
673       s12 = s12 + (pTrack[j].Py()*pTrack[j].Pz())/pTrack[j].Mag();
674       
675       s20 = s20 + (pTrack[j].Pz()*pTrack[j].Px())/pTrack[j].Mag();
676       s21 = s21 + (pTrack[j].Pz()*pTrack[j].Py())/pTrack[j].Mag();
677       s22 = s22 + (pTrack[j].Pz()*pTrack[j].Pz())/pTrack[j].Mag();
678       
679       ptot += pTrack[j].Mag();
680     }
681
682   if(ptot > 0.)
683     {
684       m(0,0) = s00/ptot;
685       m(0,1) = s01/ptot;
686       m(0,2) = s02/ptot;
687
688       m(1,0) = s10/ptot;
689       m(1,1) = s11/ptot;
690       m(1,2) = s12/ptot;
691
692       m(2,0) = s20/ptot;
693       m(2,1) = s21/ptot;
694       m(2,2) = s22/ptot;
695
696       TMatrixDSymEigen eigen(m);
697       TVectorD eigenVal = eigen.GetEigenValues();
698
699       Double_t sphericity = (3/2)*(eigenVal(2)+eigenVal(1));
700       eventShapes[1] = sphericity;
701
702       Double_t aplanarity = (3/2)*(eigenVal(2));
703       eventShapes[2] = aplanarity;
704
705       c = 3*(eigenVal(0)*eigenVal(1)+eigenVal(0)*eigenVal(2)+eigenVal(1)*eigenVal(2));
706       eventShapes[3] = c;
707     }
708   return kTRUE;
709 }
710   
711
712
713  //__________________________________________________________________________________________________________________________
714 // Trigger Decisions copid from PWG0/AliTriggerAnalysis
715
716
717 Bool_t AliAnalysisHelperJetTasks::IsTriggerFired(const AliVEvent* aEv, Trigger trigger)
718 {
719   // checks if an event has been triggered
720   // no usage of ofline trigger here yet
721   
722   // here we do a dirty hack to take also into account the
723   // missing trigger bits and Bunch crossing paatern for real data 
724
725
726   if(aEv->InheritsFrom("AliESDEvent")){
727     const AliESDEvent *esd = (AliESDEvent*)aEv;
728     switch (trigger)
729       {
730       case kAcceptAll:
731         {
732           return kTRUE;
733           break;
734         }
735       case kMB1:
736         {
737           if(esd->GetFiredTriggerClasses().Contains("CINT1B-"))return kTRUE;
738           // does the same but without or'ed V0s
739           if(esd->GetFiredTriggerClasses().Contains("CSMBB"))return kTRUE;  
740           if(esd->GetFiredTriggerClasses().Contains("CINT6B-"))return kTRUE; 
741           // this is for simulated data
742           if(esd->GetFiredTriggerClasses().Contains("MB1"))return kTRUE;   
743           break;
744         }
745       case kMB2:
746         {
747           if(esd->GetFiredTriggerClasses().Contains("MB2"))return kTRUE;   
748           break;
749         }
750       case kMB3:
751         {
752           if(esd->GetFiredTriggerClasses().Contains("MB3"))return kTRUE;   
753           break;
754         }
755       case kSPDGFO:
756         {
757           if(esd->GetFiredTriggerClasses().Contains("CSMBB"))return kTRUE;
758           if(esd->GetFiredTriggerClasses().Contains("CINT6B-"))return kTRUE; 
759           if(esd->GetFiredTriggerClasses().Contains("GFO"))return kTRUE;
760           break;
761         }
762       default:
763         {
764           Printf("IsEventTriggered: ERROR: Trigger type %d not implemented in this method", (Int_t) trigger);
765           break;
766         }
767       }
768   }
769   else if(aEv->InheritsFrom("AliAODEvent")){
770     const AliAODEvent *aod = (AliAODEvent*)aEv;
771     switch (trigger)
772       {
773       case kAcceptAll:
774         {
775           return kTRUE;
776           break;
777         }
778       case kMB1:
779         {
780           if(aod->GetFiredTriggerClasses().Contains("CINT1B"))return kTRUE;
781           // does the same but without or'ed V0s
782           if(aod->GetFiredTriggerClasses().Contains("CSMBB"))return kTRUE;   
783           // for sim data
784           if(aod->GetFiredTriggerClasses().Contains("MB1"))return kTRUE;   
785           break;
786         }
787       case kMB2:
788         {
789           if(aod->GetFiredTriggerClasses().Contains("MB2"))return kTRUE;   
790           break;
791         }
792       case kMB3:
793         {
794           if(aod->GetFiredTriggerClasses().Contains("MB3"))return kTRUE;   
795           break;
796         }
797       case kSPDGFO:
798         {
799           if(aod->GetFiredTriggerClasses().Contains("CSMBB"))return kTRUE;        
800           if(aod->GetFiredTriggerClasses().Contains("GFO"))return kTRUE;   
801           break;
802         }
803       default:
804         {
805           Printf("IsEventTriggered: ERROR: Trigger type %d not implemented in this method", (Int_t) trigger);
806           break;
807         }
808       }
809   }
810     return kFALSE;
811 }
812
813
814  AliAnalysisHelperJetTasks::MCProcessType  AliAnalysisHelperJetTasks::GetPythiaEventProcessType(AliGenEventHeader* aHeader, Bool_t adebug) {
815
816   AliGenPythiaEventHeader* pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(aHeader);
817
818   if (!pythiaGenHeader) {
819     //    printf(" AliAnalysisHelperJetTasks::GetProcessType : Unknown gen Header type). \n");
820     return kInvalidProcess;
821   }
822
823
824   Int_t pythiaType = pythiaGenHeader->ProcessType();
825   fgLastProcessType = pythiaType;
826   MCProcessType globalType = kInvalidProcess;  
827
828
829   if (adebug) {
830     printf(" AliAnalysisHelperJetTasks::GetProcessType : Pythia process type found: %d \n",pythiaType);
831   }
832
833
834   if(pythiaType==92||pythiaType==93){
835     globalType = kSD;
836   }
837   else if(pythiaType==94){
838     globalType = kDD;
839   }
840   //else if(pythiaType != 91){ // also exclude elastic to be sure... CKB??
841   else {
842     globalType = kND;
843   }
844   return globalType;
845 }
846
847
848  AliAnalysisHelperJetTasks::MCProcessType  AliAnalysisHelperJetTasks::GetDPMjetEventProcessType(AliGenEventHeader* aHeader, Bool_t adebug) {
849   //
850   // get the process type of the event.
851   //
852
853   // can only read pythia headers, either directly or from cocktalil header
854   AliGenDPMjetEventHeader* dpmJetGenHeader = dynamic_cast<AliGenDPMjetEventHeader*>(aHeader);
855
856   if (!dpmJetGenHeader) {
857     printf(" AliAnalysisHelperJetTasks::GetDPMjetProcessType : Unknown header type (not DPMjet or). \n");
858     return kInvalidProcess;
859   }
860
861   Int_t dpmJetType = dpmJetGenHeader->ProcessType();
862   fgLastProcessType = dpmJetType;
863   MCProcessType globalType = kInvalidProcess;  
864
865
866   if (adebug) {
867     printf(" AliAnalysisHelperJetTasks::GetDPMJetProcessType : DPMJet process type found: %d \n",dpmJetType);
868   }
869
870
871   if (dpmJetType == 1 || dpmJetType == 4) { // explicitly inelastic plus central diffraction
872     globalType = kND;
873   }  
874   else if (dpmJetType==5 || dpmJetType==6) {
875     globalType = kSD;
876   }
877   else if (dpmJetType==7) {
878     globalType = kDD;
879   }
880   return globalType;
881 }
882