]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGDQ/dielectron/AliDielectron.cxx
Add INT1 and the TRD triggers S masks to the OADB for LHC13g
[u/mrichter/AliRoot.git] / PWGDQ / dielectron / AliDielectron.cxx
1 /*************************************************************************
2 * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
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 **************************************************************************/
15
16 ///////////////////////////////////////////////////////////////////////////
17 //                Dielectron Analysis Main class                         //
18 //                                                                       //
19 /*
20 Framework to perform event selectoin, single track selection and track pair
21 selection.
22
23 Convention for the signs of the pair in fPairCandidates:
24 The names are available via the function PairClassName(Int_t i)
25
26 0: ev1+ ev1+  (same event like sign +)
27 1: ev1+ ev1-  (same event unlike sign)
28 2: ev1- ev1-  (same event like sign -)
29
30 3: ev1+ ev2+  (mixed event like sign +)
31 4: ev1- ev2+  (mixed event unlike sign -+)
32 6: ev1+ ev2-  (mixed event unlike sign +-)
33 7: ev1- ev2-  (mixed event like sign -)
34
35 5: ev2+ ev2+  (same event like sign +)
36 8: ev2+ ev2-  (same event unlike sign)
37 9: ev2- ev2-  (same event like sign -)
38
39 10: ev1+ ev1- (same event track rotation)
40
41 */
42 //                                                                       //
43 ///////////////////////////////////////////////////////////////////////////
44
45 #include <TString.h>
46 #include <TList.h>
47 #include <TMath.h>
48 #include <TObject.h>
49
50 #include <AliKFParticle.h>
51
52 #include <AliEventplane.h>
53 #include <AliVEvent.h>
54 #include <AliVParticle.h>
55 #include <AliVTrack.h>
56 #include "AliDielectronPair.h"
57 #include "AliDielectronHistos.h"
58 #include "AliDielectronCF.h"
59 #include "AliDielectronMC.h"
60 #include "AliDielectronVarManager.h"
61 #include "AliDielectronTrackRotator.h"
62 #include "AliDielectronDebugTree.h"
63 #include "AliDielectronSignalMC.h"
64 #include "AliDielectronMixingHandler.h"
65
66 #include "AliDielectron.h"
67
68 ClassImp(AliDielectron)
69
70 const char* AliDielectron::fgkTrackClassNames[4] = {
71   "ev1+",
72   "ev1-",
73   "ev2+",
74   "ev2-"
75 };
76
77 const char* AliDielectron::fgkPairClassNames[11] = {
78   "ev1+_ev1+",
79   "ev1+_ev1-",
80   "ev1-_ev1-",
81   "ev1+_ev2+",
82   "ev1-_ev2+",
83   "ev2+_ev2+",
84   "ev1+_ev2-",
85   "ev1-_ev2-",
86   "ev2+_ev2-",
87   "ev2-_ev2-",
88   "ev1+_ev1-_TR"
89 };
90
91 //________________________________________________________________
92 AliDielectron::AliDielectron() :
93   TNamed("AliDielectron","AliDielectron"),
94   fEventFilter("EventFilter"),
95   fTrackFilter("TrackFilter"),
96   fPairPreFilter("PairPreFilter"),
97   fPairPreFilterLegs("PairPreFilterLegs"),
98   fPairFilter("PairFilter"),
99   fEventPlanePreFilter("EventPlanePreFilter"),
100   fEventPlanePOIPreFilter("EventPlanePOIPreFilter"),
101   fPdgMother(443),
102   fPdgLeg1(11),
103   fPdgLeg2(11),
104   fSignalsMC(0x0),
105   fNoPairing(kFALSE),
106   fUseKF(kTRUE),
107   fHistoArray(0x0),
108   fHistos(0x0),
109   fPairCandidates(new TObjArray(11)),
110   fCfManagerPair(0x0),
111   fTrackRotator(0x0),
112   fDebugTree(0x0),
113   fMixing(0x0),
114   fPreFilterEventPlane(kFALSE),
115   fLikeSignSubEvents(kFALSE),
116   fPreFilterUnlikeOnly(kFALSE),
117   fPreFilterAllSigns(kFALSE),
118   fHasMC(kFALSE),
119   fStoreRotatedPairs(kFALSE),
120   fDontClearArrays(kFALSE),
121   fEstimatorFilename(""),
122   fTRDpidCorrectionFilename(""),
123   fVZEROCalibrationFilename(""),
124   fVZERORecenteringFilename("")
125 {
126   //
127   // Default constructor
128   //
129
130 }
131
132 //________________________________________________________________
133 AliDielectron::AliDielectron(const char* name, const char* title) :
134   TNamed(name,title),
135   fEventFilter("EventFilter"),
136   fTrackFilter("TrackFilter"),
137   fPairPreFilter("PairPreFilter"),
138   fPairPreFilterLegs("PairPreFilterLegs"),
139   fPairFilter("PairFilter"),
140   fEventPlanePreFilter("EventPlanePreFilter"),
141   fEventPlanePOIPreFilter("EventPlanePOIPreFilter"),
142   fPdgMother(443),
143   fPdgLeg1(11),
144   fPdgLeg2(11),
145   fSignalsMC(0x0),
146   fNoPairing(kFALSE),
147   fUseKF(kTRUE),
148   fHistoArray(0x0),
149   fHistos(0x0),
150   fPairCandidates(new TObjArray(11)),
151   fCfManagerPair(0x0),
152   fTrackRotator(0x0),
153   fDebugTree(0x0),
154   fMixing(0x0),
155   fPreFilterEventPlane(kFALSE),
156   fLikeSignSubEvents(kFALSE),
157   fPreFilterUnlikeOnly(kFALSE),
158   fPreFilterAllSigns(kFALSE),
159   fHasMC(kFALSE),
160   fStoreRotatedPairs(kFALSE),
161   fDontClearArrays(kFALSE),
162   fEstimatorFilename(""),
163   fTRDpidCorrectionFilename(""),
164   fVZEROCalibrationFilename(""),
165   fVZERORecenteringFilename("")
166 {
167   //
168   // Named constructor
169   //
170   
171 }
172
173 //________________________________________________________________
174 AliDielectron::~AliDielectron()
175 {
176   //
177   // Default destructor
178   //
179   if (fHistoArray) delete fHistoArray;
180   if (fHistos) delete fHistos;
181   if (fPairCandidates) delete fPairCandidates;
182   if (fDebugTree) delete fDebugTree;
183   if (fMixing) delete fMixing;
184   if (fSignalsMC) delete fSignalsMC;
185   if (fCfManagerPair) delete fCfManagerPair;
186 }
187
188 //________________________________________________________________
189 void AliDielectron::Init()
190 {
191   //
192   // Initialise objects
193   //
194
195   if(GetHasMC()) AliDielectronMC::Instance()->SetHasMC(GetHasMC());
196    
197   InitPairCandidateArrays();
198    
199   if (fCfManagerPair) {
200     fCfManagerPair->SetSignalsMC(fSignalsMC);
201     fCfManagerPair->InitialiseContainer(fPairFilter);
202   }
203   if (fTrackRotator)  {
204     fTrackRotator->SetTrackArrays(&fTracks[0],&fTracks[1]);
205     fTrackRotator->SetPdgLegs(fPdgLeg1,fPdgLeg2);
206   }
207   if (fDebugTree) fDebugTree->SetDielectron(this);
208   if(fEstimatorFilename.Contains(".root")) AliDielectronVarManager::InitEstimatorAvg(fEstimatorFilename.Data());
209   if(fTRDpidCorrectionFilename.Contains(".root")) AliDielectronVarManager::InitTRDpidEffHistograms(fTRDpidCorrectionFilename.Data());
210   if(fVZEROCalibrationFilename.Contains(".root")) AliDielectronVarManager::SetVZEROCalibrationFile(fVZEROCalibrationFilename.Data());
211   if(fVZERORecenteringFilename.Contains(".root")) AliDielectronVarManager::SetVZERORecenteringFile(fVZERORecenteringFilename.Data());
212   
213   if (fMixing) fMixing->Init(this);
214   if (fHistoArray) {
215     fHistoArray->SetSignalsMC(fSignalsMC);
216     fHistoArray->Init();
217   }
218
219
220 //________________________________________________________________
221 void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
222 {
223   //
224   // Process the events
225   //
226
227   //at least first event is needed!
228   if (!ev1){
229     AliError("At least first event must be set!");
230     return;
231   }
232
233   //in case we have MC load the MC event and process the MC particles
234   if (AliDielectronMC::Instance()->ConnectMCEvent()){
235     ProcessMC(ev1);
236   }
237
238   //if candidate array doesn't exist, create it
239   if (!fPairCandidates->UncheckedAt(0)) {
240     InitPairCandidateArrays();
241   } else {
242     ClearArrays();
243   }
244
245   //mask used to require that all cuts are fulfilled
246   UInt_t selectedMask=(1<<fEventFilter.GetCuts()->GetEntries())-1;
247
248   //apply event cuts
249     if ((ev1&&fEventFilter.IsSelected(ev1)!=selectedMask) ||
250         (ev2&&fEventFilter.IsSelected(ev2)!=selectedMask)) return;
251
252   //fill track arrays for the first event
253   if (ev1){
254     FillTrackArrays(ev1);
255     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(0, 1, fTracks[0], fTracks[1]);
256   }
257
258
259   //fill track arrays for the second event
260   if (ev2) {
261     FillTrackArrays(ev2,1);
262     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(2, 3, fTracks[2], fTracks[3]);
263   }
264
265   // TPC event plane correction
266   AliEventplane *cevplane = new AliEventplane();
267   if (ev1 && cevplane && fPreFilterEventPlane && ( fEventPlanePreFilter.GetCuts()->GetEntries()>0 || fEventPlanePOIPreFilter.GetCuts()->GetEntries()>0)) 
268     EventPlanePreFilter(0, 1, fTracks[0], fTracks[1], ev1, cevplane);
269
270   // set event
271   AliDielectronVarManager::SetEvent(ev1);
272   if (fMixing){
273     //set mixing bin to event data
274     Int_t bin=fMixing->FindBin(AliDielectronVarManager::GetData());
275     AliDielectronVarManager::SetValue(AliDielectronVarManager::kMixingBin,bin);
276   }
277
278   if (!fNoPairing){
279     // create pairs and fill pair candidate arrays
280     for (Int_t itrackArr1=0; itrackArr1<4; ++itrackArr1){
281       for (Int_t itrackArr2=itrackArr1; itrackArr2<4; ++itrackArr2){
282         FillPairArrays(itrackArr1, itrackArr2);
283       }
284     }
285
286     //track rotation
287     if (fTrackRotator) {
288       fTrackRotator->SetEvent(ev1);
289       FillPairArrayTR();
290     }
291   }
292
293   //fill debug tree if a manager is attached
294   if (fDebugTree) FillDebugTree();
295
296   //process event mixing
297   if (fMixing) {
298     fMixing->Fill(ev1,this);
299     //     FillHistograms(0x0,kTRUE);
300   }
301
302   //in case there is a histogram manager, fill the QA histograms
303   if (fHistos && fSignalsMC) FillMCHistograms(ev1);
304   if (fHistos) FillHistograms(ev1);
305
306
307   // clear arrays
308   if (!fDontClearArrays) ClearArrays();
309   AliDielectronVarManager::SetTPCEventPlane(0x0);
310   delete cevplane;
311 }
312
313 //________________________________________________________________
314 void AliDielectron::ProcessMC(AliVEvent *ev1)
315 {
316   //
317   // Process the MC data
318   //
319
320   AliDielectronMC *dieMC=AliDielectronMC::Instance();
321
322   if (fHistos) FillHistogramsMC(dieMC->GetMCEvent(), ev1);
323
324   if(!fSignalsMC) return;
325   //loop over all MC data and Fill the CF container if it exist
326   if (!fCfManagerPair && !fHistoArray) return;
327   if(fCfManagerPair) fCfManagerPair->SetPdgMother(fPdgMother);
328
329   Bool_t bFillCF = (fCfManagerPair ? fCfManagerPair->GetStepForMCtruth()  : kFALSE);
330   Bool_t bFillHF = (fHistoArray    ? fHistoArray->GetStepForMCGenerated() : kFALSE);
331   if(!bFillCF && !bFillHF) return;
332
333   // signals to be studied
334   Int_t nSignals = fSignalsMC->GetEntries();
335
336   // initialize 2D arrays of labels for particles from each MC signal
337   Int_t** labels1;      // labels for particles satisfying branch 1
338   Int_t** labels2;      // labels for particles satisfying branch 2
339   Int_t** labels12;     // labels for particles satisfying both branches
340   labels1 = new Int_t*[nSignals];
341   labels2 = new Int_t*[nSignals];
342   labels12 = new Int_t*[nSignals];
343   Int_t* indexes1=new Int_t[nSignals];
344   Int_t* indexes2=new Int_t[nSignals];
345   Int_t* indexes12=new Int_t[nSignals];
346   for(Int_t isig=0;isig<nSignals;++isig) {
347     *(labels1+isig) = new Int_t[dieMC->GetNMCTracks()];
348     *(labels2+isig) = new Int_t[dieMC->GetNMCTracks()];
349     *(labels12+isig) = new Int_t[dieMC->GetNMCTracks()];
350     for(Int_t ip=0; ip<dieMC->GetNMCTracks();++ip) {
351       labels1[isig][ip] = -1;
352       labels2[isig][ip] = -1;
353       labels12[isig][ip] = -1;
354     }
355     indexes1[isig]=0;
356     indexes2[isig]=0;
357     indexes12[isig]=0;
358   }
359
360   Bool_t truth1=kFALSE;
361   Bool_t truth2=kFALSE;
362   // loop over the MC tracks
363   for(Int_t ipart=0; ipart<dieMC->GetNMCTracks(); ++ipart) {
364     for(Int_t isig=0; isig<nSignals; ++isig) {       // loop over signals
365       // Proceed only if this signal is required in the pure MC step
366       // NOTE: Some signals can be satisfied by many particles and this leads to high
367       //       computation times (e.g. secondary electrons from the GEANT transport). Be aware of this!!
368       if(!((AliDielectronSignalMC*)fSignalsMC->At(isig))->GetFillPureMCStep()) continue;
369
370       truth1 = dieMC->IsMCTruth(ipart, (AliDielectronSignalMC*)fSignalsMC->At(isig), 1);
371       truth2 = dieMC->IsMCTruth(ipart, (AliDielectronSignalMC*)fSignalsMC->At(isig), 2);
372
373       // particles satisfying both branches are treated separately to avoid double counting during pairing
374       if(truth1 && truth2) {
375         labels12[isig][indexes12[isig]] = ipart;
376         ++indexes12[isig];
377       }
378       else {
379         if(truth1) {
380           labels1[isig][indexes1[isig]] = ipart;
381           ++indexes1[isig];
382         }
383         if(truth2) {
384           labels2[isig][indexes2[isig]] = ipart;
385           ++indexes2[isig];
386         }
387       }
388     }
389   }  // end loop over MC particles
390
391   // Do the pairing and fill the CF container with pure MC info
392   for(Int_t isig=0; isig<nSignals; ++isig) {
393     // mix the particles which satisfy only one of the signal branches
394     for(Int_t i1=0;i1<indexes1[isig];++i1) {
395       for(Int_t i2=0;i2<indexes2[isig];++i2) {
396         if(bFillCF) fCfManagerPair->FillMC(labels1[isig][i1], labels2[isig][i2], isig);
397         if(bFillHF) fHistoArray->Fill(labels1[isig][i1], labels2[isig][i2], isig);
398       }
399     }
400     // mix the particles which satisfy both branches
401     for(Int_t i1=0;i1<indexes12[isig];++i1) {
402       for(Int_t i2=0; i2<i1; ++i2) {
403         if(bFillCF) fCfManagerPair->FillMC(labels12[isig][i1], labels12[isig][i2], isig);
404         if(bFillHF) fHistoArray->Fill(labels12[isig][i1], labels12[isig][i2], isig);
405       }
406     }
407   }    // end loop over signals
408
409   // release the memory
410   for(Int_t isig=0;isig<nSignals;++isig) {
411     delete [] *(labels1+isig);
412     delete [] *(labels2+isig);
413     delete [] *(labels12+isig);
414   }
415   delete [] labels1;
416   delete [] labels2;
417   delete [] labels12;
418   delete [] indexes1;
419   delete [] indexes2;
420   delete [] indexes12;
421 }
422
423 //________________________________________________________________
424 void AliDielectron::FillHistogramsTracks(TObjArray **tracks)
425 {
426   //
427   // Fill Histogram information for tracks after prefilter
428   // ignore mixed events - for prefilter, only single tracks +/- are relevant 
429   //
430   
431   TString  className,className2;
432   Double_t values[AliDielectronVarManager::kNMaxValues];
433   
434   //Fill track information, separately for the track array candidates
435   for (Int_t i=0; i<2; ++i){
436     className.Form("Pre_%s",fgkTrackClassNames[i]);
437     if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
438     Int_t ntracks=tracks[i]->GetEntriesFast();
439     for (Int_t itrack=0; itrack<ntracks; ++itrack){
440       AliDielectronVarManager::Fill(tracks[i]->UncheckedAt(itrack), values);
441       fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
442     }
443   }
444 }
445
446
447 //________________________________________________________________
448 void AliDielectron::FillHistogramsMC(const AliMCEvent *ev, AliVEvent *ev1)
449 {
450   //
451   // Fill Histogram information for MCEvents
452   //
453
454   Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
455   // Fill event information
456   AliDielectronVarManager::Fill(ev1, values);    // ESD/AOD information
457   AliDielectronVarManager::Fill(ev, values);     // MC truth info
458   if (fHistos->GetHistogramList()->FindObject("MCEvent"))
459     fHistos->FillClass("MCEvent", AliDielectronVarManager::kNMaxValues, values);
460 }
461
462
463 //________________________________________________________________
464 void AliDielectron::FillHistograms(const AliVEvent *ev, Bool_t pairInfoOnly)
465 {
466   //
467   // Fill Histogram information for tracks and pairs
468   //
469   
470   TString  className,className2;
471   Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
472
473   //Fill event information
474   if (ev){
475     if (fHistos->GetHistogramList()->FindObject("Event"))
476       fHistos->FillClass("Event", AliDielectronVarManager::kNMaxValues, AliDielectronVarManager::GetData());
477   }
478
479   //Fill track information, separately for the track array candidates
480   if (!pairInfoOnly){
481     for (Int_t i=0; i<4; ++i){
482       className.Form("Track_%s",fgkTrackClassNames[i]);
483       if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
484       Int_t ntracks=fTracks[i].GetEntriesFast();
485       for (Int_t itrack=0; itrack<ntracks; ++itrack){
486         AliDielectronVarManager::Fill(fTracks[i].UncheckedAt(itrack), values);
487         fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
488       }
489     }
490   }
491
492   //Fill Pair information, separately for all pair candidate arrays and the legs
493   TObjArray arrLegs(100);
494   for (Int_t i=0; i<10; ++i){
495     className.Form("Pair_%s",fgkPairClassNames[i]);
496     className2.Form("Track_Legs_%s",fgkPairClassNames[i]);
497     Bool_t pairClass=fHistos->GetHistogramList()->FindObject(className.Data())!=0x0;
498     Bool_t legClass=fHistos->GetHistogramList()->FindObject(className2.Data())!=0x0;
499     if (!pairClass&&!legClass) continue;
500     Int_t ntracks=PairArray(i)->GetEntriesFast();
501     for (Int_t ipair=0; ipair<ntracks; ++ipair){
502       AliDielectronPair *pair=static_cast<AliDielectronPair*>(PairArray(i)->UncheckedAt(ipair));
503       
504       //fill pair information
505       if (pairClass){
506         AliDielectronVarManager::Fill(pair, values);
507         fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
508       }
509
510       //fill leg information, don't fill the information twice
511       if (legClass){
512         AliVParticle *d1=pair->GetFirstDaughter();
513         AliVParticle *d2=pair->GetSecondDaughter();
514         if (!arrLegs.FindObject(d1)){
515           AliDielectronVarManager::Fill(d1, values);
516           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
517           arrLegs.Add(d1);
518         }
519         if (!arrLegs.FindObject(d2)){
520           AliDielectronVarManager::Fill(d2, values);
521           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
522           arrLegs.Add(d2);
523         }
524       }
525     }
526     if (legClass) arrLegs.Clear();
527   }
528   
529 }
530 //________________________________________________________________
531 void AliDielectron::FillHistogramsPair(AliDielectronPair *pair,Bool_t fromPreFilter/*=kFALSE*/)
532 {
533   //
534   // Fill Histogram information for pairs and the track in the pair
535   // NOTE: in this funtion the leg information may be filled multiple
536   //       times. This funtion is used in the track rotation pairing
537   //       and those legs are not saved!
538   //
539   TString  className,className2;
540   Double_t values[AliDielectronVarManager::kNMaxValues];
541   
542   //Fill Pair information, separately for all pair candidate arrays and the legs
543   TObjArray arrLegs(100);
544   const Int_t type=pair->GetType();
545   if (fromPreFilter) {
546     className.Form("RejPair_%s",fgkPairClassNames[type]);
547     className2.Form("RejTrack_%s",fgkPairClassNames[type]);
548   } else {
549     className.Form("Pair_%s",fgkPairClassNames[type]);
550     className2.Form("Track_Legs_%s",fgkPairClassNames[type]);
551   }
552   
553   Bool_t pairClass=fHistos->GetHistogramList()->FindObject(className.Data())!=0x0;
554   Bool_t legClass=fHistos->GetHistogramList()->FindObject(className2.Data())!=0x0;
555   
556   //fill pair information
557   if (pairClass){
558     AliDielectronVarManager::Fill(pair, values);
559     fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
560   }
561
562   if (legClass){
563     AliVParticle *d1=pair->GetFirstDaughter();
564     AliDielectronVarManager::Fill(d1, values);
565     fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
566     
567     AliVParticle *d2=pair->GetSecondDaughter();
568     AliDielectronVarManager::Fill(d2, values);
569     fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
570   }
571 }
572
573 //________________________________________________________________
574 void AliDielectron::FillTrackArrays(AliVEvent * const ev, Int_t eventNr)
575 {
576   //
577   // select tracks and fill track candidate arrays
578   // eventNr = 0: First  event, use track arrays 0 and 1
579   // eventNr = 1: Second event, use track arrays 2 and 3
580   //
581
582   Int_t ntracks=ev->GetNumberOfTracks();
583
584   UInt_t selectedMask=(1<<fTrackFilter.GetCuts()->GetEntries())-1;
585   for (Int_t itrack=0; itrack<ntracks; ++itrack){
586     //get particle
587     AliVParticle *particle=ev->GetTrack(itrack);
588
589     //apply track cuts
590     if (fTrackFilter.IsSelected(particle)!=selectedMask) continue;
591
592     //fill selected particle into the corresponding track arrays
593     Short_t charge=particle->Charge();
594     if (charge>0)      fTracks[eventNr*2].Add(particle);
595     else if (charge<0) fTracks[eventNr*2+1].Add(particle);
596   }
597 }
598
599 //________________________________________________________________
600 void AliDielectron::EventPlanePreFilter(Int_t arr1, Int_t arr2, TObjArray arrTracks1, TObjArray arrTracks2, const AliVEvent *ev, AliEventplane *cevplane)
601 {
602   //
603   // Prefilter tracks and tracks from pairs
604   // Needed for rejection in the Q-Vector of the event plane
605   // remove contribution of all tracks to the Q-vector that are in invariant mass window 
606   //
607
608   // TODO: how should we implement the filtering for the nanoADOs
609
610   AliEventplane *evplane = const_cast<AliVEvent *>(ev)->GetEventplane();
611   if(!evplane) return;
612   
613   // do not change these vectors qref
614   TVector2 * const qref  = evplane->GetQVector();
615   if(!qref) return;
616   // random subevents
617   TVector2 *qrsub1 = evplane->GetQsub1();
618   TVector2 *qrsub2 = evplane->GetQsub2();
619
620   // copy references
621   TVector2 *qcorr  = new TVector2(*qref);
622   TVector2 *qcsub1 = 0x0;
623   TVector2 *qcsub2 = 0x0;
624   //  printf("qrsub1 %p %f \n",qrsub1,qrsub1->X());
625
626
627   // eta gap ?
628   Bool_t etagap = kFALSE;
629   for (Int_t iCut=0; iCut<fEventPlanePreFilter.GetCuts()->GetEntries();++iCut) {
630     TString cutName=fEventPlanePreFilter.GetCuts()->At(iCut)->GetName();
631     if(cutName.Contains("eta") || cutName.Contains("Eta"))  etagap=kTRUE;
632   }
633
634   // subevent separation
635   if(fLikeSignSubEvents || etagap) {
636     qcsub1 = new TVector2(*qcorr);
637     qcsub2 = new TVector2(*qcorr);
638
639     Int_t ntracks=ev->GetNumberOfTracks();
640     
641     // track removals
642     for (Int_t itrack=0; itrack<ntracks; ++itrack){
643       AliVParticle *particle=ev->GetTrack(itrack);
644       AliVTrack *track= static_cast<AliVTrack*>(particle);
645       if (!track) continue;
646
647       Double_t cQX     = evplane->GetQContributionX(track);
648       Double_t cQY     = evplane->GetQContributionY(track);
649       
650       // by charge sub1+ sub2-
651       if(fLikeSignSubEvents) {
652         Short_t charge=track->Charge();
653         if (charge<0) qcsub1->Set(qcsub1->X()-cQX, qcsub1->Y()-cQY);
654         if (charge>0) qcsub2->Set(qcsub2->X()-cQX, qcsub2->Y()-cQY);
655       }
656       // by eta sub1+ sub2-
657       if(etagap) {
658         Double_t eta=track->Eta();
659         if (eta<0.0) qcsub1->Set(qcsub1->X()-cQX, qcsub1->Y()-cQY);
660         if (eta>0.0) qcsub2->Set(qcsub2->X()-cQX, qcsub2->Y()-cQY);
661       }
662     }
663   }
664   else {
665     // by a random
666     qcsub1 = new TVector2(*qrsub1);
667     qcsub2 = new TVector2(*qrsub2);
668   }
669   
670   // apply cuts, e.g. etagap 
671   if(fEventPlanePreFilter.GetCuts()->GetEntries()) {
672     UInt_t selectedMask=(1<<fEventPlanePreFilter.GetCuts()->GetEntries())-1;
673     Int_t ntracks=ev->GetNumberOfTracks();
674     for (Int_t itrack=0; itrack<ntracks; ++itrack){
675       AliVParticle *particle=ev->GetTrack(itrack);
676       AliVTrack *track= static_cast<AliVTrack*>(particle);
677       if (!track) continue;
678       
679       //event plane cuts
680       UInt_t cutMask=fEventPlanePreFilter.IsSelected(track);
681       //apply cut
682       if (cutMask==selectedMask) continue;
683
684       Double_t cQX     = 0.0;
685       Double_t cQY     = 0.0;
686       if(!etagap) {
687         cQX = evplane->GetQContributionX(track);
688         cQY = evplane->GetQContributionY(track);
689       }
690       Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
691       Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
692       Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
693       Double_t cQYsub2 = evplane->GetQContributionYsub2(track);      
694
695       // update Q vectors
696       qcorr->Set(qcorr->X()-cQX, qcorr->Y()-cQY);
697       qcsub1->Set(qcsub1->X()-cQXsub1, qcsub1->Y()-cQYsub1);
698       qcsub2->Set(qcsub2->X()-cQXsub2, qcsub2->Y()-cQYsub2);
699     }
700   }
701
702   // POI (particle of interest) rejection
703   Int_t pairIndex=GetPairIndex(arr1,arr2);
704   
705   Int_t ntrack1=arrTracks1.GetEntriesFast();
706   Int_t ntrack2=arrTracks2.GetEntriesFast();
707   AliDielectronPair candidate;
708   candidate.SetKFUsage(fUseKF);
709   
710   UInt_t selectedMask=(1<<fEventPlanePOIPreFilter.GetCuts()->GetEntries())-1;
711   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
712     Int_t end=ntrack2;
713     if (arr1==arr2) end=itrack1;
714     Bool_t accepted=kFALSE;
715     for (Int_t itrack2=0; itrack2<end; ++itrack2){
716       TObject *track1=arrTracks1.UncheckedAt(itrack1);
717       TObject *track2=arrTracks2.UncheckedAt(itrack2);
718       if (!track1 || !track2) continue;
719       //create the pair
720       candidate.SetTracks(static_cast<AliVTrack*>(track1), fPdgLeg1,
721                           static_cast<AliVTrack*>(track2), fPdgLeg2);
722       
723       candidate.SetType(pairIndex);
724       candidate.SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(&candidate,fPdgMother));
725       
726       //event plane cuts
727       UInt_t cutMask=fEventPlanePOIPreFilter.IsSelected(&candidate);
728       //apply cut
729       if (cutMask==selectedMask) continue;
730
731       accepted=kTRUE;
732       //remove the tracks from the Track arrays
733       arrTracks2.AddAt(0x0,itrack2);
734     }
735       if ( accepted ) arrTracks1.AddAt(0x0,itrack1);
736   }
737   //compress the track arrays
738   arrTracks1.Compress();
739   arrTracks2.Compress();
740   
741   
742   //Modify the components: subtract the tracks
743   ntrack1=arrTracks1.GetEntriesFast();
744   ntrack2=arrTracks2.GetEntriesFast();
745   
746   // remove leg1 contribution
747   for (Int_t itrack=0; itrack<ntrack1; ++itrack){
748     AliVTrack *track= static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack));
749     if (!track) continue;
750     
751     Double_t cQX     = evplane->GetQContributionX(track);
752     Double_t cQY     = evplane->GetQContributionY(track);
753     Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
754     Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
755     Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
756     Double_t cQYsub2 = evplane->GetQContributionYsub2(track);
757     
758     // update Q vectors
759     qcorr->Set(qcorr->X()-cQX, qcorr->Y()-cQY);
760     qcsub1->Set(qcsub1->X()-cQXsub1, qcsub1->Y()-cQYsub1);
761     qcsub2->Set(qcsub2->X()-cQXsub2, qcsub2->Y()-cQYsub2);
762   }
763   // remove leg2 contribution
764   for (Int_t itrack=0; itrack<ntrack2; ++itrack){
765     AliVTrack *track= static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack));
766     if (!track) continue;
767     
768     Double_t cQX     = evplane->GetQContributionX(track);
769     Double_t cQY     = evplane->GetQContributionY(track);
770     Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
771     Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
772     Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
773     Double_t cQYsub2 = evplane->GetQContributionYsub2(track);
774     
775     // update Q vectors
776     qcorr->Set(qcorr->X()-cQX, qcorr->Y()-cQY);
777     qcsub1->Set(qcsub1->X()-cQXsub1, qcsub1->Y()-cQYsub1);
778     qcsub2->Set(qcsub2->X()-cQXsub2, qcsub2->Y()-cQYsub2);
779   }
780
781   //  printf("qrsub1 %p %f \t qcsub1 %p %f \n",qrsub1,qrsub1->X(),qcsub1,qcsub1->X());
782   // set AliEventplane with corrected values
783   cevplane->SetQVector(qcorr);
784   cevplane->SetQsub(qcsub1, qcsub2);
785   AliDielectronVarManager::SetTPCEventPlane(cevplane);
786 }
787
788 //________________________________________________________________
789 void AliDielectron::PairPreFilter(Int_t arr1, Int_t arr2, TObjArray &arrTracks1, TObjArray &arrTracks2)
790 {
791   //
792   // Prefilter tracks from pairs
793   // Needed for datlitz rejections
794   // remove all tracks from the Single track arrays that pass the cuts in this filter
795   //
796
797   Int_t ntrack1=arrTracks1.GetEntriesFast();
798   Int_t ntrack2=arrTracks2.GetEntriesFast();
799   AliDielectronPair candidate;
800   candidate.SetKFUsage(fUseKF);
801   // flag arrays for track removal
802   Bool_t *bTracks1 = new Bool_t[ntrack1];
803   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1) bTracks1[itrack1]=kFALSE;
804   Bool_t *bTracks2 = new Bool_t[ntrack2];
805   for (Int_t itrack2=0; itrack2<ntrack2; ++itrack2) bTracks2[itrack2]=kFALSE;
806
807   UInt_t selectedMask=(1<<fPairPreFilter.GetCuts()->GetEntries())-1;
808   UInt_t selectedMaskPair=(1<<fPairFilter.GetCuts()->GetEntries())-1;
809
810   Int_t nRejPasses = 1; //for fPreFilterUnlikeOnly and no set flag 
811   if (fPreFilterAllSigns) nRejPasses = 3;
812
813   for (Int_t iRP=0; iRP < nRejPasses; ++iRP) {
814         Int_t arr1RP=arr1, arr2RP=arr2;
815         TObjArray *arrTracks1RP=&arrTracks1;
816         TObjArray *arrTracks2RP=&arrTracks2;
817         Bool_t *bTracks1RP = bTracks1;
818         Bool_t *bTracks2RP = bTracks2;
819         switch (iRP) {
820                 case 1: arr1RP=arr1;arr2RP=arr1;
821                                 arrTracks1RP=&arrTracks1;
822                                 arrTracks2RP=&arrTracks1;
823                                 bTracks1RP = bTracks1;
824                                 bTracks2RP = bTracks1;
825                                 break;
826                 case 2: arr1RP=arr2;arr2RP=arr2;
827                                 arrTracks1RP=&arrTracks2;
828                                 arrTracks2RP=&arrTracks2;
829                                 bTracks1RP = bTracks2;
830                                 bTracks2RP = bTracks2;
831                                 break;
832                 default: ;//nothing to do
833         }
834         Int_t ntrack1RP=(*arrTracks1RP).GetEntriesFast();
835         Int_t ntrack2RP=(*arrTracks2RP).GetEntriesFast();
836
837         Int_t pairIndex=GetPairIndex(arr1RP,arr2RP);
838
839         for (Int_t itrack1=0; itrack1<ntrack1RP; ++itrack1){
840           Int_t end=ntrack2RP;
841           if (arr1RP==arr2RP) end=itrack1;
842           for (Int_t itrack2=0; itrack2<end; ++itrack2){
843                 TObject *track1=(*arrTracks1RP).UncheckedAt(itrack1);
844                 TObject *track2=(*arrTracks2RP).UncheckedAt(itrack2);
845                 if (!track1 || !track2) continue;
846                 //create the pair
847                 candidate.SetTracks(static_cast<AliVTrack*>(track1), fPdgLeg1,
848                         static_cast<AliVTrack*>(track2), fPdgLeg2);
849
850                 candidate.SetType(pairIndex);
851                 candidate.SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(&candidate,fPdgMother));
852                 //relate to the production vertex
853                 //       if (AliDielectronVarManager::GetKFVertex()) candidate.SetProductionVertex(*AliDielectronVarManager::GetKFVertex());
854
855                 //pair cuts
856                 UInt_t cutMask=fPairPreFilter.IsSelected(&candidate);
857
858                 //apply cut
859                 if (cutMask!=selectedMask) continue;
860                 if (fCfManagerPair) fCfManagerPair->Fill(selectedMaskPair+1 ,&candidate);
861                 if (fHistos) FillHistogramsPair(&candidate,kTRUE);
862                 //set flags for track removal
863                 bTracks1RP[itrack1]=kTRUE;
864                 bTracks2RP[itrack2]=kTRUE;
865           }
866         }
867   }
868
869   //remove the tracks from the Track arrays
870   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
871     if(bTracks1[itrack1]) arrTracks1.AddAt(0x0, itrack1);
872   }
873   for (Int_t itrack2=0; itrack2<ntrack2; ++itrack2){
874     if(bTracks2[itrack2]) arrTracks2.AddAt(0x0, itrack2);
875   }
876
877   // clean up
878   delete [] bTracks1;
879   delete [] bTracks2;
880
881   //compress the track arrays
882   arrTracks1.Compress();
883   arrTracks2.Compress();
884   
885   //apply leg cuts after the pre filter
886   if ( fPairPreFilterLegs.GetCuts()->GetEntries()>0 ) {
887     selectedMask=(1<<fPairPreFilterLegs.GetCuts()->GetEntries())-1;
888     //loop over tracks from array 1
889     for (Int_t itrack=0; itrack<arrTracks1.GetEntriesFast();++itrack){
890       //test cuts
891       UInt_t cutMask=fPairPreFilterLegs.IsSelected(arrTracks1.UncheckedAt(itrack));
892       
893       //apply cut
894       if (cutMask!=selectedMask) arrTracks1.AddAt(0x0,itrack);;
895     }
896     arrTracks1.Compress();
897     
898     //in case of like sign don't loop over second array
899     if (arr1==arr2) {
900       arrTracks2=arrTracks1;
901     } else {
902       
903       //loop over tracks from array 2
904       for (Int_t itrack=0; itrack<arrTracks2.GetEntriesFast();++itrack){
905       //test cuts
906         UInt_t cutMask=fPairPreFilterLegs.IsSelected(arrTracks2.UncheckedAt(itrack));
907       //apply cut
908         if (cutMask!=selectedMask) arrTracks2.AddAt(0x0,itrack);
909       }
910       arrTracks2.Compress();
911       
912     }
913   }
914   //For unlike-sign monitor track-cuts:
915   if (arr1!=arr2&&fHistos) {
916     TObjArray *unlikesignArray[2] = {&arrTracks1,&arrTracks2};
917     FillHistogramsTracks(unlikesignArray);
918   }
919 }
920
921 //________________________________________________________________
922 void AliDielectron::FillPairArrays(Int_t arr1, Int_t arr2)
923 {
924   //
925   // select pairs and fill pair candidate arrays
926   //
927
928   TObjArray arrTracks1=fTracks[arr1];
929   TObjArray arrTracks2=fTracks[arr2];
930
931   //process pre filter if set
932   if ((!fPreFilterAllSigns) && (!fPreFilterUnlikeOnly) && ( fPairPreFilter.GetCuts()->GetEntries()>0 ))  PairPreFilter(arr1, arr2, arrTracks1, arrTracks2);
933   
934   Int_t pairIndex=GetPairIndex(arr1,arr2);
935
936   Int_t ntrack1=arrTracks1.GetEntriesFast();
937   Int_t ntrack2=arrTracks2.GetEntriesFast();
938
939   AliDielectronPair *candidate=new AliDielectronPair;
940   candidate->SetKFUsage(fUseKF);
941
942   UInt_t selectedMask=(1<<fPairFilter.GetCuts()->GetEntries())-1;
943   
944   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
945     Int_t end=ntrack2;
946     if (arr1==arr2) end=itrack1;
947     for (Int_t itrack2=0; itrack2<end; ++itrack2){
948       //create the pair
949       candidate->SetTracks(static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1)), fPdgLeg1,
950                              static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2)), fPdgLeg2);
951       candidate->SetType(pairIndex);
952       Int_t label=AliDielectronMC::Instance()->GetLabelMotherWithPdg(candidate,fPdgMother);
953       candidate->SetLabel(label);
954       if (label>-1) candidate->SetPdgCode(fPdgMother);
955
956       // check for gamma kf particle
957       label=AliDielectronMC::Instance()->GetLabelMotherWithPdg(candidate,22);
958       if (label>-1) {
959         candidate->SetGammaTracks(static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1)), fPdgLeg1,
960                                   static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2)), fPdgLeg2);
961       // should we set the pdgmothercode and the label
962       }
963
964       //pair cuts
965       UInt_t cutMask=fPairFilter.IsSelected(candidate);
966       
967       //CF manager for the pair
968       if (fCfManagerPair) fCfManagerPair->Fill(cutMask,candidate);
969       //histogram array for the pair
970       if (fHistoArray) fHistoArray->Fill(pairIndex,candidate);
971
972       //apply cut
973       if (cutMask!=selectedMask) continue;
974
975       //add the candidate to the candidate array 
976       PairArray(pairIndex)->Add(candidate);
977       //get a new candidate
978       candidate=new AliDielectronPair;
979           candidate->SetKFUsage(fUseKF);
980     }
981   }
982   //delete the surplus candidate
983   delete candidate;
984 }
985
986 //________________________________________________________________
987 void AliDielectron::FillPairArrayTR()
988 {
989   //
990   // select pairs and fill pair candidate arrays
991   //
992   UInt_t selectedMask=(1<<fPairFilter.GetCuts()->GetEntries())-1;
993   
994   while ( fTrackRotator->NextCombination() ){
995     AliDielectronPair candidate;
996     candidate.SetKFUsage(fUseKF);
997     candidate.SetTracks(&fTrackRotator->GetKFTrackP(), &fTrackRotator->GetKFTrackN(),
998                         fTrackRotator->GetVTrackP(),fTrackRotator->GetVTrackN());
999     candidate.SetType(kEv1PMRot);
1000     
1001     //pair cuts
1002     UInt_t cutMask=fPairFilter.IsSelected(&candidate);
1003     
1004     //CF manager for the pair
1005     if (fCfManagerPair) fCfManagerPair->Fill(cutMask,&candidate);
1006     //histogram array for the pair
1007     if (fHistoArray) fHistoArray->Fill((Int_t)kEv1PMRot,&candidate);
1008     
1009     //apply cut
1010     if (cutMask==selectedMask) {
1011      if(fHistos) FillHistogramsPair(&candidate);
1012      if(fStoreRotatedPairs) PairArray(kEv1PMRot)->Add(new AliDielectronPair(candidate));
1013     } 
1014   }
1015 }
1016
1017 //________________________________________________________________
1018 void AliDielectron::FillDebugTree()
1019 {
1020   //
1021   // Fill Histogram information for tracks and pairs
1022   //
1023   
1024   //Fill Debug tree
1025   for (Int_t i=0; i<10; ++i){
1026     Int_t ntracks=PairArray(i)->GetEntriesFast();
1027     for (Int_t ipair=0; ipair<ntracks; ++ipair){
1028       fDebugTree->Fill(static_cast<AliDielectronPair*>(PairArray(i)->UncheckedAt(ipair)));
1029     }
1030   }
1031 }
1032
1033 //________________________________________________________________
1034 void AliDielectron::SaveDebugTree()
1035 {
1036   //
1037   // delete the debug tree, this will also write the tree
1038   //
1039   if (fDebugTree) fDebugTree->DeleteStreamer();
1040 }
1041
1042
1043 //__________________________________________________________________
1044 void AliDielectron::AddSignalMC(AliDielectronSignalMC* signal) {
1045   //
1046   //  Add an MC signal to the signals list
1047   //
1048   if(!fSignalsMC) {
1049     fSignalsMC = new TObjArray();
1050     fSignalsMC->SetOwner();
1051   }
1052   fSignalsMC->Add(signal);
1053 }
1054 //________________________________________________________________
1055 void AliDielectron::FillMCHistograms(const AliVEvent *ev) {
1056   //
1057   // fill QA MC histograms for pairs and legs of all added mc signals
1058   //
1059
1060   if (!fSignalsMC) return;
1061   TString className,className2;
1062   Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
1063   AliDielectronVarManager::Fill(ev, values); // get event informations
1064   //loop over all added mc signals
1065   for(Int_t isig=0; isig<fSignalsMC->GetEntries(); isig++) {
1066
1067     className.Form("Pair_%s",fSignalsMC->At(isig)->GetName());
1068     className2.Form("Track_Legs_%s",fSignalsMC->At(isig)->GetName());
1069     Bool_t pairClass=fHistos->GetHistogramList()->FindObject(className.Data())!=0x0;
1070     Bool_t legClass=fHistos->GetHistogramList()->FindObject(className2.Data())!=0x0;
1071     if(!pairClass && !legClass) return;
1072
1073     Int_t ntracks=PairArray(AliDielectron::kEv1PM)->GetEntriesFast(); // only SE +-
1074     for (Int_t ipair=0; ipair<ntracks; ++ipair){
1075       AliDielectronPair *pair=static_cast<AliDielectronPair*>(PairArray(AliDielectron::kEv1PM)->UncheckedAt(ipair));
1076
1077       Bool_t isMCtruth = AliDielectronMC::Instance()->IsMCTruth(pair, (AliDielectronSignalMC*)fSignalsMC->At(isig));
1078       if(isMCtruth) {
1079         //fill pair information
1080         if (pairClass){
1081           AliDielectronVarManager::Fill(pair, values);
1082           fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
1083         }
1084         //fill leg information, both + and - in the same histo
1085         if (legClass){
1086           AliDielectronVarManager::Fill(pair->GetFirstDaughter(),values);
1087           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
1088           AliDielectronVarManager::Fill(pair->GetSecondDaughter(),values);
1089           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
1090         }
1091       } //is signal
1092     } //loop: pairs
1093   } //loop: MCsignals
1094
1095 }