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 // Class AliAnalysisTaskVertexESD
18 // AliAnalysisTask to extract from ESD the information for the analysis
19 // of the primary vertex reconstruction efficiency and resolution
20 // (for MC events) and distributions (for real data). Three vertices:
25 // Author: A.Dainese, andrea.dainese@pd.infn.it
26 //*************************************************************************
32 #include <TClonesArray.h>
33 #include <TObjArray.h>
38 #include "AliAnalysisTask.h"
39 #include "AliAnalysisManager.h"
41 #include "AliMultiplicity.h"
42 #include "AliVertexerTracks.h"
43 #include "AliESDtrack.h"
44 #include "AliExternalTrackParam.h"
45 #include "AliESDVertex.h"
46 #include "AliESDEvent.h"
47 #include "AliESDInputHandler.h"
48 #include "AliTrackReference.h"
49 //#include "AliTriggerAnalysis.h"
51 #include "AliMCEventHandler.h"
52 #include "AliMCEvent.h"
56 #include "AliGenEventHeader.h"
57 #include "AliAnalysisTaskVertexESD.h"
60 ClassImp(AliAnalysisTaskVertexESD)
62 //________________________________________________________________________
63 AliAnalysisTaskVertexESD::AliAnalysisTaskVertexESD(const char *name) :
64 AliAnalysisTaskSE(name),
65 fCheckEventType(kTRUE),
68 fRecoVtxITSTPC(kFALSE),
69 fRecoVtxITSTPCHalfEvent(kFALSE),
70 fOnlyITSTPCTracks(kFALSE),
71 fOnlyITSSATracks(kFALSE),
89 // Define input and output slots here
90 // Output slot #0 writes into a TList container
91 DefineOutput(1, TList::Class()); //My private output
93 //________________________________________________________________________
94 AliAnalysisTaskVertexESD::~AliAnalysisTaskVertexESD()
98 // histograms are in the output list and deleted when the output
99 // list is deleted by the TSelector dtor
108 //________________________________________________________________________
109 void AliAnalysisTaskVertexESD::UserCreateOutputObjects()
114 // Several histograms are more conveniently managed in a TList
118 fNtupleVertexESD = new TNtuple("fNtupleVertexESD","vertices","run:tstamp:bunchcross:triggered:dndygen:xtrue:ytrue:ztrue:xSPD:xerrSPD:ySPD:yerrSPD:zSPD:zerrSPD:ntrksSPD:SPD3D:dphiSPD:xTPC:xerrTPC:yTPC:yerrTPC:zTPC:zerrTPC:ntrksTPC:constrTPC:xTRK:xerrTRK:yTRK:yerrTRK:zTRK:zerrTRK:ntrksTRK:constrTRK:ntrklets:nESDtracks:nITSrefit5or6:nTPCin:nTPCinEta09:SPD0cls:xSPDp:xerrSPDp:ySPDp:yerrSPDp:zSPDp:zerrSPDp:ntrksSPDp:xTPCnc:xerrTPCnc:yTPCnc:yerrTPCnc:zTPCnc:zerrTPCnc:ntrksTPCnc:xTPCc:xerrTPCc:yTPCc:yerrTPCc:zTPCc:zerrTPCc:ntrksTPCc:xTRKnc:xerrTRKnc:yTRKnc:yerrTRKnc:zTRKnc:zerrTRKnc:ntrksTRKnc:xTRKc:xerrTRKc:yTRKc:yerrTRKc:zTRKc:zerrTRKc:ntrksTRKc:deltaxTRKnc:deltayTRKnc:deltazTRKnc:deltaxerrTRKnc:deltayerrTRKnc:deltazerrTRKnc:ntrksEvenTRKnc:ntrksOddTRKnc");
120 fOutput->Add(fNtupleVertexESD);
122 fhSPDVertexX = new TH1F("fhSPDVertexX","SPDVertex x; x vertex [cm]; events",200,-1,1);
123 fOutput->Add(fhSPDVertexX);
124 fhSPDVertexY = new TH1F("fhSPDVertexY","SPDVertex y; y vertex [cm]; events",200,-1,1);
125 fOutput->Add(fhSPDVertexY);
126 fhSPDVertexZ = new TH1F("fhSPDVertexZ","SPDVertex z; z vertex [cm]; events",200,-20,20);
127 fOutput->Add(fhSPDVertexZ);
128 fhTRKVertexX = new TH1F("fhTRKVertexX","TRKVertex x; x vertex [cm]; events",200,-1,1);
129 fOutput->Add(fhTRKVertexX);
130 fhTRKVertexY = new TH1F("fhTRKVertexY","TRKVertex y; y vertex [cm]; events",200,-1,1);
131 fOutput->Add(fhTRKVertexY);
132 fhTRKVertexZ = new TH1F("fhTRKVertexZ","TRKVertex z; z vertex [cm]; events",200,-20,20);
133 fOutput->Add(fhTRKVertexZ);
134 fhTPCVertexX = new TH1F("fhTPCVertexX","TPCVertex x; x vertex [cm]; events",200,-3,3);
135 fOutput->Add(fhTPCVertexX);
136 fhTPCVertexY = new TH1F("fhTPCVertexY","TPCVertex y; y vertex [cm]; events",200,-3,3);
137 fOutput->Add(fhTPCVertexY);
138 fhTPCVertexZ = new TH1F("fhTPCVertexZ","TPCVertex z; z vertex [cm]; events",200,-20,20);
139 fOutput->Add(fhTPCVertexZ);
141 fhTrackRefs = new TH2F("fhTrackRefs","Track references; x; y",1000,-4,4,1000,-4,4);
142 fOutput->Add(fhTrackRefs);
147 //________________________________________________________________________
148 void AliAnalysisTaskVertexESD::UserExec(Option_t *)
151 // Called for each event
154 Printf("ERROR: fESD not available");
157 AliESDEvent* esdE = (AliESDEvent*) InputEvent();
159 if(fCheckEventType && (esdE->GetEventType())!=7) return;
163 mcVertex[0]=9999.; mcVertex[1]=9999.; mcVertex[2]=9999.;
164 Float_t dNchdy=-999.;
165 // *********** MC info ***************
167 AliMCEventHandler* eventHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
169 Printf("ERROR: Could not retrieve MC event handler");
173 AliMCEvent* mcEvent = eventHandler->MCEvent();
175 Printf("ERROR: Could not retrieve MC event");
179 AliStack* stack = mcEvent->Stack();
181 AliDebug(AliLog::kError, "Stack not available");
185 AliHeader* header = mcEvent->Header();
187 AliDebug(AliLog::kError, "Header not available");
190 AliGenEventHeader* genHeader = header->GenEventHeader();
191 genHeader->PrimaryVertex(mcVertex);
193 Int_t ngenpart = (Int_t)stack->GetNtrack();
194 //printf("# generated particles = %d\n",ngenpart);
196 for(Int_t ip=0; ip<ngenpart; ip++) {
197 TParticle* part = (TParticle*)stack->Particle(ip);
198 // keep only electorns, muons, pions, kaons and protons
199 Int_t apdg = TMath::Abs(part->GetPdgCode());
200 if(apdg!=11 && apdg!=13 && apdg!=211 && apdg!=321 && apdg!=2212) continue;
201 // reject secondaries
202 if(TMath::Sqrt((part->Vx()-mcVertex[0])*(part->Vx()-mcVertex[0])+(part->Vy()-mcVertex[1])*(part->Vy()-mcVertex[1]))>0.0010) continue;
203 // reject incoming protons
204 Double_t energy = part->Energy();
205 if(energy>900.) continue;
206 Double_t pz = part->Pz();
207 Double_t y = 0.5*TMath::Log((energy+pz+1.e-13)/(energy-pz+1.e-13));
208 if(TMath::Abs(y)<1.0) dNchdy += 0.5; // count 1/2 of particles in |y|<1
210 TClonesArray *trefs=0;
211 Int_t ntrefs = mcEvent->GetParticleAndTR(ip,part,trefs);
212 if(ntrefs<0) continue;
213 for(Int_t iref=0; iref<ntrefs; iref++) {
214 AliTrackReference *tref = (AliTrackReference*)trefs->At(iref);
215 if(tref->R()>10.) continue;
216 fhTrackRefs->Fill(tref->X(),tref->Y());
219 //printf("# primary particles = %7.1f\n",dNchdy);
221 // *********** MC info ***************
225 //ULong64_t triggerMask;
226 //ULong64_t spdFO = (1 << 14);
227 //ULong64_t v0left = (1 << 10);
228 //ULong64_t v0right = (1 << 11);
230 //triggerMask=esdE->GetTriggerMask();
231 // MB1: SPDFO || V0L || V0R
232 //Bool_t eventTriggered = (triggerMask & spdFO || ((triggerMask & v0left) || (triggerMask & v0right)));
234 //triggerMask & spdFO && ((triggerMask&v0left) || (triggerMask&v0right))
235 //Bool_t eventTriggered = (triggerMask & spdFO);
237 //static AliTriggerAnalysis* triggerAnalysis = new AliTriggerAnalysis();
238 Bool_t eventTriggered = 0;//triggerAnalysis->IsTriggerFired(esdE, AliTriggerAnalysis::kSPDGFO /*| AliTriggerAnalysis::kOfflineFlag*/);
240 // use response of AliPhysicsSelection
241 eventTriggered = ((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected();
243 Int_t ntracks = esdE->GetNumberOfTracks();
244 Int_t nITS5or6=0,nTPCin=0,nTPCinEta09=0;
245 //printf("Tracks # = %d\n",esdE->GetNumberOfTracks());
246 for(Int_t itr=0; itr<ntracks; itr++) {
247 AliESDtrack *t = esdE->GetTrack(itr);
248 if(t->GetNcls(0)>=5) nITS5or6++;
249 Double_t z0; t->GetZAt(0,esdE->GetMagneticField(),z0);
250 if(t->GetNcls(1)>0 && TMath::Abs(t->GetD(0,0,esdE->GetMagneticField()))<2.8 && TMath::Abs(z0)<20) {
252 if(TMath::Abs(t->GetTgl())<1.5) nTPCinEta09++;
257 const AliESDVertex *spdv=esdE->GetPrimaryVertexSPD();
258 const AliESDVertex *spdvp=esdE->GetPileupVertexSPD(0);
259 const AliESDVertex *tpcv=esdE->GetPrimaryVertexTPC();
260 const AliESDVertex *trkv=esdE->GetPrimaryVertexTracks();
262 const AliMultiplicity *alimult = esdE->GetMultiplicity();
263 Int_t ntrklets=0,spd0cls=0;
265 ntrklets = alimult->GetNumberOfTracklets();
266 for(Int_t l=0;l<alimult->GetNumberOfTracklets();l++){
267 if(alimult->GetDeltaPhi(l)<-9998.) ntrklets--;
269 spd0cls = alimult->GetNumberOfSingleClusters()+ntrklets;
275 if(spdv->GetNContributors()>0) {
276 TString title=spdv->GetTitle();
277 if(title.Contains("3D")) {
278 fhSPDVertexX->Fill(spdv->GetXv());
279 fhSPDVertexY->Fill(spdv->GetYv());
281 fhSPDVertexZ->Fill(spdv->GetZv());
286 if(trkv->GetNContributors()>0) {
287 fhTRKVertexX->Fill(trkv->GetXv());
288 fhTRKVertexY->Fill(trkv->GetYv());
289 fhTRKVertexZ->Fill(trkv->GetZv());
294 if(tpcv->GetNContributors()>0) {
295 fhTPCVertexX->Fill(tpcv->GetXv());
296 fhTPCVertexY->Fill(tpcv->GetYv());
297 fhTPCVertexZ->Fill(tpcv->GetZv());
304 Float_t expile=-999.;
305 Float_t eypile=-999.;
306 Float_t ezpile=-999.;
309 if(esdE->GetNumberOfPileupVerticesSPD()>0 && spdvp){
310 xpile=spdvp->GetXv();
311 expile=spdvp->GetXRes();
312 ypile=spdvp->GetYv();
313 eypile=spdvp->GetYRes();
314 zpile=spdvp->GetZv();
315 ezpile=spdvp->GetZRes();
316 ntrkspile=spdvp->GetNContributors();
321 Float_t xnt[82]; for(Int_t iii=0;iii<isize;iii++) xnt[iii]=0.;
325 xnt[index++]=(Float_t)esdE->GetRunNumber();
326 xnt[index++]=(Float_t)esdE->GetTimeStamp();
327 xnt[index++]=(Float_t)esdE->GetBunchCrossNumber();
328 xnt[index++]=(eventTriggered ? 1. : 0.);
330 xnt[index++]=(Float_t)dNchdy;
333 xnt[index++]=mcVertex[0];
334 xnt[index++]=mcVertex[1];
335 xnt[index++]=mcVertex[2];
337 xnt[index++]=spdv->GetXv();
338 xnt[index++]=spdv->GetXRes();
339 xnt[index++]=spdv->GetYv();
340 xnt[index++]=spdv->GetYRes();
341 xnt[index++]=spdv->GetZv();
342 xnt[index++]=spdv->GetZRes();
343 xnt[index++]=spdv->GetNContributors();
344 TString spdtitle = spdv->GetTitle();
345 xnt[index++]=(spdtitle.Contains("vertexer: 3D") ? 1. : 0.);
346 xnt[index++]=spdv->GetDispersion();
348 xnt[index++]=tpcv->GetXv();
349 xnt[index++]=tpcv->GetXRes();
350 xnt[index++]=tpcv->GetYv();
351 xnt[index++]=tpcv->GetYRes();
352 xnt[index++]=tpcv->GetZv();
353 xnt[index++]=tpcv->GetZRes();
354 xnt[index++]=tpcv->GetNContributors();
355 TString tpctitle = tpcv->GetTitle();
356 xnt[index++]=(tpctitle.Contains("WithConstraint") ? 1. : 0.);
358 xnt[index++]=trkv->GetXv();
359 xnt[index++]=trkv->GetXRes();
360 xnt[index++]=trkv->GetYv();
361 xnt[index++]=trkv->GetYRes();
362 xnt[index++]=trkv->GetZv();
363 xnt[index++]=trkv->GetZRes();
364 xnt[index++]=trkv->GetNContributors();// tpccontrorig;
365 TString trktitle = trkv->GetTitle();
366 xnt[index++]=(trktitle.Contains("WithConstraint") ? 1. : 0.);
368 xnt[index++]=float(ntrklets);
369 xnt[index++]=float(ntracks);
370 xnt[index++]=float(nITS5or6);
371 xnt[index++]=float(nTPCin);
372 xnt[index++]=float(nTPCinEta09);
374 xnt[index++]=spd0cls;
382 xnt[index++]=(Float_t)ntrkspile;
386 // add recalculated vertices TRK and TPC
389 AliESDVertex *tpcvnc = ReconstructPrimaryVertexTPC(kFALSE);
390 xnt[index++]=tpcvnc->GetXv();
391 xnt[index++]=tpcvnc->GetXRes();
392 xnt[index++]=tpcvnc->GetYv();
393 xnt[index++]=tpcvnc->GetYRes();
394 xnt[index++]=tpcvnc->GetZv();
395 xnt[index++]=tpcvnc->GetZRes();
396 xnt[index++]=tpcvnc->GetNContributors();
397 delete tpcvnc; tpcvnc=0;
399 AliESDVertex *tpcvc = ReconstructPrimaryVertexTPC(kTRUE);
400 xnt[index++]=tpcvc->GetXv();
401 xnt[index++]=tpcvc->GetXRes();
402 xnt[index++]=tpcvc->GetYv();
403 xnt[index++]=tpcvc->GetYRes();
404 xnt[index++]=tpcvc->GetZv();
405 xnt[index++]=tpcvc->GetZRes();
406 xnt[index++]=tpcvc->GetNContributors();
407 delete tpcvc; tpcvc=0;
411 AliESDVertex *trkvnc = ReconstructPrimaryVertexITSTPC(kFALSE);
412 xnt[index++]=trkvnc->GetXv();
413 xnt[index++]=trkvnc->GetXRes();
414 xnt[index++]=trkvnc->GetYv();
415 xnt[index++]=trkvnc->GetYRes();
416 xnt[index++]=trkvnc->GetZv();
417 xnt[index++]=trkvnc->GetZRes();
418 xnt[index++]=trkvnc->GetNContributors();
419 delete trkvnc; trkvnc=0;
421 AliESDVertex *trkvc = ReconstructPrimaryVertexITSTPC(kTRUE);
422 xnt[index++]=trkvc->GetXv();
423 xnt[index++]=trkvc->GetXRes();
424 xnt[index++]=trkvc->GetYv();
425 xnt[index++]=trkvc->GetYRes();
426 xnt[index++]=trkvc->GetZv();
427 xnt[index++]=trkvc->GetZRes();
428 xnt[index++]=trkvc->GetNContributors();
429 delete trkvc; trkvc=0;
432 if(fRecoVtxITSTPCHalfEvent) {
433 AliESDVertex *trkvncodd = ReconstructPrimaryVertexITSTPC(kFALSE,1);
434 AliESDVertex *trkvnceven = ReconstructPrimaryVertexITSTPC(kFALSE,2);
435 if(trkvncodd->GetNContributors()>0 &&
436 trkvnceven->GetNContributors()>0) {
437 xnt[index++]=trkvncodd->GetXv()-trkvnceven->GetXv();
438 xnt[index++]=trkvncodd->GetYv()-trkvnceven->GetYv();
439 xnt[index++]=trkvncodd->GetZv()-trkvnceven->GetZv();
440 xnt[index++]=TMath::Sqrt(trkvncodd->GetXRes()*trkvncodd->GetXRes()+trkvnceven->GetXRes()*trkvnceven->GetXRes());
441 xnt[index++]=TMath::Sqrt(trkvncodd->GetYRes()*trkvncodd->GetYRes()+trkvnceven->GetYRes()*trkvnceven->GetYRes());
442 xnt[index++]=TMath::Sqrt(trkvncodd->GetZRes()*trkvncodd->GetZRes()+trkvnceven->GetZRes()*trkvnceven->GetZRes());
443 xnt[index++]=trkvnceven->GetNContributors();
444 xnt[index++]=trkvncodd->GetNContributors();
455 delete trkvncodd; trkvncodd=0;
456 delete trkvnceven; trkvnceven=0;
460 if(index>isize) printf("AliAnalysisTaskVertexESD: ERROR, index!=isize\n");
461 if(fFillNtuple) fNtupleVertexESD->Fill(xnt);
463 // Post the data already here
464 PostData(1, fOutput);
469 //________________________________________________________________________
470 void AliAnalysisTaskVertexESD::Terminate(Option_t *)
472 // Draw result to the screen
473 // Called once at the end of the query
474 fOutput = dynamic_cast<TList*> (GetOutputData(1));
476 Printf("ERROR: fOutput not available");
480 fNtupleVertexESD = dynamic_cast<TNtuple*>(fOutput->FindObject("fNtupleVertexESD"));
485 //_________________________________________________________________________
486 AliESDVertex* AliAnalysisTaskVertexESD::ReconstructPrimaryVertexTPC(Bool_t constr) const {
487 // On the fly reco of TPC vertex from ESD
488 AliESDEvent* evt = (AliESDEvent*) fInputEvent;
489 AliVertexerTracks vertexer(evt->GetMagneticField());
490 vertexer.SetTPCMode(); // defaults
491 Float_t diamondcovxy[3]; evt->GetDiamondCovXY(diamondcovxy);
492 Double_t pos[3]={evt->GetDiamondX(),evt->GetDiamondY(),0};
493 Double_t cov[6]={diamondcovxy[0],diamondcovxy[1],diamondcovxy[2],0.,0.,10.*10.};
494 AliESDVertex *initVertex = new AliESDVertex(pos,cov,1.,1);
495 vertexer.SetVtxStart(initVertex);
497 if(!constr) vertexer.SetConstraintOff();
499 return vertexer.FindPrimaryVertex(evt);
502 //_________________________________________________________________________
503 AliESDVertex* AliAnalysisTaskVertexESD::ReconstructPrimaryVertexITSTPC(Bool_t constr,Int_t mode) const {
504 // On the fly reco of ITS+TPC vertex from ESD
505 // mode=0 use all tracks
506 // mode=1 use odd-number tracks
507 // mode=2 use even-number tracks
509 AliESDEvent* evt = (AliESDEvent*) fInputEvent;
510 AliVertexerTracks vertexer(evt->GetMagneticField());
511 vertexer.SetITSMode(); // defaults
512 vertexer.SetMinClusters(4); // default is 5
513 Float_t diamondcovxy[3]; evt->GetDiamondCovXY(diamondcovxy);
514 Double_t pos[3]={evt->GetDiamondX(),evt->GetDiamondY(),0};
515 Double_t cov[6]={diamondcovxy[0],diamondcovxy[1],diamondcovxy[2],0.,0.,10.*10.};
516 AliESDVertex *initVertex = new AliESDVertex(pos,cov,1.,1);
517 vertexer.SetVtxStart(initVertex);
519 if(!constr) vertexer.SetConstraintOff();
521 // use only ITS-TPC or only ITS-SA tracks
522 if(fOnlyITSTPCTracks || fOnlyITSSATracks || mode>0) {
524 Int_t *skip = new Int_t[evt->GetNumberOfTracks()];
525 for(Int_t itr=0;itr<evt->GetNumberOfTracks(); itr++) {
526 AliESDtrack* track = evt->GetTrack(itr);
527 if(fOnlyITSTPCTracks && track->GetNcls(1)==0) { // skip ITSSA
531 if(fOnlyITSSATracks && track->GetNcls(1)>0) { // skip ITSTPC
535 if(mode==1 && itr%2==0) skip[iskip++]=itr;
536 if(mode==2 && itr%2==1) skip[iskip++]=itr;
538 vertexer.SetSkipTracks(iskip,skip);
539 delete [] skip; skip=NULL;
542 return vertexer.FindPrimaryVertex(evt);