1 /**************************************************************************
2 * Copyright(c) 1998-2006, 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 **************************************************************************/
18 /////////////////////////////////////////////////////////////
20 // Base class for AOD reconstructed heavy-flavour decay
22 // Author: A.Dainese, andrea.dainese@lnl.infn.it
23 /////////////////////////////////////////////////////////////
25 #include <TDatabasePDG.h>
28 #include "AliAODRecoDecay.h"
29 #include "AliAODRecoDecayHF.h"
30 #include "AliAODEvent.h"
31 #include "AliVertexerTracks.h"
32 #include "AliExternalTrackParam.h"
33 #include "AliKFVertex.h"
34 #include "AliVVertex.h"
35 #include "AliESDVertex.h"
37 ClassImp(AliAODRecoDecayHF)
39 //--------------------------------------------------------------------------
40 AliAODRecoDecayHF::AliAODRecoDecayHF() :
50 // Default Constructor
53 //--------------------------------------------------------------------------
54 AliAODRecoDecayHF::AliAODRecoDecayHF(AliAODVertex *vtx2,Int_t nprongs,Short_t charge,
55 Double_t *px,Double_t *py,Double_t *pz,
56 Double_t *d0,Double_t *d0err) :
57 AliAODRecoDecay(vtx2,nprongs,charge,px,py,pz,d0),
66 // Constructor with AliAODVertex for decay vertex
68 fd0err = new Double_t[GetNProngs()];
69 for(Int_t i=0; i<GetNProngs(); i++) fd0err[i] = d0err[i];
71 //--------------------------------------------------------------------------
72 AliAODRecoDecayHF::AliAODRecoDecayHF(AliAODVertex *vtx2,Int_t nprongs,Short_t charge,
73 Double_t *d0,Double_t *d0err) :
74 AliAODRecoDecay(vtx2,nprongs,charge,d0),
83 // Constructor with AliAODVertex for decay vertex and without prongs momenta
85 fd0err = new Double_t[GetNProngs()];
86 for(Int_t i=0; i<GetNProngs(); i++) fd0err[i] = d0err[i];
88 //--------------------------------------------------------------------------
89 AliAODRecoDecayHF::AliAODRecoDecayHF(Double_t vtx1[3],Double_t vtx2[3],
90 Int_t nprongs,Short_t charge,
91 Double_t *px,Double_t *py,Double_t *pz,
93 AliAODRecoDecay(0x0,nprongs,charge,px,py,pz,d0),
102 // Constructor that can used for a "MC" object
105 fOwnPrimaryVtx = new AliAODVertex(vtx1);
107 AliAODVertex *vtx = new AliAODVertex(vtx2);
108 SetOwnSecondaryVtx(vtx);
111 //--------------------------------------------------------------------------
112 AliAODRecoDecayHF::AliAODRecoDecayHF(const AliAODRecoDecayHF &source) :
113 AliAODRecoDecay(source),
115 fEventPrimaryVtx(source.fEventPrimaryVtx),
116 fListOfCuts(source.fListOfCuts),
119 fSelectionMap(source.fSelectionMap)
124 if(source.GetOwnPrimaryVtx()) fOwnPrimaryVtx = new AliAODVertex(*(source.GetOwnPrimaryVtx()));
126 if(source.GetNProngs()>0) {
127 fd0err = new Double_t[GetNProngs()];
128 memcpy(fd0err,source.fd0err,GetNProngs()*sizeof(Double_t));
129 if(source.fProngID) {
130 fProngID = new UShort_t[GetNProngs()];
131 memcpy(fProngID,source.fProngID,GetNProngs()*sizeof(UShort_t));
135 //--------------------------------------------------------------------------
136 AliAODRecoDecayHF &AliAODRecoDecayHF::operator=(const AliAODRecoDecayHF &source)
139 // assignment operator
141 if(&source == this) return *this;
143 AliAODRecoDecay::operator=(source);
145 fEventPrimaryVtx = source.fEventPrimaryVtx;
146 fListOfCuts = source.fListOfCuts;
147 fSelectionMap = source.fSelectionMap;
149 if(source.GetOwnPrimaryVtx()) {
150 delete fOwnPrimaryVtx;
151 fOwnPrimaryVtx = new AliAODVertex(*(source.GetOwnPrimaryVtx()));
154 if(source.GetNProngs()>0) {
157 fd0err = new Double_t[GetNProngs()];
158 memcpy(fd0err,source.fd0err,GetNProngs()*sizeof(Double_t));
160 if(source.fProngID) {
162 fProngID = new UShort_t[GetNProngs()];
163 memcpy(fProngID,source.fProngID,GetNProngs()*sizeof(UShort_t));
168 //--------------------------------------------------------------------------
169 AliAODRecoDecayHF::~AliAODRecoDecayHF() {
171 // Default Destructor
173 if(fOwnPrimaryVtx) delete fOwnPrimaryVtx;
174 if(fd0err) delete [] fd0err;
175 if(fProngID) delete [] fProngID;
177 //---------------------------------------------------------------------------
178 AliKFParticle *AliAODRecoDecayHF::ApplyVertexingKF(Int_t *iprongs,Int_t nprongs,Int_t *pdgs,Bool_t topoCostraint, Double_t bzkG, Double_t *mass) const {
180 // Applies the KF vertexer
181 // Int_t iprongs[nprongs] = indices of the prongs to be used from the vertexer
182 // Int_t pdgs[nprongs] = pdgs assigned to the prongs, needed to define the AliKFParticle
183 // Bool_t topoCostraint = if kTRUE, the topological constraint is applied
184 // Double_t bzkG = magnetic field
185 // Double_t mass[2] = {mass, sigma} for the mass constraint (if mass[0]>0 the constraint is applied).
188 AliKFParticle::SetField(bzkG);
189 AliKFParticle *vertexKF=0;
192 Int_t nt=0,ntcheck=0;
194 Double_t pos[3]={0.,0.,0.};
195 if(!fOwnPrimaryVtx) {
196 printf("AliAODRecoDecayHF::ApplyVertexingKF(): cannot apply because primary vertex is not found\n");
199 fOwnPrimaryVtx->GetXYZ(pos);
200 Int_t contr=fOwnPrimaryVtx->GetNContributors();
201 Double_t covmatrix[6]={0.,0.,0.,0.,0.,0.};
202 fOwnPrimaryVtx->GetCovarianceMatrix(covmatrix);
203 Double_t chi2=fOwnPrimaryVtx->GetChi2();
204 AliESDVertex primaryVtx2(pos,covmatrix,chi2,contr,"Vertex");
208 copyKF=AliKFVertex(primaryVtx2);
209 nt=primaryVtx2.GetNContributors();
213 vertexKF = new AliKFParticle();
214 for(Int_t i= 0;i<nprongs;i++){
215 Int_t ipr=iprongs[i];
216 AliAODTrack *aodTrack = (AliAODTrack*)GetDaughter(ipr);
218 printf("AliAODRecoDecayHF::ApplyVertexingKF(): no daughters available\n");
219 delete vertexKF; vertexKF=NULL;
222 AliKFParticle daughterKF(*aodTrack,pdgs[i]);
223 vertexKF->AddDaughter(daughterKF);
225 if(topoCostraint && nt>0){
226 //Int_t index=(Int_t)GetProngID(ipr);
227 if(!aodTrack->GetUsedForPrimVtxFit()) continue;
228 copyKF -= daughterKF;
235 copyKF += (*vertexKF);
236 vertexKF->SetProductionVertex(copyKF);
241 vertexKF->SetMassConstraint(mass[0],mass[1]);
246 //---------------------------------------------------------------------------
247 AliAODVertex* AliAODRecoDecayHF::RemoveDaughtersFromPrimaryVtx(AliAODEvent *aod) {
249 // This method returns a primary vertex without the daughter tracks of the
250 // candidate and it recalculates the impact parameters and errors.
252 // The output vertex is created with "new". The user has to
253 // set it to the candidate with SetOwnPrimaryVtx(), unset it at the end
254 // of processing with UnsetOwnPrimaryVtx() and delete it.
255 // If a NULL pointer is returned, the removal failed (too few tracks left).
257 // For the moment, the primary vertex is recalculated from scratch without
258 // the daughter tracks.
261 AliAODVertex *vtxAOD = aod->GetPrimaryVertex();
262 if(!vtxAOD) return 0;
263 TString title=vtxAOD->GetTitle();
264 if(!title.Contains("VertexerTracks")) return 0;
268 AliVertexerTracks *vertexer = new AliVertexerTracks(aod->GetMagneticField());
270 Int_t ndg = GetNDaughters();
272 vertexer->SetITSMode();
273 vertexer->SetMinClusters(3);
274 vertexer->SetConstraintOff();
276 if(title.Contains("WithConstraint")) {
277 Float_t diamondcovxy[3];
278 aod->GetDiamondCovXY(diamondcovxy);
279 Double_t pos[3]={aod->GetDiamondX(),aod->GetDiamondY(),0.};
280 Double_t cov[6]={diamondcovxy[0],diamondcovxy[1],diamondcovxy[2],0.,0.,10.*10.};
281 AliESDVertex *diamond = new AliESDVertex(pos,cov,1.,1);
282 vertexer->SetVtxStart(diamond);
283 delete diamond; diamond=NULL;
286 Int_t skipped[10]; for(Int_t i=0;i<10;i++) skipped[i]=-1;
287 Int_t nTrksToSkip=0,id;
289 for(Int_t i=0; i<ndg; i++) {
290 t = (AliAODTrack*)GetDaughter(i);
291 id = (Int_t)t->GetID();
293 skipped[nTrksToSkip++] = id;
295 vertexer->SetSkipTracks(nTrksToSkip,skipped);
296 AliESDVertex *vtxESDNew = vertexer->FindPrimaryVertex(aod);
298 delete vertexer; vertexer=NULL;
300 if(!vtxESDNew) return 0;
301 if(vtxESDNew->GetNContributors()<=0) {
302 delete vtxESDNew; vtxESDNew=NULL;
306 // convert to AliAODVertex
307 Double_t pos[3],cov[6],chi2perNDF;
308 vtxESDNew->GetXYZ(pos); // position
309 vtxESDNew->GetCovMatrix(cov); //covariance matrix
310 chi2perNDF = vtxESDNew->GetChi2toNDF();
311 delete vtxESDNew; vtxESDNew=NULL;
313 AliAODVertex *vtxAODNew = new AliAODVertex(pos,cov,chi2perNDF);
315 RecalculateImpPars(vtxAODNew,aod);
319 //-----------------------------------------------------------------------------------
320 void AliAODRecoDecayHF::RecalculateImpPars(AliAODVertex *vtxAODNew,AliAODEvent* aod) {
322 // now recalculate the daughters impact parameters
324 Double_t dz[2],covdz[3];
325 for(Int_t i=0; i<GetNDaughters(); i++) {
326 AliAODTrack *t = (AliAODTrack*)GetDaughter(i);
327 AliExternalTrackParam etp; etp.CopyFromVTrack(t);
328 if(etp.PropagateToDCA(vtxAODNew,aod->GetMagneticField(),3.,dz,covdz)) {
330 fd0err[i] = TMath::Sqrt(covdz[0]);
336 //-----------------------------------------------------------------------------------
337 void AliAODRecoDecayHF::Misalign(TString misal) {
339 // Method to smear the impact parameter of the duaghter tracks
340 // and the sec. vtx position accordinlgy
341 // Useful to study effect of misalignment.
342 // The starting point are parameterisations of the impact parameter resolution
344 // Errors on d0 and vtx are not recalculated (to be done)
346 if(misal=="null")return;
347 Double_t pard0rphiMC[3]={36.7,36.,1.25};// d0(pt)=[0]+[1]/(pt^[2]); in micron, conversion to cm is done later
348 Double_t pard0rphimisal[3]={0,0,0};
349 Double_t pard0zMC[3]={85.,130.,0.7};// d0(pt)=[0]+[1]/(pt^[2]); in micron, conversion to cm is done later
350 Double_t pard0zmisal[3]={0,0,0};
352 //use this to reproduce data d0(pt) trend for pions
353 pard0rphimisal[0]=37.;
354 pard0rphimisal[1]=37.5;
355 pard0rphimisal[2]=1.25;
360 else if(misal=="resB") {
361 // temporary values: asymptotic value larger by a factor 1.2 w.r.t. MC
362 pard0rphimisal[0]=44.4;
363 pard0rphimisal[1]=37.5;
364 pard0rphimisal[2]=1.25;
365 pard0zmisal[0]=115.2;
369 else if(misal=="resC") {
370 // temporary values: slightly larger asymptotic value, larger values at low pt
371 pard0rphimisal[0]=40.;
372 pard0rphimisal[1]=40.;
373 pard0rphimisal[2]=1.3;
378 else printf("AliAODRecoDecayHF::Misalign(): wrong misalign type specified \n");
381 AliAODVertex *evVtx=0x0,*secVtx=0x0;
382 Double_t evVtxPos[3]={-9999.,-9999.,-9999.},secVtxPos[3]={-9999.,9999.,9999.};
383 if(fOwnPrimaryVtx)fOwnPrimaryVtx->GetXYZ(evVtxPos);
385 evVtx=(AliAODVertex*)(fEventPrimaryVtx.GetObject());
386 evVtx->GetXYZ(evVtxPos);
388 secVtx=(AliAODVertex*)GetSecondaryVtx();
389 secVtx->GetXYZ(secVtxPos);
391 TVector3 v2v1(secVtxPos[0]-evVtxPos[0],secVtxPos[1]-evVtxPos[1],0.);
393 Double_t sigmarphinull,sigmarphimisal,sigmarphiadd;
394 Double_t sigmaznull,sigmazmisal,sigmazadd;
395 Double_t deltad0rphi[10],deltad0z[10];
397 // loop on the two prongs
398 for(Int_t i=0; i<fNProngs; i++) {
399 sigmarphinull = pard0rphiMC[0]+pard0rphiMC[1]/TMath::Power(PtProng(i),pard0rphiMC[2]);
400 sigmarphimisal = pard0rphimisal[0]+pard0rphimisal[1]/TMath::Power(PtProng(i),pard0rphimisal[2]);
401 if(sigmarphimisal>sigmarphinull) {
402 sigmarphiadd = TMath::Sqrt(sigmarphimisal*sigmarphimisal-
403 sigmarphinull*sigmarphinull);
404 deltad0rphi[i] = gRandom->Gaus(0.,sigmarphiadd);
409 sigmaznull = pard0zMC[0]+pard0zMC[1]/TMath::Power(PtProng(i),pard0zMC[2]);
410 sigmazmisal = pard0zmisal[0]+pard0zmisal[1]/TMath::Power(PtProng(i),pard0zmisal[2]);
411 if(sigmazmisal>sigmaznull) {
412 sigmazadd = TMath::Sqrt(sigmazmisal*sigmazmisal-
413 sigmaznull*sigmaznull);
414 deltad0z[i] = gRandom->Gaus(0.,sigmazadd);
419 TVector3 pxy(fPx[i],fPy[i],0.);
420 TVector3 pxycrossv2v1=pxy.Cross(v2v1);
421 if( pxycrossv2v1.Z()*fd0[i] > 0 ) {
422 secVtxPos[0]+=1.e-4*deltad0rphi[i]*(-fPy[i])/PtProng(i);// e-4: conversion to cm
423 secVtxPos[1]+=1.e-4*deltad0rphi[i]*(+fPx[i])/PtProng(i);
425 secVtxPos[0]+=1.e-4*deltad0rphi[i]*(+fPy[i])/PtProng(i);
426 secVtxPos[1]+=1.e-4*deltad0rphi[i]*(-fPx[i])/PtProng(i);
430 fd0[i] += 1.e-4*deltad0rphi[i]; // e-4: conversion to cm
431 // change secondary vertex z
432 secVtxPos[2]+=0.5e-4*deltad0z[i];
434 secVtx->SetX(secVtxPos[0]);
435 secVtx->SetY(secVtxPos[1]);
436 secVtx->SetZ(secVtxPos[2]);