major dielectron update (included also the data and plotting macros for paper)
[u/mrichter/AliRoot.git] / PWG3 / 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
49 #include <AliESDEvent.h>
50 #include <AliESDtrack.h>
51
52 #include <AliVEvent.h>
53 #include <AliVParticle.h>
54 #include <AliVTrack.h>
55 #include "AliDielectronPair.h"
56 #include "AliDielectronHistos.h"
57 #include "AliDielectronCF.h"
58 #include "AliDielectronMC.h"
59 #include "AliDielectronVarManager.h"
60 #include "AliDielectronTrackRotator.h"
61 #include "AliDielectronDebugTree.h"
62 #include "AliDielectronSignalMC.h"
63
64 #include "AliDielectron.h"
65
66 ClassImp(AliDielectron)
67
68 const char* AliDielectron::fgkTrackClassNames[4] = {
69   "ev1+",
70   "ev1-",
71   "ev2+",
72   "ev2-"
73 };
74
75 const char* AliDielectron::fgkPairClassNames[11] = {
76   "ev1+_ev1+",
77   "ev1+_ev1-",
78   "ev1-_ev1-",
79   "ev1+_ev2+",
80   "ev1-_ev2+",
81   "ev2+_ev2+",
82   "ev1+_ev2-",
83   "ev1-_ev2-",
84   "ev2+_ev2-",
85   "ev2-_ev2-",
86   "ev1+_ev1-_TR"
87 };
88
89 //________________________________________________________________
90 AliDielectron::AliDielectron() :
91   TNamed("AliDielectron","AliDielectron"),
92   fEventFilter("EventFilter"),
93   fTrackFilter("TrackFilter"),
94   fPairPreFilter("PairPreFilter"),
95   fPairPreFilterLegs("PairPreFilterLegs"),
96   fPairFilter("PairFilter"),
97   fPdgMother(443),
98   fPdgLeg1(11),
99   fPdgLeg2(11),
100   fSignalsMC(0x0),
101   fNoPairing(kFALSE),
102   fHistos(0x0),
103   fPairCandidates(new TObjArray(10)),
104   fCfManagerPair(0x0),
105   fTrackRotator(0x0),
106   fDebugTree(0x0),
107   fPreFilterUnlikeOnly(kFALSE),
108   fPreFilterAllSigns(kFALSE),
109   fHasMC(kFALSE)
110 {
111   //
112   // Default constructor
113   //
114
115 }
116
117 //________________________________________________________________
118 AliDielectron::AliDielectron(const char* name, const char* title) :
119   TNamed(name,title),
120   fEventFilter("EventFilter"),
121   fTrackFilter("TrackFilter"),
122   fPairPreFilter("PairPreFilter"),
123   fPairPreFilterLegs("PairPreFilterLegs"),
124   fPairFilter("PairFilter"),
125   fPdgMother(443),
126   fPdgLeg1(11),
127   fPdgLeg2(11),
128   fSignalsMC(0x0),
129   fNoPairing(kFALSE),
130   fHistos(0x0),
131   fPairCandidates(new TObjArray(10)),
132   fCfManagerPair(0x0),
133   fTrackRotator(0x0),
134   fDebugTree(0x0),
135   fPreFilterUnlikeOnly(kFALSE),
136   fPreFilterAllSigns(kFALSE),
137   fHasMC(kFALSE)
138 {
139   //
140   // Named constructor
141   //
142   
143 }
144
145 //________________________________________________________________
146 AliDielectron::~AliDielectron()
147 {
148   //
149   // Default destructor
150   //
151   if (fHistos) delete fHistos;
152   if (fPairCandidates) delete fPairCandidates;
153   if (fDebugTree) delete fDebugTree;
154   if (fSignalsMC) delete fSignalsMC;
155 }
156
157 //________________________________________________________________
158 void AliDielectron::Init()
159 {
160   //
161   // Initialise objects
162   //
163
164   if(GetHasMC()) AliDielectronMC::Instance()->SetHasMC(GetHasMC());
165   
166   if (fCfManagerPair) {
167     fCfManagerPair->SetSignalsMC(fSignalsMC);
168     fCfManagerPair->InitialiseContainer(fPairFilter);
169   }
170   if (fTrackRotator)  {
171     fTrackRotator->SetTrackArrays(&fTracks[0],&fTracks[1]);
172     fTrackRotator->SetPdgLegs(fPdgLeg1,fPdgLeg2);
173   }
174   if (fDebugTree) fDebugTree->SetDielectron(this);
175
176
177 //________________________________________________________________
178 void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
179 {
180   //
181   // Process the events
182   //
183
184   //at least first event is needed!
185   if (!ev1){
186     AliError("At least first event must be set!");
187     return;
188   }
189     
190   AliDielectronVarManager::SetEvent(ev1);
191    
192   //in case we have MC load the MC event and process the MC particles
193   if (AliDielectronMC::Instance()->HasMC()) {
194     if (!AliDielectronMC::Instance()->ConnectMCEvent()){
195       AliError("Could not properly connect the MC event, skipping this event!");
196       return;
197     }
198     ProcessMC();
199   }
200   
201   //if candidate array doesn't exist, create it
202   if (!fPairCandidates->UncheckedAt(0)) {
203     InitPairCandidateArrays();
204   } else {
205     ClearArrays();
206   }
207
208   //mask used to require that all cuts are fulfilled
209   UInt_t selectedMask=(1<<fEventFilter.GetCuts()->GetEntries())-1;
210
211   //apply event cuts
212     if ((ev1&&fEventFilter.IsSelected(ev1)!=selectedMask) ||
213         (ev2&&fEventFilter.IsSelected(ev2)!=selectedMask)) return;
214   
215   AliDielectronVarManager::SetEvent(ev1);
216   
217   //fill track arrays for the first event
218   if (ev1){
219     FillTrackArrays(ev1);
220     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(0, 1, fTracks[0], fTracks[1]);
221     if ((fPreFilterAllSigns) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) {
222                         PairPreFilter(0, 0, fTracks[0], fTracks[0]);
223                         PairPreFilter(1, 1, fTracks[1], fTracks[1]);
224                 }               
225   }
226
227
228   //fill track arrays for the second event
229   if (ev2) {
230     FillTrackArrays(ev2,1);
231     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(2, 3, fTracks[2], fTracks[3]);
232     if ((fPreFilterAllSigns) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) {
233                         PairPreFilter(2, 2, fTracks[2], fTracks[2]);
234                         PairPreFilter(3, 3, fTracks[3], fTracks[3]);
235                 }               
236   }
237
238   if (!fNoPairing){
239     // create pairs and fill pair candidate arrays
240     for (Int_t itrackArr1=0; itrackArr1<4; ++itrackArr1){
241       for (Int_t itrackArr2=itrackArr1; itrackArr2<4; ++itrackArr2){
242         FillPairArrays(itrackArr1, itrackArr2);
243       }
244     }
245
246     //track rotation
247     if (fTrackRotator) {
248       fTrackRotator->SetEvent(ev1);
249       FillPairArrayTR();
250     }
251   }
252   
253   //in case there is a histogram manager, fill the QA histograms
254   if (fHistos) FillHistograms(ev1);
255
256   //fill debug tree if a manager is attached
257   if (fDebugTree) FillDebugTree();
258 }
259
260 //________________________________________________________________
261 void AliDielectron::ProcessMC()
262 {
263   //
264   // Process the MC data
265   //
266
267   AliDielectronMC *dieMC=AliDielectronMC::Instance();
268
269   if (fHistos) FillHistogramsMC(dieMC->GetMCEvent());
270
271   if(!fSignalsMC) return;
272   //loop over all MC data and Fill the CF container if it exist
273   if (!fCfManagerPair) return;
274   fCfManagerPair->SetPdgMother(fPdgMother);
275   if(!fCfManagerPair->GetStepForMCtruth()) return;
276
277   // signals to be studied
278   Int_t nSignals = fSignalsMC->GetEntries();
279
280   // initialize 2D arrays of labels for particles from each MC signal
281   Int_t** labels1;      // labels for particles satisfying branch 1
282   Int_t** labels2;      // labels for particles satisfying branch 2
283   Int_t** labels12;     // labels for particles satisfying both branches
284   labels1 = new Int_t*[nSignals];
285   labels2 = new Int_t*[nSignals];
286   labels12 = new Int_t*[nSignals];
287   Int_t* indexes1=new Int_t[nSignals];
288   Int_t* indexes2=new Int_t[nSignals];
289   Int_t* indexes12=new Int_t[nSignals];
290   for(Int_t isig=0;isig<nSignals;++isig) {
291     *(labels1+isig) = new Int_t[dieMC->GetNMCTracks()];
292     *(labels2+isig) = new Int_t[dieMC->GetNMCTracks()];
293     *(labels12+isig) = new Int_t[dieMC->GetNMCTracks()];
294     for(Int_t ip=0; ip<dieMC->GetNMCTracks();++ip) {
295       labels1[isig][ip] = -1;
296       labels2[isig][ip] = -1;
297       labels12[isig][ip] = -1;
298     }
299     indexes1[isig]=0;
300     indexes2[isig]=0;
301     indexes12[isig]=0;
302   }
303
304   Bool_t truth1=kFALSE;
305   Bool_t truth2=kFALSE;
306   // loop over the MC tracks
307   for(Int_t ipart=0; ipart<dieMC->GetNMCTracks(); ++ipart) {
308     for(Int_t isig=0; isig<nSignals; ++isig) {       // loop over signals
309       // Proceed only if this signal is required in the pure MC step
310       // NOTE: Some signals can be satisfied by many particles and this leads to high
311       //       computation times (e.g. secondary electrons from the GEANT transport). Be aware of this!!
312       if(!((AliDielectronSignalMC*)fSignalsMC->At(isig))->GetFillPureMCStep()) continue;
313
314       truth1 = dieMC->IsMCTruth(ipart, (AliDielectronSignalMC*)fSignalsMC->At(isig), 1);
315       truth2 = dieMC->IsMCTruth(ipart, (AliDielectronSignalMC*)fSignalsMC->At(isig), 2);
316
317       // particles satisfying both branches are treated separately to avoid double counting during pairing
318       if(truth1 && truth2) {
319         labels12[isig][indexes12[isig]] = ipart;
320         ++indexes12[isig];
321       }
322       else {
323         if(truth1) {
324           labels1[isig][indexes1[isig]] = ipart;
325           ++indexes1[isig];
326         }
327         if(truth2) {
328           labels2[isig][indexes2[isig]] = ipart;
329           ++indexes2[isig];
330         }
331       }
332     }
333   }  // end loop over MC particles
334
335   // Do the pairing and fill the CF container with pure MC info
336   for(Int_t isig=0; isig<nSignals; ++isig) {
337     // mix the particles which satisfy only one of the signal branches
338     for(Int_t i1=0;i1<indexes1[isig];++i1) {
339       for(Int_t i2=0;i2<indexes2[isig];++i2) {
340         fCfManagerPair->FillMC(labels1[isig][i1], labels2[isig][i2], isig);
341       }
342     }
343     // mix the particles which satisfy both branches
344     for(Int_t i1=0;i1<indexes12[isig];++i1) {
345       for(Int_t i2=0; i2<i1; ++i2) {
346         fCfManagerPair->FillMC(labels12[isig][i1], labels12[isig][i2], isig);
347       }
348     }
349   }    // end loop over signals
350
351   // release the memory
352   for(Int_t isig=0;isig<nSignals;++isig) {
353     delete [] *(labels1+isig);
354     delete [] *(labels2+isig);
355     delete [] *(labels12+isig);
356   }
357   delete [] labels1;
358   delete [] labels2;
359   delete [] labels12;
360   delete [] indexes1;
361   delete [] indexes2;
362   delete [] indexes12;
363 }
364
365 //________________________________________________________________
366 void AliDielectron::FillHistogramsTracks(TObjArray **tracks)
367 {
368   //
369   // Fill Histogram information for tracks after prefilter
370   // ignore mixed events - for prefilter, only single tracks +/- are relevant 
371   //
372   
373   TString  className,className2;
374   Double_t values[AliDielectronVarManager::kNMaxValues];
375   
376   //Fill track information, separately for the track array candidates
377   for (Int_t i=0; i<2; ++i){
378     className.Form("Pre_%s",fgkTrackClassNames[i]);
379     if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
380     Int_t ntracks=tracks[i]->GetEntriesFast();
381     for (Int_t itrack=0; itrack<ntracks; ++itrack){
382       AliDielectronVarManager::Fill(tracks[i]->UncheckedAt(itrack), values);
383       fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
384     }
385   }
386 }
387
388
389 //________________________________________________________________
390 void AliDielectron::FillHistogramsMC(const AliMCEvent *ev)
391 {
392   //
393   // Fill Histogram information for MCEvents
394   //
395
396   Double_t values[AliDielectronVarManager::kNMaxValues];
397   // Fill event information
398   AliDielectronVarManager::Fill(ev, values);
399   if (fHistos->GetHistogramList()->FindObject("MCEvent"))
400     fHistos->FillClass("MCEvent", AliDielectronVarManager::kNMaxValues, values);
401 }
402
403
404 //________________________________________________________________
405 void AliDielectron::FillHistograms(const AliVEvent *ev)
406 {
407   //
408   // Fill Histogram information for tracks and pairs
409   //
410   
411   TString  className,className2;
412   Double_t values[AliDielectronVarManager::kNMaxValues];
413   //Fill event information
414   AliDielectronVarManager::Fill(ev, values);
415   if (fHistos->GetHistogramList()->FindObject("Event"))
416     fHistos->FillClass("Event", AliDielectronVarManager::kNMaxValues, values);
417   
418   //Fill track information, separately for the track array candidates
419   for (Int_t i=0; i<4; ++i){
420     className.Form("Track_%s",fgkTrackClassNames[i]);
421     if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
422     Int_t ntracks=fTracks[i].GetEntriesFast();
423     for (Int_t itrack=0; itrack<ntracks; ++itrack){
424       AliDielectronVarManager::Fill(fTracks[i].UncheckedAt(itrack), values);
425       fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
426     }
427   }
428
429   //Fill Pair information, separately for all pair candidate arrays and the legs
430   TObjArray arrLegs(100);
431   for (Int_t i=0; i<10; ++i){
432     className.Form("Pair_%s",fgkPairClassNames[i]);
433     className2.Form("Track_Legs_%s",fgkPairClassNames[i]);
434     Bool_t pairClass=fHistos->GetHistogramList()->FindObject(className.Data())!=0x0;
435     Bool_t legClass=fHistos->GetHistogramList()->FindObject(className2.Data())!=0x0;
436     if (!pairClass&&!legClass) continue;
437     Int_t ntracks=PairArray(i)->GetEntriesFast();
438     for (Int_t ipair=0; ipair<ntracks; ++ipair){
439       AliDielectronPair *pair=static_cast<AliDielectronPair*>(PairArray(i)->UncheckedAt(ipair));
440       
441       //fill pair information
442       if (pairClass){
443         AliDielectronVarManager::Fill(pair, values);
444         fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
445       }
446
447       //fill leg information, don't fill the information twice
448       if (legClass){
449         AliVParticle *d1=pair->GetFirstDaughter();
450         AliVParticle *d2=pair->GetSecondDaughter();
451         if (!arrLegs.FindObject(d1)){
452           AliDielectronVarManager::Fill(d1, values);
453           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
454           arrLegs.Add(d1);
455         }
456         if (!arrLegs.FindObject(d2)){
457           AliDielectronVarManager::Fill(d2, values);
458           fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
459           arrLegs.Add(d2);
460         }
461       }
462     }
463     if (legClass) arrLegs.Clear();
464   }
465   
466 }
467 //________________________________________________________________
468 void AliDielectron::FillHistogramsPair(AliDielectronPair *pair,Bool_t fromPreFilter/*=kFALSE*/)
469 {
470   //
471   // Fill Histogram information for pairs and the track in the pair
472   // NOTE: in this funtion the leg information may be filled multiple
473   //       times. This funtion is used in the track rotation pairing
474   //       and those legs are not saved!
475   //
476   TString  className,className2;
477   Double_t values[AliDielectronVarManager::kNMaxValues];
478   
479   //Fill Pair information, separately for all pair candidate arrays and the legs
480   TObjArray arrLegs(100);
481   const Int_t type=pair->GetType();
482   if (fromPreFilter) {
483     className.Form("RejPair_%s",fgkPairClassNames[type]);
484     className2.Form("RejTrack_%s",fgkPairClassNames[type]);
485   } else {
486     className.Form("Pair_%s",fgkPairClassNames[type]);
487     className2.Form("Track_Legs_%s",fgkPairClassNames[type]);
488   }
489   
490   Bool_t pairClass=fHistos->GetHistogramList()->FindObject(className.Data())!=0x0;
491   Bool_t legClass=fHistos->GetHistogramList()->FindObject(className2.Data())!=0x0;
492   
493   //fill pair information
494   if (pairClass){
495     AliDielectronVarManager::Fill(pair, values);
496     fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
497   }
498
499   if (legClass){
500     AliVParticle *d1=pair->GetFirstDaughter();
501     AliDielectronVarManager::Fill(d1, values);
502     fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
503     
504     AliVParticle *d2=pair->GetSecondDaughter();
505     AliDielectronVarManager::Fill(d2, values);
506     fHistos->FillClass(className2, AliDielectronVarManager::kNMaxValues, values);
507   }
508 }
509
510 //________________________________________________________________
511 void AliDielectron::FillTrackArrays(AliVEvent * const ev, Int_t eventNr)
512 {
513   //
514   // select tracks and fill track candidate arrays
515   // eventNr = 0: First  event, use track arrays 0 and 1
516   // eventNr = 1: Second event, use track arrays 2 and 3
517   //
518   
519   Int_t ntracks=ev->GetNumberOfTracks();
520   UInt_t selectedMask=(1<<fTrackFilter.GetCuts()->GetEntries())-1;
521   for (Int_t itrack=0; itrack<ntracks; ++itrack){
522     //get particle
523     AliVParticle *particle=ev->GetTrack(itrack);
524     //TODO: temporary solution, perhaps think about a better implementation
525     //      This is needed to use AliESDpidCuts, which relies on the ESD event
526     //      is set as a AliESDtrack attribute... somehow ugly!
527     if (ev->IsA()==AliESDEvent::Class()){
528       AliESDtrack *track=static_cast<AliESDtrack*>(particle);
529       track->SetESDEvent(static_cast<AliESDEvent*>(ev)); //only in trunk...
530     }
531     
532     //apply track cuts
533     if (fTrackFilter.IsSelected(particle)!=selectedMask) continue;
534     
535     //fill selected particle into the corresponding track arrays
536     Short_t charge=particle->Charge();
537     if (charge>0)      fTracks[eventNr*2].Add(particle);
538     else if (charge<0) fTracks[eventNr*2+1].Add(particle);
539   }
540 }
541
542 //________________________________________________________________
543 void AliDielectron::PairPreFilter(Int_t arr1, Int_t arr2, TObjArray &arrTracks1, TObjArray &arrTracks2)
544 {
545   //
546   // Prefilter tracks from pairs
547   // Needed for datlitz rejections
548   // remove all tracks from the Single track arrays that pass the cuts in this filter
549   //
550   Int_t pairIndex=GetPairIndex(arr1,arr2);
551   
552   Int_t ntrack1=arrTracks1.GetEntriesFast();
553   Int_t ntrack2=arrTracks2.GetEntriesFast();
554   
555   AliDielectronPair candidate;
556   
557   UInt_t selectedMask=(1<<fPairPreFilter.GetCuts()->GetEntries())-1;
558   UInt_t selectedMaskPair=(1<<fPairFilter.GetCuts()->GetEntries())-1;
559   
560   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
561     Int_t end=ntrack2;
562     if (arr1==arr2) end=itrack1;
563     Bool_t accepted=kFALSE;
564     for (Int_t itrack2=0; itrack2<end; ++itrack2){
565       AliVTrack *track1=static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1));
566       AliVTrack *track2=static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2));
567       if (!track1 || !track2) continue;
568       //create the pair
569       candidate.SetTracks(track1, fPdgLeg1,
570                           track2, fPdgLeg2);
571       candidate.SetType(pairIndex);
572       candidate.SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(&candidate,fPdgMother));
573       //relate to the production vertex
574 //       if (AliDielectronVarManager::GetKFVertex()) candidate.SetProductionVertex(*AliDielectronVarManager::GetKFVertex());
575       
576       //pair cuts
577       UInt_t cutMask=fPairPreFilter.IsSelected(&candidate);
578       
579       //apply cut
580       if (cutMask!=selectedMask) continue;
581       if (fCfManagerPair) fCfManagerPair->Fill(selectedMaskPair+1 ,&candidate);
582       accepted=kTRUE;
583       if (fHistos) FillHistogramsPair(&candidate,kTRUE);
584       //remove the tracks from the Track arrays
585       arrTracks2.AddAt(0x0,itrack2);
586       //in case of like sign remove the track from both arrays!
587       if (arr1==arr2) arrTracks1.AddAt(0x0, itrack2);
588     }
589     if ( accepted ) arrTracks1.AddAt(0x0,itrack1);
590   }
591   //compress the track arrays
592   
593
594
595   arrTracks1.Compress();
596   arrTracks2.Compress();
597   
598   //apply leg cuts after the pre filter
599   if ( fPairPreFilterLegs.GetCuts()->GetEntries()>0 ) {
600     selectedMask=(1<<fPairPreFilterLegs.GetCuts()->GetEntries())-1;
601     //loop over tracks from array 1
602     for (Int_t itrack=0; itrack<arrTracks1.GetEntriesFast();++itrack){
603       //test cuts
604       UInt_t cutMask=fPairPreFilterLegs.IsSelected(arrTracks1.UncheckedAt(itrack));
605       
606       //apply cut
607       if (cutMask!=selectedMask) arrTracks1.AddAt(0x0,itrack);;
608     }
609     arrTracks1.Compress();
610     
611     //in case of like sign don't loop over second array
612     if (arr1==arr2) {
613       arrTracks2=arrTracks1;
614     } else {
615       
616       //loop over tracks from array 2
617       for (Int_t itrack=0; itrack<arrTracks2.GetEntriesFast();++itrack){
618       //test cuts
619         UInt_t cutMask=fPairPreFilterLegs.IsSelected(arrTracks2.UncheckedAt(itrack));
620       //apply cut
621         if (cutMask!=selectedMask) arrTracks2.AddAt(0x0,itrack);
622       }
623       arrTracks2.Compress();
624       
625     }
626   }
627   //For unlike-sign monitor track-cuts:
628   if (arr1!=arr2&&fHistos) {
629     TObjArray *unlikesignArray[2] = {&arrTracks1,&arrTracks2};
630     FillHistogramsTracks(unlikesignArray);
631   }
632 }
633
634 //________________________________________________________________
635 void AliDielectron::FillPairArrays(Int_t arr1, Int_t arr2)
636 {
637   //
638   // select pairs and fill pair candidate arrays
639   //
640
641   TObjArray arrTracks1=fTracks[arr1];
642   TObjArray arrTracks2=fTracks[arr2];
643
644   //process pre filter if set
645   if ((!fPreFilterAllSigns) && (!fPreFilterUnlikeOnly) && ( fPairPreFilter.GetCuts()->GetEntries()>0 ))  PairPreFilter(arr1, arr2, arrTracks1, arrTracks2);
646   
647   Int_t pairIndex=GetPairIndex(arr1,arr2);
648
649   Int_t ntrack1=arrTracks1.GetEntriesFast();
650   Int_t ntrack2=arrTracks2.GetEntriesFast();
651
652   AliDielectronPair *candidate=new AliDielectronPair;
653
654   UInt_t selectedMask=(1<<fPairFilter.GetCuts()->GetEntries())-1;
655   
656   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
657     Int_t end=ntrack2;
658     if (arr1==arr2) end=itrack1;
659     for (Int_t itrack2=0; itrack2<end; ++itrack2){
660       //create the pair
661       candidate->SetTracks(static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1)), fPdgLeg1,
662                            static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2)), fPdgLeg2);
663       candidate->SetType(pairIndex);
664       candidate->SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(candidate,fPdgMother));
665
666       //pair cuts
667       UInt_t cutMask=fPairFilter.IsSelected(candidate);
668       
669       //CF manager for the pair
670       if (fCfManagerPair) fCfManagerPair->Fill(cutMask,candidate);
671
672       //apply cut
673       if (cutMask!=selectedMask) continue;
674
675       //add the candidate to the candidate array 
676       PairArray(pairIndex)->Add(candidate);
677       //get a new candidate
678       candidate=new AliDielectronPair;
679     }
680   }
681   //delete the surplus candidate
682   delete candidate;
683 }
684
685 //________________________________________________________________
686 void AliDielectron::FillPairArrayTR()
687 {
688   //
689   // select pairs and fill pair candidate arrays
690   //
691   UInt_t selectedMask=(1<<fPairFilter.GetCuts()->GetEntries())-1;
692   
693   while ( fTrackRotator->NextCombination() ){
694     AliDielectronPair candidate;
695     candidate.SetTracks(&fTrackRotator->GetKFTrackP(), &fTrackRotator->GetKFTrackN(),
696                         fTrackRotator->GetVTrackP(),fTrackRotator->GetVTrackN());
697     candidate.SetType(kEv1PMRot);
698     
699     //pair cuts
700     UInt_t cutMask=fPairFilter.IsSelected(&candidate);
701     
702     //CF manager for the pair
703     if (fCfManagerPair) fCfManagerPair->Fill(cutMask,&candidate);
704     
705     //apply cut
706     if (cutMask==selectedMask&&fHistos) FillHistogramsPair(&candidate);
707   }
708 }
709
710 //________________________________________________________________
711 void AliDielectron::FillDebugTree()
712 {
713   //
714   // Fill Histogram information for tracks and pairs
715   //
716   
717   //Fill Debug tree
718   for (Int_t i=0; i<10; ++i){
719     Int_t ntracks=PairArray(i)->GetEntriesFast();
720     for (Int_t ipair=0; ipair<ntracks; ++ipair){
721       fDebugTree->Fill(static_cast<AliDielectronPair*>(PairArray(i)->UncheckedAt(ipair)));
722     }
723   }
724 }
725
726 //________________________________________________________________
727 void AliDielectron::SaveDebugTree()
728 {
729   //
730   // delete the debug tree, this will also write the tree
731   //
732   if (fDebugTree) fDebugTree->DeleteStreamer();
733 }
734
735
736 //__________________________________________________________________
737 void AliDielectron::AddSignalMC(AliDielectronSignalMC* signal) {
738   //
739   //  Add an MC signal to the signals list
740   //
741   if(!fSignalsMC) {
742     fSignalsMC = new TObjArray();
743     fSignalsMC->SetOwner();
744   }
745   fSignalsMC->Add(signal);
746 }