]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGDQ/dielectron/AliDielectronMixingHandler.cxx
o small fix in mixing handler (bin finding)
[u/mrichter/AliRoot.git] / PWGDQ / dielectron / AliDielectronMixingHandler.cxx
CommitLineData
5720c765 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 MixingHandler //
18// //
19// //
20/*
21Detailed description
22
23
24*/
25// //
26///////////////////////////////////////////////////////////////////////////
27
28#include <TVectorD.h>
29#include <TH1.h>
30#include <TAxis.h>
31
32#include <AliLog.h>
33#include <AliVTrack.h>
34
35#include "AliDielectron.h"
36#include "AliDielectronHelper.h"
37#include "AliDielectronHistos.h"
38#include "AliDielectronEvent.h"
39
40#include "AliDielectronMixingHandler.h"
41
42ClassImp(AliDielectronMixingHandler)
43
44AliDielectronMixingHandler::AliDielectronMixingHandler() :
45 TNamed(),
46 fDepth(10),
47 fArrPools("TClonesArray"),
48 fAxes(kMaxCuts),
49 fMixType(kOSonly),
50 fMixIncomplete(kTRUE),
51 fMoveToSameVertex(kFALSE)
52{
53 //
54 // Default Constructor
55 //
56 for (Int_t i=0; i<kMaxCuts; ++i){
57 fEventCuts[i]=0;
58 }
59 fAxes.SetOwner(kTRUE);
60}
61
62//______________________________________________
63AliDielectronMixingHandler::AliDielectronMixingHandler(const char* name, const char* title) :
64 TNamed(name, title),
65 fDepth(10),
66 fArrPools("TClonesArray"),
67 fAxes(kMaxCuts),
68 fMixType(kOSonly),
69 fMixIncomplete(kTRUE),
70 fMoveToSameVertex(kFALSE)
71{
72 //
73 // Named Constructor
74 //
75 for (Int_t i=0; i<kMaxCuts; ++i){
76 fEventCuts[i]=0;
77 }
78 fAxes.SetOwner(kTRUE);
79}
80
81//______________________________________________
82AliDielectronMixingHandler::~AliDielectronMixingHandler()
83{
84 //
85 // Default Destructor
86 //
87 fAxes.Delete();
88}
89
90//________________________________________________________________
91void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
92 Int_t nbins, Double_t min, Double_t max, Bool_t log)
93{
94 //
95 // Add a variable to the mixing handler
96 //
97
98 // limit number of variables to kMaxCuts
99 if (fAxes.GetEntriesFast()>=kMaxCuts) return;
100
101 TVectorD *binLimits=0x0;
102 if (!log) binLimits=AliDielectronHelper::MakeLinBinning(nbins,min,max);
103 else binLimits=AliDielectronHelper::MakeLogBinning(nbins,min,max);
104 if (!binLimits) return;
105
106 Int_t size=fAxes.GetEntriesFast();
107 fEventCuts[size]=(UShort_t)type;
108 fAxes.Add(binLimits);
109}
110
111//________________________________________________________________
112void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
113 const char* binLimitStr)
114{
115 //
116 // Add a variable to the mixing handler with arbitrary binning
117 //
118
119 // limit number of variables to kMaxCuts
120 if (fAxes.GetEntriesFast()>=kMaxCuts) return;
121
122 TVectorD *binLimits=AliDielectronHelper::MakeArbitraryBinning(binLimitStr);
123 if (!binLimits) return;
124
125 Int_t size=fAxes.GetEntriesFast();
126 fEventCuts[size]=(UShort_t)type;
127 fAxes.Add(binLimits);
128}
129
130//______________________________________________
131void AliDielectronMixingHandler::Fill(const AliVEvent *ev, AliDielectron *diele)
132{
133 //
134 // fill event buffers and perform mixing if the pool depth is reached
135 //
136
137 //check if there are tracks available
138 if (diele->GetTrackArray(0)->GetEntriesFast()==0 && diele->GetTrackArray(1)->GetEntriesFast()==0) return;
139
140 //find mixing bin
d327d9cd 141 Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
5720c765 142 AliDielectronVarManager::Fill(ev,values);
143
144 TString dim;
145 Int_t bin=FindBin(values,&dim);
146
d327d9cd 147 //add mixing bin to event data
148 values[AliDielectronVarManager::kMixingBin] = bin;
149
5720c765 150 if (bin<0){
151 AliDebug(5,Form("Bin outside range: %s",dim.Data()));
152 return;
153 }
154
155 // get mixing pool, create it if it does not yet exist.
156 TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(bin));
157 if (!poolp){
158 AliDebug(10,Form("New pool at %d (%s)\n",bin,dim.Data()));
159 poolp=new(fArrPools[bin]) TClonesArray("AliDielectronEvent",fDepth);
160 }
161 TClonesArray &pool=*poolp;
162
163 AliDebug(10,Form("new event at %d: %d",bin,pool.GetEntriesFast()));
164 AliDielectronEvent *event=new(pool[pool.GetEntriesFast()]) AliDielectronEvent();
165
166 event->SetTracks(*diele->GetTrackArray(0), *diele->GetTrackArray(1), *diele->GetPairArray(1));
167 event->SetEventData(values);
168
169 // check if pool depth is reached.
170 if (pool.GetEntriesFast()<fDepth) return;
171
172 // pool depth reached, do mixing
173 DoMixing(pool,diele);
174
175 // increase counter for full bins
176 if (diele->fHistos) {
177 diele->fHistos->Fill("Mixing","Stats",0);
178 diele->fHistos->Fill("Mixing","CompletePools",bin);
179 }
180
181 //clear the current pool
182 pool.Clear("C");
183}
184
185//______________________________________________
186void AliDielectronMixingHandler::DoMixing(TClonesArray &pool, AliDielectron *diele)
187{
188 //
189 // perform the mixing
190 //
191
192 //buffer track arrays and copy them back afterwards
193 TObjArray arrTrDummy[4];
194 for (Int_t i=0; i<4; ++i) arrTrDummy[i]=diele->fTracks[i];
195
196 //buffer also global event data
197 Double_t values[AliDielectronVarManager::kNMaxValues]={0};
198 for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues; ++i)
199 values[i]=AliDielectronVarManager::GetValue((AliDielectronVarManager::ValueTypes)i);
200
201 for (Int_t i1=0; i1<pool.GetEntriesFast(); ++i1){
202 AliDielectronEvent *ev1=static_cast<AliDielectronEvent*>(pool.At(i1));
203 //use event data from the first event
204 //both events are in the same mixing bin anyhow...
205 AliDielectronVarManager::SetEventData(ev1->GetEventData());
206
207 TObject *o=0x0;
208 TIter ev1P(ev1->GetTrackArrayP());
209 TIter ev1N(ev1->GetTrackArrayN());
210
211 for (Int_t i2=i1+1; i2<pool.GetEntriesFast(); ++i2){
212 //clear arryas
213 diele->fTracks[0].Clear();
214 diele->fTracks[1].Clear();
215 diele->fTracks[2].Clear();
216 diele->fTracks[3].Clear();
217
218 //setup track arrays
219 AliDielectronEvent *ev2=static_cast<AliDielectronEvent*>(pool.At(i2));
220
221 ev1P.Reset();
222 ev1N.Reset();
223 TIter ev2P(ev2->GetTrackArrayP());
224 TIter ev2N(ev2->GetTrackArrayN());
225
226 //
227 //move tracks to the same vertex (vertex of the first event), if requested
228 //
229 if (fMoveToSameVertex){
230 const Double_t *varsFirst=ev1->GetEventData();
231 const Double_t *varsMix=ev2->GetEventData();
232
233 const Double_t vFirst[3]={varsFirst[AliDielectronVarManager::kXvPrim],
234 varsFirst[AliDielectronVarManager::kYvPrim],
235 varsFirst[AliDielectronVarManager::kZvPrim]};
236
237 const Double_t vMix[3] ={varsMix[AliDielectronVarManager::kXvPrim],
238 varsMix[AliDielectronVarManager::kYvPrim],
239 varsMix[AliDielectronVarManager::kZvPrim]};
240
241 //loop over all tracks from the second event and move them to the vertex of the first
242 AliVTrack *vtrack=0x0;
243 while ( ( vtrack=(AliVTrack*)ev2P() ) ){
244 MoveToSameVertex(vtrack, vFirst, vMix);
245 }
246
247
248 while ( ( vtrack=(AliVTrack*)ev2N() ) ){
249 MoveToSameVertex(vtrack, vFirst, vMix);
250 }
251
252
253 ev2P.Reset();
254 ev2N.Reset();
255 }
256
257 //mixing of ev1- ev2+ (pair type4). This is common for all mixing types
258 while ( (o=ev1N()) ) diele->fTracks[1].Add(o);
259 while ( (o=ev2P()) ) diele->fTracks[2].Add(o);
260 diele->FillPairArrays(1,2);
261
262 if (fMixType==kAll || fMixType==kOSandLS){
263 // all 4 pair arrays will be filled
264 while ( (o=ev1P()) ) diele->fTracks[0].Add(o);
265 while ( (o=ev2N()) ) diele->fTracks[3].Add(o);
266 diele->FillPairArrays(0,2);
267 diele->FillPairArrays(1,3);
268 if (fMixType==kAll) diele->FillPairArrays(0,3);
269 }
270
271 if (fMixType==kOSonly || fMixType==kOSandLS){
272 //use the pair type of ev1- ev1+ also for ev1+ ev1-
273 diele->fTracks[1].Clear();
274 diele->fTracks[2].Clear();
275 while ( (o=ev1P()) ) diele->fTracks[1].Add(o);
276 while ( (o=ev2N()) ) diele->fTracks[2].Add(o);
277 diele->FillPairArrays(1,2);
278 }
279 }
280 }
281
282 //copy back the tracks
283 for (Int_t i=0; i<4; ++i) {
284 diele->fTracks[i].Clear();
285 diele->fTracks[i]=arrTrDummy[i];
286 }
287
288 //set back global event values
289 AliDielectronVarManager::SetEventData(values);
290}
291
292//______________________________________________
293void AliDielectronMixingHandler::MixRemaining(AliDielectron *diele)
294{
295 //
296 // mix all pools even if they are incomplete
297 //
298
299 //Check if there was any processed data and it is requested to mix incomplete bins
ac390e40 300 if (!diele || !diele->PairArray(0) || !fMixIncomplete ) return;
5720c765 301
302
303 for (Int_t ipool=0; ipool<fArrPools.GetSize(); ++ipool){
304 TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(ipool));
d327d9cd 305 if (!poolp || !poolp->GetEntriesFast() || !poolp->At(0)) continue;
5720c765 306 //clear the arrays before the final processing"
307 AliDebug(10,Form("Incomplete: Bin %d (%d)\n",ipool,poolp->GetEntriesFast()));
308 diele->ClearArrays();
309 DoMixing(*poolp,diele);
310
5720c765 311 // increase counter for incomplete bins
312 if (diele->fHistos) {
d327d9cd 313 //buffer event data and set event data using the first event in this pool
314 Double_t values[AliDielectronVarManager::kNMaxValues]={0};
315 for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues; ++i)
316 values[i]=AliDielectronVarManager::GetValue((AliDielectronVarManager::ValueTypes)i);
317
318 AliDielectronEvent *ev1=static_cast<AliDielectronEvent*>(poolp->At(0));
319 //use event data from the first event all events are in the same mixing bin anyhow...
320 AliDielectronVarManager::SetEventData(ev1->GetEventData());
321
322 // fill the histograms
ac390e40 323 diele->FillHistograms(0x0, kTRUE);
5720c765 324 diele->fHistos->Fill("Mixing","Stats",1);
325 diele->fHistos->Fill("Mixing","InCompletePools",ipool);
326 diele->fHistos->Fill("Mixing","Entries_InCompletePools",poolp->GetEntriesFast());
d327d9cd 327
328 //set back global event values
329 AliDielectronVarManager::SetEventData(values);
5720c765 330 }
331
332 }
333}
334
335
336//______________________________________________
337void AliDielectronMixingHandler::Init(const AliDielectron *diele)
338{
339 //
340 // initialise event buffers
341 //
342
d327d9cd 343 Int_t size=GetNumberOfBins();
5720c765 344
345 AliDebug(10,Form("Creating a pool array with size %d \n",size));
346
347 fArrPools.Expand(size);
348
349 //add statics histogram if we have a histogram manager
350 if (diele && diele->fHistos) {
351 diele->fHistos->AddClass("Mixing");
352 diele->fHistos->UserHistogram("Mixing","Stats","Mixing Statistics;;#called bins",2,0,2);
353 TH1* h=diele->fHistos->GetHistogram("Mixing","Stats");
354 h->GetXaxis()->SetBinLabel(1,"Complete");
355 h->GetXaxis()->SetBinLabel(2,"Incomplete");
356
357 diele->fHistos->UserHistogram("Mixing","CompletePools","Mixing Statistics compete pools;bin;#fills",size,0,size);
358 diele->fHistos->UserHistogram("Mixing","InCompletePools","Mixing Statistics incomplete pools;bin;#fills",size,0,size);
359 diele->fHistos->UserHistogram("Mixing","Entries_InCompletePools","#entries in incomplete pools;entries;#fills",fDepth,0,fDepth);
360 }
361
362 TString values;
363 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
364 TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
365 Int_t nRows=bins->GetNrows();
366 values+=Form("%s: ",AliDielectronVarManager::GetValueName(fEventCuts[i]));
367 for (Int_t irow=0; irow<nRows; ++irow){
368 values+=Form("%.2f, ",(*bins)[irow]);
369 }
370 }
371
372 AliDebug(10,values.Data());
373}
374
375//______________________________________________
d327d9cd 376Int_t AliDielectronMixingHandler::GetNumberOfBins() const
377{
378 //
379 // return the number of bins this mixing handler has
380 //
381 Int_t size=1;
382 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i)
383 size*=((static_cast<TVectorD*>(fAxes.At(i)))->GetNrows()-1);
384 return size;
385}
386
387//______________________________________________
5720c765 388Int_t AliDielectronMixingHandler::FindBin(const Double_t values[], TString *dim)
389{
390 //
391 // bin bin in mixing stack described by 'values'
392 // if the values are outside the binning range -1 is returned
393 // if dim is non NULL debug info will be stored in the variable
394 //
395
396 if (fAxes.GetEntriesFast()==0) {
397 if (dim) (*dim)="single bin";
398 return 0;
399 }
400 if (dim) (*dim)="";
401 Int_t sizeAdd=1;
402 Int_t bin=0;
403 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
404 Double_t val=values[fEventCuts[i]];
405 TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
406 Int_t nRows=bins->GetNrows();
407 if ( (val<(*bins)[0]) || (val>(*bins)[nRows-1]) ) {
408 return -1;
409 }
410
411 Int_t pos=TMath::BinarySearch(nRows,bins->GetMatrixArray(),val);
412 bin+=sizeAdd*pos;
a823f01b 413 if (dim) (*dim)+=Form("%s: %f (%d); ",AliDielectronVarManager::GetValueName(fEventCuts[i]),val,pos);
414 sizeAdd*=(nRows-1);
5720c765 415 }
416
417 return bin;
418}
419
420//______________________________________________
421void AliDielectronMixingHandler::MoveToSameVertex(AliVTrack * const vtrack, const Double_t *vFirst, const Double_t* vMix)
422{
423 //
424 // move 'track' which belongs to the vertex information of vMix to the vertex of vFirst
425 //
426
427 static Bool_t printed=kFALSE;
428
429 if (vtrack->IsA()==AliESDtrack::Class()){
430 AliESDtrack *track=(AliESDtrack*)vtrack;
431
432 //get track information
433 Double_t x = track->GetX();
434 Double_t alpha = track->GetAlpha();
435 Double_t param[5] = {0};
436 Double_t cov[15] = {0};
437
438 for (Int_t i=0; i<5; ++i) param[i]=track->GetParameter()[i];
439 for (Int_t i=0; i<15; ++i) cov[i] =track->GetCovariance()[i];
440
441 //translation
442 Double_t vt[3] = {vMix[0]-vFirst[0],vMix[1]-vFirst[1],vMix[2]-vFirst[2]};
443 //rotate to the track frame
236e1bda 444// track->Global2LocalPosition(vt,track->GetAlpha());
5720c765 445
446 //add to track position
236e1bda 447// x = x -vt[0];
448// param[0] = param[0]-vt[1];
449// param[1] = param[1]-vt[2];
450 x = x;
451 param[0] = param[0];
5720c765 452 param[1] = param[1]-vt[2];
453
454 //set updated track information
455 track->Set(x, alpha, param, cov);
456 } else {
457 // AliAODTrack *track=(AliAODTrack*)vtrack;
458 // Double_t pos[3]={0};
459 // track->GetPosition(pos);
460 // if (pos[0]>-999.){
461 // pos[0]=pos[0]-vMix[AliDielectronVarManager::kXvPrim]+vFirst[AliDielectronVarManager::kXvPrim];
462 // pos[1]=pos[1]-vMix[AliDielectronVarManager::kYvPrim]+vFirst[AliDielectronVarManager::kYvPrim];
463 // pos[2]=pos[2]-vMix[AliDielectronVarManager::kZvPrim]+vFirst[AliDielectronVarManager::kZvPrim];
464 // track->SetPosition(pos);
465// AliError("Move To same vertex not yet implemented for AOD!");
466 if (!printed) {
467// Error("AliDielectronMixingHandler::MoveToSameVertex","Move To same vertex not yet implemented for AOD!");
468 printed=kTRUE;
469 }
470 //
471 // Not that clear how to do it. In AOD track there is fPosition, fPositionAtDCA and "TRef fProdVertex"
472 // where Xv(), Yv(), Zv() returns the position of fProdVertex
473 //
474 }
475
476}