1 /*************************************************************************
2 * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 ///////////////////////////////////////////////////////////////////////////
17 // Dielectron MixingHandler //
26 ///////////////////////////////////////////////////////////////////////////
33 #include <AliVTrack.h>
35 #include "AliDielectron.h"
36 #include "AliDielectronHelper.h"
37 #include "AliDielectronHistos.h"
38 #include "AliDielectronEvent.h"
40 #include "AliDielectronMixingHandler.h"
42 ClassImp(AliDielectronMixingHandler)
44 AliDielectronMixingHandler::AliDielectronMixingHandler() :
47 fArrPools("TClonesArray"),
50 fMixIncomplete(kTRUE),
51 fMoveToSameVertex(kFALSE),
52 fSkipFirstEvt(kFALSE),
56 // Default Constructor
58 for (Int_t i=0; i<kMaxCuts; ++i){
61 fAxes.SetOwner(kTRUE);
64 //______________________________________________
65 AliDielectronMixingHandler::AliDielectronMixingHandler(const char* name, const char* title) :
68 fArrPools("TClonesArray"),
71 fMixIncomplete(kTRUE),
72 fMoveToSameVertex(kFALSE),
73 fSkipFirstEvt(kFALSE),
79 for (Int_t i=0; i<kMaxCuts; ++i){
82 fAxes.SetOwner(kTRUE);
85 //______________________________________________
86 AliDielectronMixingHandler::~AliDielectronMixingHandler()
95 //________________________________________________________________
96 void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
97 Int_t nbins, Double_t min, Double_t max, Bool_t log)
100 // Add a variable to the mixing handler
103 // limit number of variables to kMaxCuts
104 if (fAxes.GetEntriesFast()>=kMaxCuts) return;
106 TVectorD *binLimits=0x0;
107 if (!log) binLimits=AliDielectronHelper::MakeLinBinning(nbins,min,max);
108 else binLimits=AliDielectronHelper::MakeLogBinning(nbins,min,max);
109 if (!binLimits) return;
111 Int_t size=fAxes.GetEntriesFast();
112 fEventCuts[size]=(UShort_t)type;
113 fAxes.Add(binLimits);
116 //________________________________________________________________
117 void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
118 const char* binLimitStr)
121 // Add a variable to the mixing handler with arbitrary binning
124 // limit number of variables to kMaxCuts
125 if (fAxes.GetEntriesFast()>=kMaxCuts) return;
127 TVectorD *binLimits=AliDielectronHelper::MakeArbitraryBinning(binLimitStr);
128 if (!binLimits) return;
130 Int_t size=fAxes.GetEntriesFast();
131 fEventCuts[size]=(UShort_t)type;
132 fAxes.Add(binLimits);
135 //________________________________________________________________
136 void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
137 TVectorD * const bins)
140 // Add a variable to the mixing handler with arbitrary binning 'bins'
143 // limit number of variables to kMaxCuts
144 if (fAxes.GetEntriesFast()>=kMaxCuts) return;
146 Int_t size=fAxes.GetEntriesFast();
147 fEventCuts[size]=(UShort_t)type;
151 //______________________________________________
152 void AliDielectronMixingHandler::Fill(const AliVEvent *ev, AliDielectron *diele)
155 // fill event buffers and perform mixing if the pool depth is reached
158 //check if there are tracks available
159 if (diele->GetTrackArray(0)->GetEntriesFast()==0 && diele->GetTrackArray(1)->GetEntriesFast()==0) return;
162 Int_t bin=FindBin(AliDielectronVarManager::GetData(),&dim);
164 //add mixing bin to event data
165 AliDielectronVarManager::SetValue(AliDielectronVarManager::kMixingBin,bin);
168 AliDebug(5,Form("Bin outside range: %s",dim.Data()));
172 // get mixing pool, create it if it does not yet exist.
173 TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(bin));
175 AliDebug(10,Form("New pool at %d (%s)\n",bin,dim.Data()));
176 poolp=new(fArrPools[bin]) TClonesArray("AliDielectronEvent",1);
178 TClonesArray &pool=*poolp;
180 // clear the current pool if its size was reached by last event
181 // clear before fill new event into it
182 // NOTE: clear not directly after DoMixing, because you may want to use the ME
183 // in the internal train by other configs/tasks
184 // reset the event pool size to 1 (this keeps the physical memory consumption low)
185 if(pool.GetEntriesFast()==fDepth) {
187 pool.ExpandCreate(1);
190 AliDebug(10,Form("new event at %d: %d",bin,pool.GetEntriesFast()));
191 AliDielectronEvent *event=new(pool[pool.GetEntriesFast()]) AliDielectronEvent();
192 if(ev->IsA() == AliAODEvent::Class()) event->SetAOD(TMath::Max(diele->GetTrackArray(0)->GetEntriesFast(),diele->GetTrackArray(1)->GetEntriesFast()));
193 else event->SetESD();
195 event->SetProcessID(fPID);
196 event->SetTracks(*diele->GetTrackArray(0), *diele->GetTrackArray(1), *diele->GetPairArray(1));
197 event->SetEventData(AliDielectronVarManager::GetData());
199 // check if pool depth is reached.
200 if (pool.GetEntriesFast()<fDepth) return;
202 // pool depth reached, do mixing
203 DoMixing(pool,diele);
205 // increase counter for full bins
206 if (diele->fHistos) {
207 diele->fHistos->Fill("Mixing","Stats",0);
208 diele->fHistos->Fill("Mixing","CompletePools",bin);
213 //______________________________________________
214 void AliDielectronMixingHandler::DoMixing(TClonesArray &pool, AliDielectron *diele)
217 // perform the mixing
220 //buffer track arrays and copy them back afterwards
221 TObjArray arrTrDummy[4];
222 for (Int_t i=0; i<4; ++i) arrTrDummy[i]=diele->fTracks[i];
224 //buffer also global event data
225 Double_t values[AliDielectronVarManager::kNMaxValues]={0};
226 for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues; ++i)
227 values[i]=AliDielectronVarManager::GetValue((AliDielectronVarManager::ValueTypes)i);
230 // use event data from the first event
231 // all events are in the same mixing bin anyhow...
232 // optionally use only the event data from the first event and no tracks of it,
233 // by this you should get ride of event plane - leg correlations in the mixing
234 // but you loose the 1st event in the mixing statistics
235 AliDielectronEvent *ev0=static_cast<AliDielectronEvent*>(pool.At(0));
236 AliDielectronVarManager::SetEventData(ev0->GetEventData());
237 Int_t firstEvt=(fSkipFirstEvt ? 1 : 0);
239 for (Int_t i1=firstEvt; i1<pool.GetEntriesFast(); ++i1){
240 AliDielectronEvent *ev1=static_cast<AliDielectronEvent*>(pool.At(i1));
241 //use event data from the first event
242 //both events are in the same mixing bin anyhow...
243 if( !fSkipFirstEvt ) AliDielectronVarManager::SetEventData(ev1->GetEventData());
246 TIter ev1P(ev1->GetTrackArrayP());
247 TIter ev1N(ev1->GetTrackArrayN());
249 for (Int_t i2=i1+1; i2<pool.GetEntriesFast(); ++i2){
251 diele->fTracks[0].Clear();
252 diele->fTracks[1].Clear();
253 diele->fTracks[2].Clear();
254 diele->fTracks[3].Clear();
257 AliDielectronEvent *ev2=static_cast<AliDielectronEvent*>(pool.At(i2));
260 TIter ev2P(ev2->GetTrackArrayP());
261 TIter ev2N(ev2->GetTrackArrayN());
264 //move tracks to the same vertex (vertex of the first event), if requested
266 if (fMoveToSameVertex){
267 const Double_t *varsFirst=ev1->GetEventData();
268 const Double_t *varsMix=ev2->GetEventData();
270 const Double_t vFirst[3]={varsFirst[AliDielectronVarManager::kXvPrim],
271 varsFirst[AliDielectronVarManager::kYvPrim],
272 varsFirst[AliDielectronVarManager::kZvPrim]};
274 const Double_t vMix[3] ={varsMix[AliDielectronVarManager::kXvPrim],
275 varsMix[AliDielectronVarManager::kYvPrim],
276 varsMix[AliDielectronVarManager::kZvPrim]};
278 //loop over all tracks from the second event and move them to the vertex of the first
279 AliVTrack *vtrack=0x0;
280 while ( ( vtrack=(AliVTrack*)ev2P() ) ){
281 MoveToSameVertex(vtrack, vFirst, vMix);
285 while ( ( vtrack=(AliVTrack*)ev2N() ) ){
286 MoveToSameVertex(vtrack, vFirst, vMix);
294 //mixing of ev1- ev2+ (pair type4). This is common for all mixing types
295 while ( (o=ev1N()) ) diele->fTracks[1].Add(o);
296 while ( (o=ev2P()) ) diele->fTracks[2].Add(o);
297 diele->FillPairArrays(1,2);
299 if (fMixType==kAll || fMixType==kOSandLS){
300 // all 4 pair arrays will be filled
301 while ( (o=ev1P()) ) diele->fTracks[0].Add(o);
302 while ( (o=ev2N()) ) diele->fTracks[3].Add(o);
303 diele->FillPairArrays(0,2);
304 diele->FillPairArrays(1,3);
305 if (fMixType==kAll) diele->FillPairArrays(0,3);
308 if (fMixType==kOSonly || fMixType==kOSandLS){
309 //use the pair type of ev1- ev1+ also for ev1+ ev1-
310 diele->fTracks[1].Clear();
311 diele->fTracks[2].Clear();
312 while ( (o=ev1P()) ) diele->fTracks[1].Add(o);
313 while ( (o=ev2N()) ) diele->fTracks[2].Add(o);
314 diele->FillPairArrays(1,2);
320 //copy back the tracks
321 for (Int_t i=0; i<4; ++i) {
322 diele->fTracks[i].Clear();
323 diele->fTracks[i]=arrTrDummy[i];
326 //set back global event values
327 AliDielectronVarManager::SetEventData(values);
330 //______________________________________________
331 Bool_t AliDielectronMixingHandler::MixRemaining(AliDielectron *diele, Int_t ipool)
334 // mix all pools even if they are incomplete
337 //Check if there was any processed data and it is requested to mix incomplete bins
338 if (!diele || !fMixIncomplete ) return 0;
340 AliDielectronVarManager::SetEvent(0x0);
341 TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(ipool));
342 if (!poolp || !poolp->GetEntriesFast() || !poolp->At(0)) return 0;
343 //clear the arrays before the final processing"
344 AliDebug(10,Form("Incomplete: Bin %d (%d)\n",ipool,poolp->GetEntriesFast()));
345 diele->ClearArrays();
346 DoMixing(*poolp,diele);
348 // increase counter for incomplete bins
349 if (diele->fHistos) {
350 //buffer event data and set event data using the first event in this pool
351 Double_t values[AliDielectronVarManager::kNMaxValues]={0};
352 for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues; ++i)
353 values[i]=AliDielectronVarManager::GetValue((AliDielectronVarManager::ValueTypes)i);
355 AliDielectronEvent *ev1=static_cast<AliDielectronEvent*>(poolp->At(0));
356 //use event data from the first event all events are in the same mixing bin anyhow...
357 AliDielectronVarManager::SetEventData(ev1->GetEventData());
359 // fill the histograms
360 diele->FillHistograms(0x0, kTRUE);
361 diele->fHistos->Fill("Mixing","Stats",1);
362 diele->fHistos->Fill("Mixing","InCompletePools",ipool);
363 diele->fHistos->Fill("Mixing","Entries_InCompletePools",poolp->GetEntriesFast());
365 //set back global event values (this would mean set back to zero)
366 //AliDielectronVarManager::SetEventData(values);
372 //______________________________________________
373 void AliDielectronMixingHandler::Init(const AliDielectron *diele)
376 // initialise event buffers
378 Int_t size=GetNumberOfBins();
380 AliDebug(10,Form("Creating a pool array with size %d \n",size));
382 if(diele && diele->DoEventProcess()) fArrPools.Expand(size);
384 //add statics histogram if we have a histogram manager
385 if (diele && diele->fHistos && diele->DoEventProcess()) {
386 diele->fHistos->AddClass("Mixing");
387 diele->fHistos->UserHistogram("Mixing","Stats","Mixing Statistics;;#called bins",2,0,2);
388 TH1* h=diele->fHistos->GetHistogram("Mixing","Stats");
389 h->GetXaxis()->SetBinLabel(1,"Complete");
390 h->GetXaxis()->SetBinLabel(2,"Incomplete");
392 diele->fHistos->UserHistogram("Mixing","CompletePools","Mixing Statistics compete pools;bin;#fills",size,0,size);
393 diele->fHistos->UserHistogram("Mixing","InCompletePools","Mixing Statistics incomplete pools;bin;#fills",size,0,size);
394 diele->fHistos->UserHistogram("Mixing","Entries_InCompletePools","#entries in incomplete pools;entries;#fills",fDepth,0,fDepth);
398 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
399 TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
400 Int_t nRows=bins->GetNrows();
401 values+=Form("%s: ",AliDielectronVarManager::GetValueName(fEventCuts[i]));
402 for (Int_t irow=0; irow<nRows; ++irow){
403 values+=Form("%.2f, ",(*bins)[irow]);
408 fPID=TProcessID::AddProcessID();
411 AliDebug(10,values.Data());
414 //______________________________________________
415 Int_t AliDielectronMixingHandler::GetNumberOfBins() const
418 // return the number of bins this mixing handler has
421 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i)
422 size*=((static_cast<TVectorD*>(fAxes.At(i)))->GetNrows()-1);
426 //______________________________________________
427 Int_t AliDielectronMixingHandler::FindBin(const Double_t values[], TString *dim)
430 // bin bin in mixing stack described by 'values'
431 // if the values are outside the binning range -1 is returned
432 // if dim is non NULL debug info will be stored in the variable
435 if (fAxes.GetEntriesFast()==0) {
436 if (dim) (*dim)="single bin";
442 for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
443 Double_t val=values[fEventCuts[i]];
444 TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
445 Int_t nRows=bins->GetNrows();
446 if ( (val<(*bins)[0]) || (val>(*bins)[nRows-1]) ) {
450 Int_t pos=TMath::BinarySearch(nRows,bins->GetMatrixArray(),val);
452 if (dim) (*dim)+=Form("%s: %f (%d); ",AliDielectronVarManager::GetValueName(fEventCuts[i]),val,pos);
459 //______________________________________________
460 void AliDielectronMixingHandler::MoveToSameVertex(AliVTrack * const vtrack, const Double_t *vFirst, const Double_t* vMix)
463 // move 'track' which belongs to the vertex information of vMix to the vertex of vFirst
466 static Bool_t printed=kFALSE;
468 if (vtrack->IsA()==AliESDtrack::Class()){
469 AliESDtrack *track=(AliESDtrack*)vtrack;
471 //get track information
472 Double_t x = track->GetX();
473 Double_t alpha = track->GetAlpha();
474 Double_t param[5] = {0};
475 Double_t cov[15] = {0};
477 for (Int_t i=0; i<5; ++i) param[i]=track->GetParameter()[i];
478 for (Int_t i=0; i<15; ++i) cov[i] =track->GetCovariance()[i];
481 Double_t vt[3] = {vMix[0]-vFirst[0],vMix[1]-vFirst[1],vMix[2]-vFirst[2]};
482 //rotate to the track frame
483 // track->Global2LocalPosition(vt,track->GetAlpha());
485 //add to track position
487 // param[0] = param[0]-vt[1];
488 // param[1] = param[1]-vt[2];
489 param[1] = param[1]-vt[2];
491 //set updated track information
492 track->Set(x, alpha, param, cov);
494 // AliAODTrack *track=(AliAODTrack*)vtrack;
495 // Double_t pos[3]={0};
496 // track->GetPosition(pos);
497 // if (pos[0]>-999.){
498 // pos[0]=pos[0]-vMix[AliDielectronVarManager::kXvPrim]+vFirst[AliDielectronVarManager::kXvPrim];
499 // pos[1]=pos[1]-vMix[AliDielectronVarManager::kYvPrim]+vFirst[AliDielectronVarManager::kYvPrim];
500 // pos[2]=pos[2]-vMix[AliDielectronVarManager::kZvPrim]+vFirst[AliDielectronVarManager::kZvPrim];
501 // track->SetPosition(pos);
502 // AliError("Move To same vertex not yet implemented for AOD!");
504 // Error("AliDielectronMixingHandler::MoveToSameVertex","Move To same vertex not yet implemented for AOD!");
508 // Not that clear how to do it. In AOD track there is fPosition, fPositionAtDCA and "TRef fProdVertex"
509 // where Xv(), Yv(), Zv() returns the position of fProdVertex