1 /**************************************************************************
2 * Copyright(c) 1998-2007, 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 //----------------------------------------------------------------------------
19 // Implementation of the heavy-flavour vertexing analysis class
20 // Candidates are stored in the AOD as objects deriving from AliAODRecoDecay.
21 // To be used as a task of AliAnalysisManager by means of the interface
22 // class AliAnalysisTaskSEVertexingHF.
23 // An example of usage in the macro AliAnalysisTaskSEVertexingHFTest.C.
25 // Contact: andrea.dainese@pd.infn.it
26 // Contributors: E.Bruna, G.E.Bruno, A.Dainese, C.Di Gliglio,
27 // F.Prino, R.Romita, X.M.Zhang
28 //----------------------------------------------------------------------------
29 #include <Riostream.h>
31 #include <TDatabasePDG.h>
35 #include "AliVEvent.h"
36 #include "AliVVertex.h"
37 #include "AliVTrack.h"
38 #include "AliVertexerTracks.h"
39 #include "AliKFVertex.h"
40 #include "AliESDEvent.h"
41 #include "AliESDVertex.h"
42 #include "AliExternalTrackParam.h"
43 #include "AliNeutralTrackParam.h"
44 #include "AliESDtrack.h"
45 #include "AliESDtrackCuts.h"
46 #include "AliAODEvent.h"
47 #include "AliAODRecoDecay.h"
48 #include "AliAODRecoDecayHF.h"
49 #include "AliAODRecoDecayHF2Prong.h"
50 #include "AliAODRecoDecayHF3Prong.h"
51 #include "AliAODRecoDecayHF4Prong.h"
52 #include "AliAODRecoCascadeHF.h"
53 #include "AliRDHFCutsD0toKpi.h"
54 #include "AliRDHFCutsJpsitoee.h"
55 #include "AliRDHFCutsDplustoKpipi.h"
56 #include "AliRDHFCutsDstoKKpi.h"
57 #include "AliRDHFCutsLctopKpi.h"
58 #include "AliRDHFCutsLctoV0.h"
59 #include "AliRDHFCutsD0toKpipipi.h"
60 #include "AliRDHFCutsDStartoKpipi.h"
61 #include "AliAnalysisFilter.h"
62 #include "AliAnalysisVertexingHF.h"
63 #include "AliMixedEvent.h"
67 ClassImp(AliAnalysisVertexingHF)
69 //----------------------------------------------------------------------------
70 AliAnalysisVertexingHF::AliAnalysisVertexingHF():
75 fSecVtxWithKF(kFALSE),
76 fRecoPrimVtxSkippingTrks(kFALSE),
77 fRmTrksFromPrimVtx(kFALSE),
88 fTrackFilterSoftPi(0x0),
91 fCutsDplustoKpipi(0x0),
95 fCutsD0toKpipipi(0x0),
96 fCutsDStartoKpipi(0x0),
98 fFindVertexForDstar(kTRUE),
99 fFindVertexForCascades(kTRUE),
100 fMassCutBeforeVertexing(kFALSE),
105 // Default constructor
107 Double_t d02[2],d03[3],d04[4];
108 fMassCalc2 = new AliAODRecoDecay(0x0,2,0,d02);
109 fMassCalc3 = new AliAODRecoDecay(0x0,3,1,d03);
110 fMassCalc4 = new AliAODRecoDecay(0x0,4,0,d04);
113 //--------------------------------------------------------------------------
114 AliAnalysisVertexingHF::AliAnalysisVertexingHF(const AliAnalysisVertexingHF &source) :
116 fInputAOD(source.fInputAOD),
117 fAODMapSize(source.fAODMapSize),
118 fAODMap(source.fAODMap),
120 fSecVtxWithKF(source.fSecVtxWithKF),
121 fRecoPrimVtxSkippingTrks(source.fRecoPrimVtxSkippingTrks),
122 fRmTrksFromPrimVtx(source.fRmTrksFromPrimVtx),
124 fD0toKpi(source.fD0toKpi),
125 fJPSItoEle(source.fJPSItoEle),
126 f3Prong(source.f3Prong),
127 f4Prong(source.f4Prong),
128 fDstar(source.fDstar),
129 fCascades(source.fCascades),
130 fLikeSign(source.fLikeSign),
131 fMixEvent(source.fMixEvent),
132 fTrackFilter(source.fTrackFilter),
133 fTrackFilterSoftPi(source.fTrackFilterSoftPi),
134 fCutsD0toKpi(source.fCutsD0toKpi),
135 fCutsJpsitoee(source.fCutsJpsitoee),
136 fCutsDplustoKpipi(source.fCutsDplustoKpipi),
137 fCutsDstoKKpi(source.fCutsDstoKKpi),
138 fCutsLctopKpi(source.fCutsLctopKpi),
139 fCutsLctoV0(source.fCutsLctoV0),
140 fCutsD0toKpipipi(source.fCutsD0toKpipipi),
141 fCutsDStartoKpipi(source.fCutsDStartoKpipi),
142 fListOfCuts(source.fListOfCuts),
143 fFindVertexForDstar(source.fFindVertexForDstar),
144 fFindVertexForCascades(source.fFindVertexForCascades),
145 fMassCutBeforeVertexing(source.fMassCutBeforeVertexing),
146 fMassCalc2(source.fMassCalc2),
147 fMassCalc3(source.fMassCalc3),
148 fMassCalc4(source.fMassCalc4)
154 //--------------------------------------------------------------------------
155 AliAnalysisVertexingHF &AliAnalysisVertexingHF::operator=(const AliAnalysisVertexingHF &source)
158 // assignment operator
160 if(&source == this) return *this;
161 fInputAOD = source.fInputAOD;
162 fAODMapSize = source.fAODMapSize;
163 fBzkG = source.fBzkG;
164 fSecVtxWithKF = source.fSecVtxWithKF;
165 fRecoPrimVtxSkippingTrks = source.fRecoPrimVtxSkippingTrks;
166 fRmTrksFromPrimVtx = source.fRmTrksFromPrimVtx;
168 fD0toKpi = source.fD0toKpi;
169 fJPSItoEle = source.fJPSItoEle;
170 f3Prong = source.f3Prong;
171 f4Prong = source.f4Prong;
172 fDstar = source.fDstar;
173 fCascades = source.fCascades;
174 fLikeSign = source.fLikeSign;
175 fMixEvent = source.fMixEvent;
176 fTrackFilter = source.fTrackFilter;
177 fTrackFilterSoftPi = source.fTrackFilterSoftPi;
178 fCutsD0toKpi = source.fCutsD0toKpi;
179 fCutsJpsitoee = source.fCutsJpsitoee;
180 fCutsDplustoKpipi = source.fCutsDplustoKpipi;
181 fCutsDstoKKpi = source.fCutsDstoKKpi;
182 fCutsLctopKpi = source.fCutsLctopKpi;
183 fCutsLctoV0 = source.fCutsLctoV0;
184 fCutsD0toKpipipi = source.fCutsD0toKpipipi;
185 fCutsDStartoKpipi = source.fCutsDStartoKpipi;
186 fListOfCuts = source.fListOfCuts;
187 fFindVertexForDstar = source.fFindVertexForDstar;
188 fFindVertexForCascades = source.fFindVertexForCascades;
189 fMassCutBeforeVertexing = source.fMassCutBeforeVertexing;
190 fMassCalc2 = source.fMassCalc2;
191 fMassCalc3 = source.fMassCalc3;
192 fMassCalc4 = source.fMassCalc4;
196 //----------------------------------------------------------------------------
197 AliAnalysisVertexingHF::~AliAnalysisVertexingHF() {
199 if(fV1) { delete fV1; fV1=0; }
200 if(fTrackFilter) { delete fTrackFilter; fTrackFilter=0; }
201 if(fTrackFilterSoftPi) { delete fTrackFilterSoftPi; fTrackFilterSoftPi=0; }
202 if(fCutsD0toKpi) { delete fCutsD0toKpi; fCutsD0toKpi=0; }
203 if(fCutsJpsitoee) { delete fCutsJpsitoee; fCutsJpsitoee=0; }
204 if(fCutsDplustoKpipi) { delete fCutsDplustoKpipi; fCutsDplustoKpipi=0; }
205 if(fCutsDstoKKpi) { delete fCutsDstoKKpi; fCutsDstoKKpi=0; }
206 if(fCutsLctopKpi) { delete fCutsLctopKpi; fCutsLctopKpi=0; }
207 if(fCutsLctoV0) { delete fCutsLctoV0; fCutsLctoV0=0; }
208 if(fCutsD0toKpipipi) { delete fCutsD0toKpipipi; fCutsD0toKpipipi=0; }
209 if(fCutsDStartoKpipi) { delete fCutsDStartoKpipi; fCutsDStartoKpipi=0; }
210 if(fAODMap) { delete [] fAODMap; fAODMap=0; }
211 if(fMassCalc2) { delete fMassCalc2; fMassCalc2=0; }
212 if(fMassCalc3) { delete fMassCalc3; fMassCalc3=0; }
213 if(fMassCalc4) { delete fMassCalc4; fMassCalc4=0; }
215 //----------------------------------------------------------------------------
216 TList *AliAnalysisVertexingHF::FillListOfCuts() {
217 // Fill list of analysis cuts
219 TList *list = new TList();
221 list->SetName("ListOfCuts");
224 AliRDHFCutsD0toKpi *cutsD0toKpi = new AliRDHFCutsD0toKpi(*fCutsD0toKpi);
225 list->Add(cutsD0toKpi);
228 AliRDHFCutsJpsitoee *cutsJpsitoee = new AliRDHFCutsJpsitoee(*fCutsJpsitoee);
229 list->Add(cutsJpsitoee);
231 if(fCutsDplustoKpipi) {
232 AliRDHFCutsDplustoKpipi *cutsDplustoKpipi = new AliRDHFCutsDplustoKpipi(*fCutsDplustoKpipi);
233 list->Add(cutsDplustoKpipi);
236 AliRDHFCutsDstoKKpi *cutsDstoKKpi = new AliRDHFCutsDstoKKpi(*fCutsDstoKKpi);
237 list->Add(cutsDstoKKpi);
240 AliRDHFCutsLctopKpi *cutsLctopKpi = new AliRDHFCutsLctopKpi(*fCutsLctopKpi);
241 list->Add(cutsLctopKpi);
244 AliRDHFCutsLctoV0 *cutsLctoV0 = new AliRDHFCutsLctoV0(*fCutsLctoV0);
245 list->Add(cutsLctoV0);
247 if(fCutsD0toKpipipi) {
248 AliRDHFCutsD0toKpipipi *cutsD0toKpipipi = new AliRDHFCutsD0toKpipipi(*fCutsD0toKpipipi);
249 list->Add(cutsD0toKpipipi);
251 if(fCutsDStartoKpipi) {
252 AliRDHFCutsDStartoKpipi *cutsDStartoKpipi = new AliRDHFCutsDStartoKpipi(*fCutsDStartoKpipi);
253 list->Add(cutsDStartoKpipi);
256 // keep a pointer to the list
261 //----------------------------------------------------------------------------
262 void AliAnalysisVertexingHF::FindCandidates(AliVEvent *event,
263 TClonesArray *aodVerticesHFTClArr,
264 TClonesArray *aodD0toKpiTClArr,
265 TClonesArray *aodJPSItoEleTClArr,
266 TClonesArray *aodCharm3ProngTClArr,
267 TClonesArray *aodCharm4ProngTClArr,
268 TClonesArray *aodDstarTClArr,
269 TClonesArray *aodCascadesTClArr,
270 TClonesArray *aodLikeSign2ProngTClArr,
271 TClonesArray *aodLikeSign3ProngTClArr)
273 // Find heavy-flavour vertex candidates
275 // Output: AOD (additional branches added)
278 TString evtype = event->IsA()->GetName();
279 fInputAOD = ((evtype=="AliAODEvent") ? kTRUE : kFALSE);
280 } // if we do mixing AliVEvent is a AliMixedEvent
283 AliDebug(2,"Creating HF candidates from AOD");
285 AliDebug(2,"Creating HF candidates from ESD");
288 if(!aodVerticesHFTClArr) {
289 printf("ERROR: no aodVerticesHFTClArr");
292 if((fD0toKpi || fDstar) && !aodD0toKpiTClArr) {
293 printf("ERROR: no aodD0toKpiTClArr");
296 if(fJPSItoEle && !aodJPSItoEleTClArr) {
297 printf("ERROR: no aodJPSItoEleTClArr");
300 if(f3Prong && !aodCharm3ProngTClArr) {
301 printf("ERROR: no aodCharm3ProngTClArr");
304 if(f4Prong && !aodCharm4ProngTClArr) {
305 printf("ERROR: no aodCharm4ProngTClArr");
308 if(fDstar && !aodDstarTClArr) {
309 printf("ERROR: no aodDstarTClArr");
312 if(fCascades && !aodCascadesTClArr){
313 printf("ERROR: no aodCascadesTClArr ");
316 if(fLikeSign && !aodLikeSign2ProngTClArr) {
317 printf("ERROR: no aodLikeSign2ProngTClArr");
320 if(fLikeSign && f3Prong && !aodLikeSign3ProngTClArr) {
321 printf("ERROR: no aodLikeSign2ProngTClArr");
325 // delete candidates from previous event and create references
326 Int_t iVerticesHF=0,iD0toKpi=0,iJPSItoEle=0,i3Prong=0,i4Prong=0,iDstar=0,iCascades=0,iLikeSign2Prong=0,iLikeSign3Prong=0;
327 aodVerticesHFTClArr->Delete();
328 iVerticesHF = aodVerticesHFTClArr->GetEntriesFast();
329 TClonesArray &verticesHFRef = *aodVerticesHFTClArr;
330 if(fD0toKpi || fDstar) {
331 aodD0toKpiTClArr->Delete();
332 iD0toKpi = aodD0toKpiTClArr->GetEntriesFast();
335 aodJPSItoEleTClArr->Delete();
336 iJPSItoEle = aodJPSItoEleTClArr->GetEntriesFast();
339 aodCharm3ProngTClArr->Delete();
340 i3Prong = aodCharm3ProngTClArr->GetEntriesFast();
343 aodCharm4ProngTClArr->Delete();
344 i4Prong = aodCharm4ProngTClArr->GetEntriesFast();
347 aodDstarTClArr->Delete();
348 iDstar = aodDstarTClArr->GetEntriesFast();
351 aodCascadesTClArr->Delete();
352 iCascades = aodCascadesTClArr->GetEntriesFast();
355 aodLikeSign2ProngTClArr->Delete();
356 iLikeSign2Prong = aodLikeSign2ProngTClArr->GetEntriesFast();
358 if(fLikeSign && f3Prong) {
359 aodLikeSign3ProngTClArr->Delete();
360 iLikeSign3Prong = aodLikeSign3ProngTClArr->GetEntriesFast();
363 TClonesArray &aodD0toKpiRef = *aodD0toKpiTClArr;
364 TClonesArray &aodJPSItoEleRef = *aodJPSItoEleTClArr;
365 TClonesArray &aodCharm3ProngRef = *aodCharm3ProngTClArr;
366 TClonesArray &aodCharm4ProngRef = *aodCharm4ProngTClArr;
367 TClonesArray &aodDstarRef = *aodDstarTClArr;
368 TClonesArray &aodCascadesRef = *aodCascadesTClArr;
369 TClonesArray &aodLikeSign2ProngRef = *aodLikeSign2ProngTClArr;
370 TClonesArray &aodLikeSign3ProngRef = *aodLikeSign3ProngTClArr;
373 AliAODRecoDecayHF2Prong *io2Prong = 0;
374 AliAODRecoDecayHF3Prong *io3Prong = 0;
375 AliAODRecoDecayHF4Prong *io4Prong = 0;
376 AliAODRecoCascadeHF *ioCascade = 0;
378 Int_t iTrkP1,iTrkP2,iTrkN1,iTrkN2,iTrkSoftPi,trkEntries,iv0,nv0;
379 Double_t xdummy,ydummy,dcap1n1,dcap1n2,dcap2n1,dcap1p2,dcan1n2,dcap2n2,dcaV0,dcaCasc;
380 Bool_t okD0=kFALSE,okJPSI=kFALSE,ok3Prong=kFALSE,ok4Prong=kFALSE;
381 Bool_t okDstar=kFALSE,okD0fromDstar=kFALSE;
382 Bool_t okCascades=kFALSE;
383 AliESDtrack *postrack1 = 0;
384 AliESDtrack *postrack2 = 0;
385 AliESDtrack *negtrack1 = 0;
386 AliESDtrack *negtrack2 = 0;
387 AliESDtrack *trackPi = 0;
388 // AliESDtrack *posV0track = 0;
389 // AliESDtrack *negV0track = 0;
390 Float_t dcaMax = fCutsD0toKpi->GetDCACut();
391 if(fCutsJpsitoee) dcaMax=TMath::Max(dcaMax,fCutsJpsitoee->GetDCACut());
392 if(fCutsDplustoKpipi) dcaMax=TMath::Max(dcaMax,fCutsDplustoKpipi->GetDCACut());
393 if(fCutsDstoKKpi) dcaMax=TMath::Max(dcaMax,fCutsDstoKKpi->GetDCACut());
394 if(fCutsLctopKpi) dcaMax=TMath::Max(dcaMax,fCutsLctopKpi->GetDCACut());
395 if(fCutsD0toKpipipi) dcaMax=TMath::Max(dcaMax,fCutsD0toKpipipi->GetDCACut());
396 if(fCutsDStartoKpipi) dcaMax=TMath::Max(dcaMax,fCutsDStartoKpipi->GetDCACut());
398 AliDebug(2,Form(" dca cut set to %f cm",dcaMax));
402 fBzkG = (Double_t)event->GetMagneticField();
404 trkEntries = (Int_t)event->GetNumberOfTracks();
405 AliDebug(1,Form(" Number of tracks: %d",trkEntries));
407 nv0 = (Int_t)event->GetNumberOfV0s();
408 AliDebug(1,Form(" Number of V0s: %d",nv0));
410 if( trkEntries<2 && (trkEntries<1 || nv0<1) ) {
411 AliDebug(1,Form(" Not enough tracks: %d",trkEntries));
416 if(!fCutsD0toKpi->IsEventSelected(event)) return;
418 // call function that applies sigle-track selection,
419 // for displaced tracks and soft pions (both charges) for D*,
420 // and retrieves primary vertex
421 TObjArray seleTrksArray(trkEntries);
422 UChar_t *seleFlags = new UChar_t[trkEntries]; // bit 0: displaced, bit 1: softpi
424 Int_t *evtNumber = new Int_t[trkEntries];
425 SelectTracksAndCopyVertex(event,trkEntries,seleTrksArray,nSeleTrks,seleFlags,evtNumber);
427 AliDebug(1,Form(" Selected tracks: %d",nSeleTrks));
429 TObjArray *twoTrackArray1 = new TObjArray(2);
430 TObjArray *twoTrackArray2 = new TObjArray(2);
431 TObjArray *twoTrackArrayV0 = new TObjArray(2);
432 TObjArray *twoTrackArrayCasc = new TObjArray(2);
433 TObjArray *threeTrackArray = new TObjArray(3);
434 TObjArray *fourTrackArray = new TObjArray(4);
437 Bool_t isLikeSign2Prong=kFALSE,isLikeSign3Prong=kFALSE;
439 AliAODRecoDecayHF *rd = 0;
440 AliAODRecoCascadeHF *rc = 0;
444 Bool_t massCutOK=kTRUE;
446 // LOOP ON POSITIVE TRACKS
447 for(iTrkP1=0; iTrkP1<nSeleTrks; iTrkP1++) {
449 //if(iTrkP1%1==0) AliDebug(1,Form(" 1st loop on pos: track number %d of %d",iTrkP1,nSeleTrks));
450 //if(iTrkP1%1==0) printf(" 1st loop on pos: track number %d of %d\n",iTrkP1,nSeleTrks);
452 // get track from tracks array
453 postrack1 = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkP1);
455 if(!TESTBIT(seleFlags[iTrkP1],kBitDispl)) continue;
457 // Make cascades with V0+track
461 for(iv0=0; iv0<nv0; iv0++){
463 //AliDebug(1,Form(" loop on v0s for track number %d and v0 number %d",iTrkP1,iv0));
467 v0 = ((AliAODEvent*)event)->GetV0(iv0);
469 esdV0 = ((AliESDEvent*)event)->GetV0(iv0);
471 if ( (!v0 || !v0->IsA()->InheritsFrom("AliAODv0") ) &&
472 (!esdV0 || !esdV0->IsA()->InheritsFrom("AliESDv0") ) ) continue;
475 // Get the tracks that form the V0
476 // ( parameters at primary vertex )
477 // and define an AliExternalTrackParam out of them
478 AliExternalTrackParam * posV0track;
479 AliExternalTrackParam * negV0track;
482 AliAODTrack *posVV0track = (AliAODTrack*)(v0->GetDaughter(0));
483 AliAODTrack *negVV0track = (AliAODTrack*)(v0->GetDaughter(1));
484 if( !posVV0track || !negVV0track ) continue;
486 // Apply some basic V0 daughter criteria
488 // bachelor must not be a v0-track
489 if (posVV0track->GetID() == postrack1->GetID() ||
490 negVV0track->GetID() == postrack1->GetID()) continue;
491 // reject like-sign v0
492 if ( posVV0track->Charge() == negVV0track->Charge() ) continue;
493 // avoid ghost TPC tracks
494 if(!(posVV0track->GetStatus() & AliESDtrack::kTPCrefit) ||
495 !(negVV0track->GetStatus() & AliESDtrack::kTPCrefit)) continue;
496 // Get AliExternalTrackParam out of the AliAODTracks
497 Double_t xyz[3], pxpypz[3], cv[21]; Short_t sign;
498 posVV0track->PxPyPz(pxpypz); posVV0track->XvYvZv(xyz);
499 posVV0track->GetCovarianceXYZPxPyPz(cv); sign=posVV0track->Charge();
500 posV0track = new AliExternalTrackParam(xyz,pxpypz,cv,sign);
501 negVV0track->PxPyPz(pxpypz); negVV0track->XvYvZv(xyz);
502 negVV0track->GetCovarianceXYZPxPyPz(cv); sign=negVV0track->Charge();
503 negV0track = new AliExternalTrackParam(xyz,pxpypz,cv,sign);
505 AliESDtrack *posVV0track = (AliESDtrack*)(event->GetTrack( esdV0->GetPindex() ));
506 AliESDtrack *negVV0track = (AliESDtrack*)(event->GetTrack( esdV0->GetNindex() ));
507 if( !posVV0track || !negVV0track ) continue;
509 // Apply some basic V0 daughter criteria
511 // bachelor must not be a v0-track
512 if (posVV0track->GetID() == postrack1->GetID() ||
513 negVV0track->GetID() == postrack1->GetID()) continue;
514 // reject like-sign v0
515 if ( posVV0track->Charge() == negVV0track->Charge() ) continue;
516 // avoid ghost TPC tracks
517 if(!(posVV0track->GetStatus() & AliESDtrack::kTPCrefit) ||
518 !(negVV0track->GetStatus() & AliESDtrack::kTPCrefit)) continue;
519 // reject kinks (only necessary on AliESDtracks)
520 if (posVV0track->GetKinkIndex(0)>0 || negVV0track->GetKinkIndex(0)>0) continue;
521 // Get AliExternalTrackParam out of the AliESDtracks
522 posV0track = new AliExternalTrackParam(*posVV0track);
523 negV0track = new AliExternalTrackParam(*negVV0track);
525 // Define the AODv0 from ESDv0 if reading ESDs
526 v0 = TransformESDv0toAODv0(esdV0,twoTrackArrayV0);
528 if( !posV0track || !negV0track ){
529 AliDebug(1,Form(" Couldn't get the V0 daughters"));
533 // fill in the v0 two-external-track-param array
534 twoTrackArrayV0->AddAt(posV0track,0);
535 twoTrackArrayV0->AddAt(negV0track,1);
538 dcaV0 = v0->DcaV0Daughters();
540 // Define the V0 (neutral) track
541 AliNeutralTrackParam *trackV0;
543 const AliVTrack *trackVV0 = dynamic_cast<const AliVTrack*>(v0);
544 if(trackVV0) trackV0 = new AliNeutralTrackParam(trackVV0);
546 Double_t xyz[3], pxpypz[3];
548 esdV0->PxPyPz(pxpypz);
549 Double_t cv[21]; for(int i=0; i<21; i++) cv[i]=0;
550 trackV0 = new AliNeutralTrackParam(xyz,pxpypz,cv,0);
552 // Fill in the object array to create the cascade
553 twoTrackArrayCasc->AddAt(postrack1,0);
554 twoTrackArrayCasc->AddAt(trackV0,1);
556 // Compute the cascade vertex
557 AliAODVertex *vertexCasc = 0;
558 if(fFindVertexForCascades) {
559 // DCA between the two tracks
560 dcaCasc = postrack1->GetDCA(trackV0,fBzkG,xdummy,ydummy);
562 vertexCasc = ReconstructSecondaryVertex(twoTrackArrayCasc,dispersion,kFALSE);
564 // assume Cascade decays at the primary vertex
565 Double_t pos[3],cov[6],chi2perNDF;
567 fV1->GetCovMatrix(cov);
568 chi2perNDF = fV1->GetChi2toNDF();
569 vertexCasc = new AliAODVertex(pos,cov,chi2perNDF,0x0,-1,AliAODVertex::kUndef,2);
573 delete posV0track; posV0track=NULL;
574 delete negV0track; negV0track=NULL;
575 delete trackV0; trackV0=NULL;
576 if(!fInputAOD) {delete v0; v0=NULL;}
577 twoTrackArrayCasc->Clear();
581 // Create and store the Cascade if passed the cuts
582 ioCascade = MakeCascade(twoTrackArrayCasc,event,vertexCasc,v0,dcaCasc,okCascades);
583 if(okCascades && ioCascade) {
584 //AliDebug(1,Form("Storing a cascade object... "));
585 // add the vertex and the cascade to the AOD
586 AliAODVertex *vCasc = new(verticesHFRef[iVerticesHF++])AliAODVertex(*vertexCasc);
587 rc = new(aodCascadesRef[iCascades++])AliAODRecoCascadeHF(*ioCascade);
588 rc->SetSecondaryVtx(vCasc);
589 vCasc->SetParent(rc);
590 rc->SetPrimaryVtxRef((AliAODVertex*)event->GetPrimaryVertex());
591 if(!fInputAOD) vCasc->AddDaughter(v0); // just to fill ref #0 ??
592 AddRefs(vCasc,rc,event,twoTrackArrayCasc); // add the track (proton)
593 vCasc->AddDaughter(v0); // fill the 2prong V0
597 delete posV0track; posV0track=NULL;
598 delete negV0track; negV0track=NULL;
599 delete trackV0; trackV0=NULL;
600 twoTrackArrayV0->Clear();
601 twoTrackArrayCasc->Clear();
602 if(ioCascade) { delete ioCascade; ioCascade=NULL; }
603 if(vertexCasc) { delete vertexCasc; vertexCasc=NULL; }
604 if(!fInputAOD) {delete v0; v0=NULL;}
606 } // end loop on V0's
609 // If there is less than 2 particles continue
611 AliDebug(1,Form(" Not enough tracks: %d",trkEntries));
615 if(postrack1->Charge()<0 && !fLikeSign) continue;
617 // LOOP ON NEGATIVE TRACKS
618 for(iTrkN1=0; iTrkN1<nSeleTrks; iTrkN1++) {
620 //if(iTrkN1%1==0) AliDebug(1,Form(" 1st loop on neg: track number %d of %d",iTrkN1,nSeleTrks));
621 //if(iTrkN1%1==0) printf(" 1st loop on neg: track number %d of %d\n",iTrkN1,nSeleTrks);
623 if(iTrkN1==iTrkP1) continue;
625 // get track from tracks array
626 negtrack1 = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkN1);
628 if(negtrack1->Charge()>0 && !fLikeSign) continue;
630 if(!TESTBIT(seleFlags[iTrkN1],kBitDispl)) continue;
633 if(evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
636 if(postrack1->Charge()==negtrack1->Charge()) { // like-sign
637 isLikeSign2Prong=kTRUE;
638 if(!fLikeSign) continue;
639 if(iTrkN1<iTrkP1) continue; // this is needed to avoid double-counting of like-sign
640 } else { // unlike-sign
641 isLikeSign2Prong=kFALSE;
642 if(postrack1->Charge()<0 || negtrack1->Charge()>0) continue; // this is needed to avoid double-counting of unlike-sign
644 if(evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
649 // back to primary vertex
650 postrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
651 negtrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
653 // DCA between the two tracks
654 dcap1n1 = postrack1->GetDCA(negtrack1,fBzkG,xdummy,ydummy);
655 if(dcap1n1>dcaMax) { negtrack1=0; continue; }
658 twoTrackArray1->AddAt(postrack1,0);
659 twoTrackArray1->AddAt(negtrack1,1);
660 AliAODVertex *vertexp1n1 = ReconstructSecondaryVertex(twoTrackArray1,dispersion);
662 twoTrackArray1->Clear();
668 if(fD0toKpi || fJPSItoEle || fDstar || fLikeSign) {
670 io2Prong = Make2Prong(twoTrackArray1,event,vertexp1n1,dcap1n1,okD0,okJPSI,okD0fromDstar);
672 if((fD0toKpi && okD0) || (fJPSItoEle && okJPSI) || (isLikeSign2Prong && (okD0 || okJPSI))) {
673 // add the vertex and the decay to the AOD
674 AliAODVertex *v2Prong = new(verticesHFRef[iVerticesHF++])AliAODVertex(*vertexp1n1);
675 if(!isLikeSign2Prong) {
677 rd = new(aodD0toKpiRef[iD0toKpi++])AliAODRecoDecayHF2Prong(*io2Prong);
678 rd->SetSecondaryVtx(v2Prong);
679 v2Prong->SetParent(rd);
680 AddRefs(v2Prong,rd,event,twoTrackArray1);
683 rd = new(aodJPSItoEleRef[iJPSItoEle++])AliAODRecoDecayHF2Prong(*io2Prong);
684 rd->SetSecondaryVtx(v2Prong);
685 if(!okD0) v2Prong->SetParent(rd); // it cannot have two mothers ...
686 AddRefs(v2Prong,rd,event,twoTrackArray1);
688 } else { // isLikeSign2Prong
689 rd = new(aodLikeSign2ProngRef[iLikeSign2Prong++])AliAODRecoDecayHF2Prong(*io2Prong);
690 rd->SetSecondaryVtx(v2Prong);
691 v2Prong->SetParent(rd);
692 AddRefs(v2Prong,rd,event,twoTrackArray1);
694 // Set selection bit for PID
695 if(okD0) SetSelectionBitForPID(fCutsD0toKpi,rd,AliRDHFCuts::kD0toKpiPID);
698 if(fDstar && okD0fromDstar && !isLikeSign2Prong) {
699 // write references in io2Prong
701 AddDaughterRefs(vertexp1n1,event,twoTrackArray1);
703 vertexp1n1->AddDaughter(postrack1);
704 vertexp1n1->AddDaughter(negtrack1);
706 io2Prong->SetSecondaryVtx(vertexp1n1);
707 //printf("---> %d %d %d %d %d\n",vertexp1n1->GetNDaughters(),iTrkP1,iTrkN1,postrack1->Charge(),negtrack1->Charge());
708 // create a track from the D0
709 AliNeutralTrackParam *trackD0 = new AliNeutralTrackParam(io2Prong);
711 // LOOP ON TRACKS THAT PASSED THE SOFT PION CUTS
712 for(iTrkSoftPi=0; iTrkSoftPi<nSeleTrks; iTrkSoftPi++) {
714 if(iTrkSoftPi==iTrkP1 || iTrkSoftPi==iTrkN1) continue;
716 if(!TESTBIT(seleFlags[iTrkSoftPi],kBitSoftPi)) continue;
719 if(evtNumber[iTrkP1]==evtNumber[iTrkSoftPi] ||
720 evtNumber[iTrkN1]==evtNumber[iTrkSoftPi] ||
721 evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
724 //if(iTrkSoftPi%1==0) AliDebug(1,Form(" 1st loop on pi_s: track number %d of %d",iTrkSoftPi,nSeleTrks));
726 trackD0->PropagateToDCA(fV1,fBzkG,kVeryBig);
727 if(trackD0->GetSigmaY2()<0. || trackD0->GetSigmaZ2()<0.) continue; // this is insipired by the AliITStrackV2::Invariant() checks
729 // get track from tracks array
730 trackPi = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkSoftPi);
731 trackPi->PropagateToDCA(fV1,fBzkG,kVeryBig);
733 twoTrackArrayCasc->AddAt(trackPi,0);
734 twoTrackArrayCasc->AddAt(trackD0,1);
736 AliAODVertex *vertexCasc = 0;
738 if(fFindVertexForDstar) {
739 // DCA between the two tracks
740 dcaCasc = trackPi->GetDCA(trackD0,fBzkG,xdummy,ydummy);
742 vertexCasc = ReconstructSecondaryVertex(twoTrackArrayCasc,dispersion,kFALSE);
744 // assume Dstar decays at the primary vertex
745 Double_t pos[3],cov[6],chi2perNDF;
747 fV1->GetCovMatrix(cov);
748 chi2perNDF = fV1->GetChi2toNDF();
749 vertexCasc = new AliAODVertex(pos,cov,chi2perNDF,0x0,-1,AliAODVertex::kUndef,2);
753 twoTrackArrayCasc->Clear();
758 ioCascade = MakeCascade(twoTrackArrayCasc,event,vertexCasc,io2Prong,dcaCasc,okDstar);
760 // add the D0 to the AOD (if not already done)
762 AliAODVertex *v2Prong = new(verticesHFRef[iVerticesHF++])AliAODVertex(*vertexp1n1);
763 rd = new(aodD0toKpiRef[iD0toKpi++])AliAODRecoDecayHF2Prong(*io2Prong);
764 rd->SetSecondaryVtx(v2Prong);
765 v2Prong->SetParent(rd);
766 AddRefs(v2Prong,rd,event,twoTrackArray1);
767 okD0=kTRUE; // this is done to add it only once
769 // add the vertex and the cascade to the AOD
770 AliAODVertex *vCasc = new(verticesHFRef[iVerticesHF++])AliAODVertex(*vertexCasc);
771 rc = new(aodDstarRef[iDstar++])AliAODRecoCascadeHF(*ioCascade);
772 rc->SetSecondaryVtx(vCasc);
773 vCasc->SetParent(rc);
774 if(!fInputAOD) vCasc->AddDaughter(rd); // just to fill ref #0
775 AddRefs(vCasc,rc,event,twoTrackArrayCasc);
776 vCasc->AddDaughter(rd); // add the D0 (in ref #1)
777 // Set selection bit for PID
778 SetSelectionBitForPID(fCutsDStartoKpipi,rc,AliRDHFCuts::kDstarPID);
780 twoTrackArrayCasc->Clear();
782 if(ioCascade) {delete ioCascade; ioCascade=NULL;}
783 delete vertexCasc; vertexCasc=NULL;
784 } // end loop on soft pi tracks
786 if(trackD0) {delete trackD0; trackD0=NULL;}
789 if(io2Prong) {delete io2Prong; io2Prong=NULL;}
792 twoTrackArray1->Clear();
793 if( (!f3Prong && !f4Prong) ||
794 (isLikeSign2Prong && !f3Prong) ) {
801 // 2nd LOOP ON POSITIVE TRACKS
802 for(iTrkP2=iTrkP1+1; iTrkP2<nSeleTrks; iTrkP2++) {
804 if(iTrkP2==iTrkP1 || iTrkP2==iTrkN1) continue;
806 //if(iTrkP2%1==0) AliDebug(1,Form(" 2nd loop on pos: track number %d of %d",iTrkP2,nSeleTrks));
808 // get track from tracks array
809 postrack2 = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkP2);
811 if(postrack2->Charge()<0) continue;
813 if(!TESTBIT(seleFlags[iTrkP2],kBitDispl)) continue;
816 if(evtNumber[iTrkP1]==evtNumber[iTrkP2] ||
817 evtNumber[iTrkN1]==evtNumber[iTrkP2] ||
818 evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
821 if(isLikeSign2Prong) { // like-sign pair -> have to build only like-sign triplet
822 if(postrack1->Charge()>0) { // ok: like-sign triplet (+++)
823 isLikeSign3Prong=kTRUE;
827 } else { // normal triplet (+-+)
828 isLikeSign3Prong=kFALSE;
830 if(evtNumber[iTrkP1]==evtNumber[iTrkP2] ||
831 evtNumber[iTrkN1]==evtNumber[iTrkP2] ||
832 evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
836 // back to primary vertex
837 postrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
838 postrack2->PropagateToDCA(fV1,fBzkG,kVeryBig);
839 negtrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
840 //printf("********** %d %d %d\n",postrack1->GetID(),postrack2->GetID(),negtrack1->GetID());
842 dcap2n1 = postrack2->GetDCA(negtrack1,fBzkG,xdummy,ydummy);
843 if(dcap2n1>dcaMax) { postrack2=0; continue; }
844 dcap1p2 = postrack2->GetDCA(postrack1,fBzkG,xdummy,ydummy);
845 if(dcap1p2>dcaMax) { postrack2=0; continue; }
847 // check invariant mass cuts for D+,Ds,Lc
850 if(postrack2->Charge()>0) {
851 threeTrackArray->AddAt(postrack1,0);
852 threeTrackArray->AddAt(negtrack1,1);
853 threeTrackArray->AddAt(postrack2,2);
855 threeTrackArray->AddAt(negtrack1,0);
856 threeTrackArray->AddAt(postrack1,1);
857 threeTrackArray->AddAt(postrack2,2);
859 if(fMassCutBeforeVertexing)
860 massCutOK = SelectInvMassAndPt(threeTrackArray);
863 if(f3Prong && !massCutOK) {
864 threeTrackArray->Clear();
872 twoTrackArray2->AddAt(postrack2,0);
873 twoTrackArray2->AddAt(negtrack1,1);
874 AliAODVertex *vertexp2n1 = ReconstructSecondaryVertex(twoTrackArray2,dispersion);
876 twoTrackArray2->Clear();
881 // 3 prong candidates
882 if(f3Prong && massCutOK) {
884 AliAODVertex* secVert3PrAOD = ReconstructSecondaryVertex(threeTrackArray,dispersion);
885 io3Prong = Make3Prong(threeTrackArray,event,secVert3PrAOD,dispersion,vertexp1n1,vertexp2n1,dcap1n1,dcap2n1,dcap1p2,ok3Prong);
887 AliAODVertex *v3Prong = new(verticesHFRef[iVerticesHF++])AliAODVertex(*secVert3PrAOD);
888 if(!isLikeSign3Prong) {
889 rd = new(aodCharm3ProngRef[i3Prong++])AliAODRecoDecayHF3Prong(*io3Prong);
890 rd->SetSecondaryVtx(v3Prong);
891 v3Prong->SetParent(rd);
892 AddRefs(v3Prong,rd,event,threeTrackArray);
893 } else { // isLikeSign3Prong
894 rd = new(aodLikeSign3ProngRef[iLikeSign3Prong++])AliAODRecoDecayHF3Prong(*io3Prong);
895 rd->SetSecondaryVtx(v3Prong);
896 v3Prong->SetParent(rd);
897 AddRefs(v3Prong,rd,event,threeTrackArray);
899 // Set selection bit for PID
900 SetSelectionBitForPID(fCutsDplustoKpipi,rd,AliRDHFCuts::kDplusPID);
901 SetSelectionBitForPID(fCutsDstoKKpi,rd,AliRDHFCuts::kDsPID);
902 SetSelectionBitForPID(fCutsLctopKpi,rd,AliRDHFCuts::kLcPID);
904 if(io3Prong) {delete io3Prong; io3Prong=NULL;}
905 if(secVert3PrAOD) {delete secVert3PrAOD; secVert3PrAOD=NULL;}
908 // 4 prong candidates
910 // don't make 4 prong with like-sign pairs and triplets
911 && !isLikeSign2Prong && !isLikeSign3Prong
912 // track-to-track dca cuts already now
913 && dcap1n1 < fCutsD0toKpipipi->GetDCACut()
914 && dcap2n1 < fCutsD0toKpipipi->GetDCACut()) {
916 // back to primary vertex
917 postrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
918 postrack2->PropagateToDCA(fV1,fBzkG,kVeryBig);
919 negtrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
920 // Vertexing for these 3 (can be taken from above?)
921 threeTrackArray->AddAt(postrack1,0);
922 threeTrackArray->AddAt(negtrack1,1);
923 threeTrackArray->AddAt(postrack2,2);
924 AliAODVertex* vertexp1n1p2 = ReconstructSecondaryVertex(threeTrackArray,dispersion);
926 // 3rd LOOP ON NEGATIVE TRACKS (for 4 prong)
927 for(iTrkN2=iTrkN1+1; iTrkN2<nSeleTrks; iTrkN2++) {
929 if(iTrkN2==iTrkP1 || iTrkN2==iTrkP2 || iTrkN2==iTrkN1) continue;
931 //if(iTrkN2%1==0) AliDebug(1,Form(" 3rd loop on neg: track number %d of %d",iTrkN2,nSeleTrks));
933 // get track from tracks array
934 negtrack2 = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkN2);
936 if(negtrack2->Charge()>0) continue;
938 if(!TESTBIT(seleFlags[iTrkN2],kBitDispl)) continue;
940 if(evtNumber[iTrkP1]==evtNumber[iTrkN2] ||
941 evtNumber[iTrkN1]==evtNumber[iTrkN2] ||
942 evtNumber[iTrkP2]==evtNumber[iTrkN2] ||
943 evtNumber[iTrkP1]==evtNumber[iTrkN1] ||
944 evtNumber[iTrkP1]==evtNumber[iTrkP2] ||
945 evtNumber[iTrkN1]==evtNumber[iTrkP2]) continue;
948 // back to primary vertex
949 postrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
950 postrack2->PropagateToDCA(fV1,fBzkG,kVeryBig);
951 negtrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
952 negtrack2->PropagateToDCA(fV1,fBzkG,kVeryBig);
953 dcap1n2 = postrack1->GetDCA(negtrack2,fBzkG,xdummy,ydummy);
954 if(dcap1n2 > fCutsD0toKpipipi->GetDCACut()) { negtrack2=0; continue; }
955 dcap2n2 = postrack2->GetDCA(negtrack2,fBzkG,xdummy,ydummy);
956 if(dcap2n2 > fCutsD0toKpipipi->GetDCACut()) { negtrack2=0; continue; }
959 fourTrackArray->AddAt(postrack1,0);
960 fourTrackArray->AddAt(negtrack1,1);
961 fourTrackArray->AddAt(postrack2,2);
962 fourTrackArray->AddAt(negtrack2,3);
964 // check invariant mass cuts for D0
966 if(fMassCutBeforeVertexing)
967 massCutOK = SelectInvMassAndPt(fourTrackArray);
970 fourTrackArray->Clear();
976 AliAODVertex* secVert4PrAOD = ReconstructSecondaryVertex(fourTrackArray,dispersion);
977 io4Prong = Make4Prong(fourTrackArray,event,secVert4PrAOD,vertexp1n1,vertexp1n1p2,dcap1n1,dcap1n2,dcap2n1,dcap2n2,ok4Prong);
979 AliAODVertex *v4Prong = new(verticesHFRef[iVerticesHF++])AliAODVertex(*secVert4PrAOD);
980 rd = new(aodCharm4ProngRef[i4Prong++])AliAODRecoDecayHF4Prong(*io4Prong);
981 rd->SetSecondaryVtx(v4Prong);
982 v4Prong->SetParent(rd);
983 AddRefs(v4Prong,rd,event,fourTrackArray);
986 if(io4Prong) {delete io4Prong; io4Prong=NULL;}
987 if(secVert4PrAOD) {delete secVert4PrAOD; secVert4PrAOD=NULL;}
988 fourTrackArray->Clear();
991 } // end loop on negative tracks
993 threeTrackArray->Clear();
1001 } // end 2nd loop on positive tracks
1003 twoTrackArray2->Clear();
1005 // 2nd LOOP ON NEGATIVE TRACKS (for 3 prong -+-)
1006 for(iTrkN2=iTrkN1+1; iTrkN2<nSeleTrks; iTrkN2++) {
1008 if(iTrkN2==iTrkP1 || iTrkN2==iTrkP2 || iTrkN2==iTrkN1) continue;
1010 //if(iTrkN2%1==0) AliDebug(1,Form(" 2nd loop on neg: track number %d of %d",iTrkN2,nSeleTrks));
1012 // get track from tracks array
1013 negtrack2 = (AliESDtrack*)seleTrksArray.UncheckedAt(iTrkN2);
1015 if(negtrack2->Charge()>0) continue;
1017 if(!TESTBIT(seleFlags[iTrkN2],kBitDispl)) continue;
1020 if(evtNumber[iTrkP1]==evtNumber[iTrkN2] ||
1021 evtNumber[iTrkN1]==evtNumber[iTrkN2] ||
1022 evtNumber[iTrkP1]==evtNumber[iTrkN1]) continue;
1025 if(isLikeSign2Prong) { // like-sign pair -> have to build only like-sign triplet
1026 if(postrack1->Charge()<0) { // ok: like-sign triplet (---)
1027 isLikeSign3Prong=kTRUE;
1031 } else { // normal triplet (-+-)
1032 isLikeSign3Prong=kFALSE;
1035 // back to primary vertex
1036 postrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
1037 negtrack1->PropagateToDCA(fV1,fBzkG,kVeryBig);
1038 negtrack2->PropagateToDCA(fV1,fBzkG,kVeryBig);
1039 //printf("********** %d %d %d\n",postrack1->GetID(),negtrack1->GetID(),negtrack2->GetID());
1041 dcap1n2 = postrack1->GetDCA(negtrack2,fBzkG,xdummy,ydummy);
1042 if(dcap1n2>dcaMax) { negtrack2=0; continue; }
1043 dcan1n2 = negtrack1->GetDCA(negtrack2,fBzkG,xdummy,ydummy);
1044 if(dcan1n2>dcaMax) { negtrack2=0; continue; }
1046 threeTrackArray->AddAt(negtrack1,0);
1047 threeTrackArray->AddAt(postrack1,1);
1048 threeTrackArray->AddAt(negtrack2,2);
1050 // check invariant mass cuts for D+,Ds,Lc
1052 if(fMassCutBeforeVertexing && f3Prong)
1053 massCutOK = SelectInvMassAndPt(threeTrackArray);
1056 threeTrackArray->Clear();
1062 twoTrackArray2->AddAt(postrack1,0);
1063 twoTrackArray2->AddAt(negtrack2,1);
1065 AliAODVertex *vertexp1n2 = ReconstructSecondaryVertex(twoTrackArray2,dispersion);
1067 twoTrackArray2->Clear();
1073 AliAODVertex* secVert3PrAOD = ReconstructSecondaryVertex(threeTrackArray,dispersion);
1074 io3Prong = Make3Prong(threeTrackArray,event,secVert3PrAOD,dispersion,vertexp1n1,vertexp1n2,dcap1n1,dcap1n2,dcan1n2,ok3Prong);
1076 AliAODVertex *v3Prong = new(verticesHFRef[iVerticesHF++])AliAODVertex(*secVert3PrAOD);
1077 if(!isLikeSign3Prong) {
1078 rd = new(aodCharm3ProngRef[i3Prong++])AliAODRecoDecayHF3Prong(*io3Prong);
1079 rd->SetSecondaryVtx(v3Prong);
1080 v3Prong->SetParent(rd);
1081 AddRefs(v3Prong,rd,event,threeTrackArray);
1082 } else { // isLikeSign3Prong
1083 rd = new(aodLikeSign3ProngRef[iLikeSign3Prong++])AliAODRecoDecayHF3Prong(*io3Prong);
1084 rd->SetSecondaryVtx(v3Prong);
1085 v3Prong->SetParent(rd);
1086 AddRefs(v3Prong,rd,event,threeTrackArray);
1088 // Set selection bit for PID
1089 SetSelectionBitForPID(fCutsDplustoKpipi,rd,AliRDHFCuts::kDplusPID);
1090 SetSelectionBitForPID(fCutsDstoKKpi,rd,AliRDHFCuts::kDsPID);
1091 SetSelectionBitForPID(fCutsLctopKpi,rd,AliRDHFCuts::kLcPID);
1093 if(io3Prong) {delete io3Prong; io3Prong=NULL;}
1094 if(secVert3PrAOD) {delete secVert3PrAOD; secVert3PrAOD=NULL;}
1096 threeTrackArray->Clear();
1100 } // end 2nd loop on negative tracks
1102 twoTrackArray2->Clear();
1106 } // end 1st loop on negative tracks
1109 } // end 1st loop on positive tracks
1112 AliDebug(1,Form(" Total HF vertices in event = %d;",
1113 (Int_t)aodVerticesHFTClArr->GetEntriesFast()));
1115 AliDebug(1,Form(" D0->Kpi in event = %d;",
1116 (Int_t)aodD0toKpiTClArr->GetEntriesFast()));
1119 AliDebug(1,Form(" JPSI->ee in event = %d;",
1120 (Int_t)aodJPSItoEleTClArr->GetEntriesFast()));
1123 AliDebug(1,Form(" Charm->3Prong in event = %d;",
1124 (Int_t)aodCharm3ProngTClArr->GetEntriesFast()));
1127 AliDebug(1,Form(" Charm->4Prong in event = %d;\n",
1128 (Int_t)aodCharm4ProngTClArr->GetEntriesFast()));
1131 AliDebug(1,Form(" D*->D0pi in event = %d;\n",
1132 (Int_t)aodDstarTClArr->GetEntriesFast()));
1135 AliDebug(1,Form(" cascades -> v0 + track in event = %d;\n",
1136 (Int_t)aodCascadesTClArr->GetEntriesFast()));
1139 AliDebug(1,Form(" Like-sign 2Prong in event = %d;\n",
1140 (Int_t)aodLikeSign2ProngTClArr->GetEntriesFast()));
1142 if(fLikeSign && f3Prong) {
1143 AliDebug(1,Form(" Like-sign 3Prong in event = %d;\n",
1144 (Int_t)aodLikeSign3ProngTClArr->GetEntriesFast()));
1148 twoTrackArray1->Delete(); delete twoTrackArray1;
1149 twoTrackArray2->Delete(); delete twoTrackArray2;
1150 twoTrackArrayCasc->Delete(); delete twoTrackArrayCasc;
1151 twoTrackArrayV0->Delete(); delete twoTrackArrayV0;
1152 threeTrackArray->Clear();
1153 threeTrackArray->Delete(); delete threeTrackArray;
1154 fourTrackArray->Delete(); delete fourTrackArray;
1155 delete [] seleFlags; seleFlags=NULL;
1156 if(evtNumber) {delete [] evtNumber; evtNumber=NULL;}
1159 seleTrksArray.Delete();
1160 if(fAODMap) { delete fAODMap; fAODMap=NULL; }
1165 //----------------------------------------------------------------------------
1166 void AliAnalysisVertexingHF::AddRefs(AliAODVertex *v,AliAODRecoDecayHF *rd,
1167 const AliVEvent *event,
1168 const TObjArray *trkArray) const
1170 // Add the AOD tracks as daughters of the vertex (TRef)
1171 // Also add the references to the primary vertex and to the cuts
1174 AddDaughterRefs(v,event,trkArray);
1175 rd->SetPrimaryVtxRef((AliAODVertex*)event->GetPrimaryVertex());
1179 rd->SetListOfCutsRef((TList*)fListOfCuts);
1180 //fListOfCuts->Print();
1181 cout<<fListOfCuts<<endl;
1182 TList *l=(TList*)rd->GetListOfCuts();
1184 if(l) {l->Print(); }else{printf("error\n");}
1189 //----------------------------------------------------------------------------
1190 void AliAnalysisVertexingHF::AddDaughterRefs(AliAODVertex *v,
1191 const AliVEvent *event,
1192 const TObjArray *trkArray) const
1194 // Add the AOD tracks as daughters of the vertex (TRef)
1196 Int_t nDg = v->GetNDaughters();
1198 if(nDg) dg = v->GetDaughter(0);
1200 if(dg) return; // daughters already added
1202 Int_t nTrks = trkArray->GetEntriesFast();
1204 AliExternalTrackParam *track = 0;
1205 AliAODTrack *aodTrack = 0;
1208 for(Int_t i=0; i<nTrks; i++) {
1209 track = (AliExternalTrackParam*)trkArray->UncheckedAt(i);
1210 id = (Int_t)track->GetID();
1211 //printf("---> %d\n",id);
1212 if(id<0) continue; // this track is a AliAODRecoDecay
1213 aodTrack = (AliAODTrack*)event->GetTrack(fAODMap[id]);
1214 v->AddDaughter(aodTrack);
1219 //---------------------------------------------------------------------------
1220 void AliAnalysisVertexingHF::FixReferences(AliAODEvent *aod)
1222 // Checks that the references to the daughter tracks are properly
1223 // assigned and reassigns them if needed
1227 TClonesArray *inputArray=(TClonesArray*)aod->GetList()->FindObject("VerticesHF");
1228 if(!inputArray) return;
1230 AliAODTrack *track = 0;
1231 AliAODVertex *vertex = 0;
1233 Bool_t needtofix=kFALSE;
1234 for(Int_t iv=0; iv<inputArray->GetEntriesFast(); iv++) {
1235 vertex = (AliAODVertex*)inputArray->UncheckedAt(iv);
1236 for(Int_t id=0; id<vertex->GetNDaughters(); id++) {
1237 track = (AliAODTrack*)vertex->GetDaughter(id);
1238 if(!track->GetStatus()) needtofix=kTRUE;
1240 if(needtofix) break;
1243 if(!needtofix) return;
1246 printf("Fixing references\n");
1248 fAODMapSize = 100000;
1249 fAODMap = new Int_t[fAODMapSize];
1251 for(Int_t i=0; i<aod->GetNumberOfTracks(); i++) {
1252 track = aod->GetTrack(i);
1254 // skip pure ITS SA tracks
1255 if(track->GetStatus()&AliESDtrack::kITSpureSA) continue;
1257 // skip tracks without ITS
1258 if(!(track->GetStatus()&AliESDtrack::kITSin)) continue;
1260 // TEMPORARY: check that the cov matrix is there
1261 Double_t covtest[21];
1262 if(!track->GetCovarianceXYZPxPyPz(covtest)) continue;
1265 fAODMap[(Int_t)track->GetID()] = i;
1269 Int_t ids[4]={-1,-1,-1,-1};
1270 for(Int_t iv=0; iv<inputArray->GetEntriesFast(); iv++) {
1271 Bool_t cascade=kFALSE;
1272 vertex = (AliAODVertex*)inputArray->UncheckedAt(iv);
1274 Int_t nDgs = vertex->GetNDaughters();
1275 for(id=0; id<nDgs; id++) {
1276 track = (AliAODTrack*)vertex->GetDaughter(id);
1277 if(track->Charge()==0) {cascade=kTRUE; continue;} // cascade
1278 ids[id]=(Int_t)track->GetID();
1279 vertex->RemoveDaughter(track);
1281 if(cascade) continue;
1282 for(id=0; id<nDgs; id++) {
1283 track = aod->GetTrack(fAODMap[ids[id]]);
1284 vertex->AddDaughter(track);
1291 //----------------------------------------------------------------------------
1292 AliAODRecoCascadeHF* AliAnalysisVertexingHF::MakeCascade(
1293 TObjArray *twoTrackArray,AliVEvent *event,
1294 AliAODVertex *secVert,
1295 AliAODRecoDecayHF2Prong *rd2Prong,
1297 Bool_t &okDstar) const
1299 // Make the cascade as a 2Prong decay and check if it passes Dstar
1300 // reconstruction cuts
1304 Bool_t dummy1,dummy2,dummy3;
1306 // We use Make2Prong to construct the AliAODRecoCascadeHF
1307 // (which inherits from AliAODRecoDecayHF2Prong)
1308 AliAODRecoCascadeHF *theCascade =
1309 (AliAODRecoCascadeHF*)Make2Prong(twoTrackArray,event,secVert,dca,
1310 dummy1,dummy2,dummy3);
1311 if(!theCascade) return 0x0;
1314 AliESDtrack *trackPi = (AliESDtrack*)twoTrackArray->UncheckedAt(0);
1315 theCascade->SetCharge(trackPi->Charge());
1317 //--- selection cuts
1319 AliAODRecoCascadeHF *tmpCascade = new AliAODRecoCascadeHF(*theCascade);
1320 tmpCascade->GetSecondaryVtx()->AddDaughter(trackPi);
1321 tmpCascade->GetSecondaryVtx()->AddDaughter(rd2Prong);
1322 AliAODVertex *primVertexAOD=0;
1323 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx) {
1324 // take event primary vertex
1325 primVertexAOD = PrimaryVertex();
1326 tmpCascade->SetOwnPrimaryVtx(primVertexAOD);
1327 rd2Prong->SetOwnPrimaryVtx(primVertexAOD);
1331 okDstar = (Bool_t)fCutsDStartoKpipi->IsSelected(tmpCascade,AliRDHFCuts::kCandidate);
1332 if(okDstar) theCascade->SetSelectionBit(AliRDHFCuts::kDstarCuts);
1334 tmpCascade->GetSecondaryVtx()->RemoveDaughters();
1335 tmpCascade->UnsetOwnPrimaryVtx();
1336 delete tmpCascade; tmpCascade=NULL;
1337 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx && !fMixEvent) {
1338 rd2Prong->UnsetOwnPrimaryVtx();
1340 if(primVertexAOD) {delete primVertexAOD; primVertexAOD=NULL;}
1348 //----------------------------------------------------------------------------
1349 AliAODRecoCascadeHF* AliAnalysisVertexingHF::MakeCascade(
1350 TObjArray *twoTrackArray,AliVEvent *event,
1351 AliAODVertex *secVert,
1354 Bool_t &okCascades) const
1357 // Make the cascade as a 2Prong decay and check if it passes
1358 // cascades reconstruction cuts
1360 // AliDebug(2,Form(" building the cascade"));
1362 Bool_t dummy1,dummy2,dummy3;
1364 // We use Make2Prong to construct the AliAODRecoCascadeHF
1365 // (which inherits from AliAODRecoDecayHF2Prong)
1366 AliAODRecoCascadeHF *theCascade =
1367 (AliAODRecoCascadeHF*)Make2Prong(twoTrackArray,event,secVert,dca,
1368 dummy1,dummy2,dummy3);
1369 if(!theCascade) return 0x0;
1371 // bachelor track and charge
1372 AliESDtrack *trackBachelor = (AliESDtrack*)twoTrackArray->UncheckedAt(0);
1373 theCascade->SetCharge(trackBachelor->Charge());
1375 //--- selection cuts
1377 AliAODRecoCascadeHF *tmpCascade = new AliAODRecoCascadeHF(*theCascade);
1378 tmpCascade->GetSecondaryVtx()->AddDaughter(trackBachelor);
1379 tmpCascade->GetSecondaryVtx()->AddDaughter(v0);
1380 AliAODVertex *primVertexAOD=0;
1381 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx) {
1382 // take event primary vertex
1383 primVertexAOD = PrimaryVertex();
1384 if(!primVertexAOD) primVertexAOD = (AliAODVertex*)event->GetPrimaryVertex();
1385 tmpCascade->SetOwnPrimaryVtx(primVertexAOD);
1389 if(fCascades && fInputAOD){
1390 okCascades = (Bool_t)fCutsLctoV0->IsSelected(tmpCascade,AliRDHFCuts::kCandidate);
1393 //AliDebug(2,Form("The cascade is contructed from ESDs, no cuts are applied"));
1395 }// no cuts implemented from ESDs
1396 tmpCascade->GetSecondaryVtx()->RemoveDaughters();
1397 tmpCascade->UnsetOwnPrimaryVtx();
1398 delete tmpCascade; tmpCascade=NULL;
1399 if(primVertexAOD) {delete primVertexAOD; primVertexAOD=NULL;}
1405 //-----------------------------------------------------------------------------
1406 AliAODRecoDecayHF2Prong *AliAnalysisVertexingHF::Make2Prong(
1407 TObjArray *twoTrackArray,AliVEvent *event,
1408 AliAODVertex *secVert,Double_t dca,
1409 Bool_t &okD0,Bool_t &okJPSI,
1410 Bool_t &okD0fromDstar) const
1412 // Make 2Prong candidates and check if they pass D0toKpi or BtoJPSI
1413 // reconstruction cuts
1414 // G.E.Bruno (J/psi), A.Dainese (D0->Kpi)
1416 okD0=kFALSE; okJPSI=kFALSE; okD0fromDstar=kFALSE;
1418 Double_t px[2],py[2],pz[2],d0[2],d0err[2];
1419 AliESDtrack *postrack = (AliESDtrack*)twoTrackArray->UncheckedAt(0);
1420 AliESDtrack *negtrack = (AliESDtrack*)twoTrackArray->UncheckedAt(1);
1422 // propagate tracks to secondary vertex, to compute inv. mass
1423 postrack->PropagateToDCA(secVert,fBzkG,kVeryBig);
1424 negtrack->PropagateToDCA(secVert,fBzkG,kVeryBig);
1426 Double_t momentum[3];
1427 postrack->GetPxPyPz(momentum);
1428 px[0] = momentum[0]; py[0] = momentum[1]; pz[0] = momentum[2];
1429 negtrack->GetPxPyPz(momentum);
1430 px[1] = momentum[0]; py[1] = momentum[1]; pz[1] = momentum[2];
1433 // invariant mass cut (try to improve coding here..)
1434 Bool_t okMassCut=kFALSE;
1435 if(!okMassCut && fD0toKpi) if(SelectInvMassAndPt(0,2,px,py,pz)) okMassCut=kTRUE;
1436 if(!okMassCut && fJPSItoEle) if(SelectInvMassAndPt(1,2,px,py,pz)) okMassCut=kTRUE;
1437 if(!okMassCut && fDstar) if(SelectInvMassAndPt(3,2,px,py,pz)) okMassCut=kTRUE;
1439 //AliDebug(2," candidate didn't pass mass cut");
1442 // primary vertex to be used by this candidate
1443 AliAODVertex *primVertexAOD = PrimaryVertex(twoTrackArray,event);
1444 if(!primVertexAOD) return 0x0;
1447 Double_t d0z0[2],covd0z0[3];
1448 postrack->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1450 d0err[0] = TMath::Sqrt(covd0z0[0]);
1451 negtrack->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1453 d0err[1] = TMath::Sqrt(covd0z0[0]);
1455 // create the object AliAODRecoDecayHF2Prong
1456 AliAODRecoDecayHF2Prong *the2Prong = new AliAODRecoDecayHF2Prong(secVert,px,py,pz,d0,d0err,dca);
1457 the2Prong->SetOwnPrimaryVtx(primVertexAOD);
1458 UShort_t id[2]={(UShort_t)postrack->GetID(),(UShort_t)negtrack->GetID()};
1459 the2Prong->SetProngIDs(2,id);
1460 delete primVertexAOD; primVertexAOD=NULL;
1463 if(postrack->Charge()!=0 && negtrack->Charge()!=0) { // don't apply these cuts if it's a Dstar
1466 okD0 = (Bool_t)fCutsD0toKpi->IsSelected(the2Prong,AliRDHFCuts::kCandidate);
1467 if(okD0) the2Prong->SetSelectionBit(AliRDHFCuts::kD0toKpiCuts);
1469 //if(fDebug && fD0toKpi) printf(" %d\n",(Int_t)okD0);
1470 // select J/psi from B
1472 okJPSI = (Bool_t)fCutsJpsitoee->IsSelected(the2Prong,AliRDHFCuts::kCandidate);
1474 //if(fDebug && fJPSItoEle) printf(" %d\n",(Int_t)okJPSI);
1475 // select D0->Kpi from Dstar
1477 okD0fromDstar = (Bool_t)fCutsDStartoKpipi->IsD0FromDStarSelected(the2Prong->Pt(),the2Prong,AliRDHFCuts::kCandidate);
1478 if(okD0fromDstar) the2Prong->SetSelectionBit(AliRDHFCuts::kD0fromDstarCuts);
1480 //if(fDebug && fDstar) printf(" %d\n",(Int_t)okD0fromDstar);
1484 // remove the primary vertex (was used only for selection)
1485 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx && !fMixEvent) {
1486 the2Prong->UnsetOwnPrimaryVtx();
1489 // get PID info from ESD
1490 Double_t esdpid0[5]={0.,0.,0.,0.,0.};
1491 if(postrack->GetStatus()&AliESDtrack::kESDpid) postrack->GetESDpid(esdpid0);
1492 Double_t esdpid1[5]={0.,0.,0.,0.,0.};
1493 if(negtrack->GetStatus()&AliESDtrack::kESDpid) negtrack->GetESDpid(esdpid1);
1494 Double_t esdpid[10];
1495 for(Int_t i=0;i<5;i++) {
1496 esdpid[i] = esdpid0[i];
1497 esdpid[5+i] = esdpid1[i];
1499 the2Prong->SetPID(2,esdpid);
1503 //----------------------------------------------------------------------------
1504 AliAODRecoDecayHF3Prong* AliAnalysisVertexingHF::Make3Prong(
1505 TObjArray *threeTrackArray,AliVEvent *event,
1506 AliAODVertex *secVert,Double_t dispersion,
1507 const AliAODVertex *vertexp1n1,const AliAODVertex *vertexp2n1,
1508 Double_t dcap1n1,Double_t dcap2n1,Double_t dcap1p2,
1509 Bool_t &ok3Prong) const
1511 // Make 3Prong candidates and check if they pass Dplus or Ds or Lambdac
1512 // reconstruction cuts
1517 if(!secVert || !vertexp1n1 || !vertexp2n1) return 0x0;
1519 Double_t px[3],py[3],pz[3],d0[3],d0err[3];
1520 Double_t momentum[3];
1523 AliESDtrack *postrack1 = (AliESDtrack*)threeTrackArray->UncheckedAt(0);
1524 AliESDtrack *negtrack = (AliESDtrack*)threeTrackArray->UncheckedAt(1);
1525 AliESDtrack *postrack2 = (AliESDtrack*)threeTrackArray->UncheckedAt(2);
1527 postrack1->PropagateToDCA(secVert,fBzkG,kVeryBig);
1528 negtrack->PropagateToDCA(secVert,fBzkG,kVeryBig);
1529 postrack2->PropagateToDCA(secVert,fBzkG,kVeryBig);
1530 postrack1->GetPxPyPz(momentum);
1531 px[0] = momentum[0]; py[0] = momentum[1]; pz[0] = momentum[2];
1532 negtrack->GetPxPyPz(momentum);
1533 px[1] = momentum[0]; py[1] = momentum[1]; pz[1] = momentum[2];
1534 postrack2->GetPxPyPz(momentum);
1535 px[2] = momentum[0]; py[2] = momentum[1]; pz[2] = momentum[2];
1537 // invariant mass cut for D+, Ds, Lc
1538 Bool_t okMassCut=kFALSE;
1539 if(fMassCutBeforeVertexing) okMassCut=kTRUE; // mass cut already done and passed
1540 if(!okMassCut && f3Prong) if(SelectInvMassAndPt(2,3,px,py,pz)) okMassCut=kTRUE;
1542 //AliDebug(2," candidate didn't pass mass cut");
1546 // primary vertex to be used by this candidate
1547 AliAODVertex *primVertexAOD = PrimaryVertex(threeTrackArray,event);
1548 if(!primVertexAOD) return 0x0;
1550 Double_t d0z0[2],covd0z0[3];
1551 postrack1->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1553 d0err[0] = TMath::Sqrt(covd0z0[0]);
1554 negtrack->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1556 d0err[1] = TMath::Sqrt(covd0z0[0]);
1557 postrack2->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1559 d0err[2] = TMath::Sqrt(covd0z0[0]);
1562 // create the object AliAODRecoDecayHF3Prong
1563 Double_t pos[3]; primVertexAOD->GetXYZ(pos);
1564 Double_t dca[3]={dcap1n1,dcap2n1,dcap1p2};
1565 Double_t dist12=TMath::Sqrt((vertexp1n1->GetX()-pos[0])*(vertexp1n1->GetX()-pos[0])+(vertexp1n1->GetY()-pos[1])*(vertexp1n1->GetY()-pos[1])+(vertexp1n1->GetZ()-pos[2])*(vertexp1n1->GetZ()-pos[2]));
1566 Double_t dist23=TMath::Sqrt((vertexp2n1->GetX()-pos[0])*(vertexp2n1->GetX()-pos[0])+(vertexp2n1->GetY()-pos[1])*(vertexp2n1->GetY()-pos[1])+(vertexp2n1->GetZ()-pos[2])*(vertexp2n1->GetZ()-pos[2]));
1567 Short_t charge=(Short_t)(postrack1->Charge()+postrack2->Charge()+negtrack->Charge());
1568 AliAODRecoDecayHF3Prong *the3Prong = new AliAODRecoDecayHF3Prong(secVert,px,py,pz,d0,d0err,dca,dispersion,dist12,dist23,charge);
1569 the3Prong->SetOwnPrimaryVtx(primVertexAOD);
1570 UShort_t id[3]={(UShort_t)postrack1->GetID(),(UShort_t)negtrack->GetID(),(UShort_t)postrack2->GetID()};
1571 the3Prong->SetProngIDs(3,id);
1573 delete primVertexAOD; primVertexAOD=NULL;
1575 // select D+->Kpipi, Ds->KKpi, Lc->pKpi
1579 if(fCutsDplustoKpipi->IsSelected(the3Prong,AliRDHFCuts::kCandidate)) {
1581 the3Prong->SetSelectionBit(AliRDHFCuts::kDplusCuts);
1583 if(fCutsDstoKKpi->IsSelected(the3Prong,AliRDHFCuts::kCandidate)) {
1585 the3Prong->SetSelectionBit(AliRDHFCuts::kDsCuts);
1587 if(fCutsLctopKpi->IsSelected(the3Prong,AliRDHFCuts::kCandidate)) {
1589 the3Prong->SetSelectionBit(AliRDHFCuts::kLcCuts);
1592 //if(fDebug) printf("ok3Prong: %d\n",(Int_t)ok3Prong);
1594 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx && !fMixEvent) {
1595 the3Prong->UnsetOwnPrimaryVtx();
1598 // get PID info from ESD
1599 Double_t esdpid0[5]={0.,0.,0.,0.,0.};
1600 if(postrack1->GetStatus()&AliESDtrack::kESDpid) postrack1->GetESDpid(esdpid0);
1601 Double_t esdpid1[5]={0.,0.,0.,0.,0.};
1602 if(negtrack->GetStatus()&AliESDtrack::kESDpid) negtrack->GetESDpid(esdpid1);
1603 Double_t esdpid2[5]={0.,0.,0.,0.,0.};
1604 if(postrack2->GetStatus()&AliESDtrack::kESDpid) postrack2->GetESDpid(esdpid2);
1606 Double_t esdpid[15];
1607 for(Int_t i=0;i<5;i++) {
1608 esdpid[i] = esdpid0[i];
1609 esdpid[5+i] = esdpid1[i];
1610 esdpid[10+i] = esdpid2[i];
1612 the3Prong->SetPID(3,esdpid);
1616 //----------------------------------------------------------------------------
1617 AliAODRecoDecayHF4Prong* AliAnalysisVertexingHF::Make4Prong(
1618 TObjArray *fourTrackArray,AliVEvent *event,
1619 AliAODVertex *secVert,
1620 const AliAODVertex *vertexp1n1,
1621 const AliAODVertex *vertexp1n1p2,
1622 Double_t dcap1n1,Double_t dcap1n2,
1623 Double_t dcap2n1,Double_t dcap2n2,
1624 Bool_t &ok4Prong) const
1626 // Make 4Prong candidates and check if they pass D0toKpipipi
1627 // reconstruction cuts
1628 // G.E.Bruno, R.Romita
1631 if(!secVert || !vertexp1n1 || !vertexp1n1p2) return 0x0;
1633 Double_t px[4],py[4],pz[4],d0[4],d0err[4];//d0z[3];
1635 AliESDtrack *postrack1 = (AliESDtrack*)fourTrackArray->UncheckedAt(0);
1636 AliESDtrack *negtrack1 = (AliESDtrack*)fourTrackArray->UncheckedAt(1);
1637 AliESDtrack *postrack2 = (AliESDtrack*)fourTrackArray->UncheckedAt(2);
1638 AliESDtrack *negtrack2 = (AliESDtrack*)fourTrackArray->UncheckedAt(3);
1640 postrack1->PropagateToDCA(secVert,fBzkG,kVeryBig);
1641 negtrack1->PropagateToDCA(secVert,fBzkG,kVeryBig);
1642 postrack2->PropagateToDCA(secVert,fBzkG,kVeryBig);
1643 negtrack2->PropagateToDCA(secVert,fBzkG,kVeryBig);
1645 Double_t momentum[3];
1646 postrack1->GetPxPyPz(momentum);
1647 px[0] = momentum[0]; py[0] = momentum[1]; pz[0] = momentum[2];
1648 negtrack1->GetPxPyPz(momentum);
1649 px[1] = momentum[0]; py[1] = momentum[1]; pz[1] = momentum[2];
1650 postrack2->GetPxPyPz(momentum);
1651 px[2] = momentum[0]; py[2] = momentum[1]; pz[2] = momentum[2];
1652 negtrack2->GetPxPyPz(momentum);
1653 px[3] = momentum[0]; py[3] = momentum[1]; pz[3] = momentum[2];
1655 // invariant mass cut for rho or D0 (try to improve coding here..)
1656 Bool_t okMassCut=kFALSE;
1657 if(fMassCutBeforeVertexing) okMassCut=kTRUE; // mass cut already done and passed
1658 if(!okMassCut && !(fCutsD0toKpipipi->GetUsePID())) { //no PID, to be implemented with PID
1659 if(SelectInvMassAndPt(4,4,px,py,pz)) okMassCut=kTRUE;
1662 //if(fDebug) printf(" candidate didn't pass mass cut\n");
1663 //printf(" candidate didn't pass mass cut\n");
1667 // primary vertex to be used by this candidate
1668 AliAODVertex *primVertexAOD = PrimaryVertex(fourTrackArray,event);
1669 if(!primVertexAOD) return 0x0;
1671 Double_t d0z0[2],covd0z0[3];
1672 postrack1->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1674 d0err[0] = TMath::Sqrt(covd0z0[0]);
1675 negtrack1->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1677 d0err[1] = TMath::Sqrt(covd0z0[0]);
1678 postrack2->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1680 d0err[2] = TMath::Sqrt(covd0z0[0]);
1681 negtrack2->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
1683 d0err[3] = TMath::Sqrt(covd0z0[0]);
1686 // create the object AliAODRecoDecayHF4Prong
1687 Double_t pos[3]; primVertexAOD->GetXYZ(pos);
1688 Double_t dca[6]={dcap1n1,0.,dcap1n2,dcap2n1,0.,dcap2n2};
1689 Double_t dist12=TMath::Sqrt((vertexp1n1->GetX()-pos[0])*(vertexp1n1->GetX()-pos[0])+(vertexp1n1->GetY()-pos[1])*(vertexp1n1->GetY()-pos[1])+(vertexp1n1->GetZ()-pos[2])*(vertexp1n1->GetZ()-pos[2]));
1690 Double_t dist3=TMath::Sqrt((vertexp1n1p2->GetX()-pos[0])*(vertexp1n1p2->GetX()-pos[0])+(vertexp1n1p2->GetY()-pos[1])*(vertexp1n1p2->GetY()-pos[1])+(vertexp1n1p2->GetZ()-pos[2])*(vertexp1n1p2->GetZ()-pos[2]));
1691 Double_t dist4=TMath::Sqrt((secVert->GetX()-pos[0])*(secVert->GetX()-pos[0])+(secVert->GetY()-pos[1])*(secVert->GetY()-pos[1])+(secVert->GetZ()-pos[2])*(secVert->GetZ()-pos[2]));
1693 AliAODRecoDecayHF4Prong *the4Prong = new AliAODRecoDecayHF4Prong(secVert,px,py,pz,d0,d0err,dca,dist12,dist3,dist4,charge);
1694 the4Prong->SetOwnPrimaryVtx(primVertexAOD);
1695 UShort_t id[4]={(UShort_t)postrack1->GetID(),(UShort_t)negtrack1->GetID(),(UShort_t)postrack2->GetID(),(UShort_t)negtrack2->GetID()};
1696 the4Prong->SetProngIDs(4,id);
1698 delete primVertexAOD; primVertexAOD=NULL;
1700 ok4Prong=(Bool_t)fCutsD0toKpipipi->IsSelected(the4Prong,AliRDHFCuts::kCandidate);
1703 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx && !fMixEvent) {
1704 the4Prong->UnsetOwnPrimaryVtx();
1708 // get PID info from ESD
1709 Double_t esdpid0[5]={0.,0.,0.,0.,0.};
1710 if(postrack1->GetStatus()&AliESDtrack::kESDpid) postrack1->GetESDpid(esdpid0);
1711 Double_t esdpid1[5]={0.,0.,0.,0.,0.};
1712 if(negtrack1->GetStatus()&AliESDtrack::kESDpid) negtrack1->GetESDpid(esdpid1);
1713 Double_t esdpid2[5]={0.,0.,0.,0.,0.};
1714 if(postrack2->GetStatus()&AliESDtrack::kESDpid) postrack2->GetESDpid(esdpid2);
1715 Double_t esdpid3[5]={0.,0.,0.,0.,0.};
1716 if(negtrack2->GetStatus()&AliESDtrack::kESDpid) negtrack2->GetESDpid(esdpid3);
1718 Double_t esdpid[20];
1719 for(Int_t i=0;i<5;i++) {
1720 esdpid[i] = esdpid0[i];
1721 esdpid[5+i] = esdpid1[i];
1722 esdpid[10+i] = esdpid2[i];
1723 esdpid[15+i] = esdpid3[i];
1725 the4Prong->SetPID(4,esdpid);
1729 //-----------------------------------------------------------------------------
1730 AliAODVertex* AliAnalysisVertexingHF::PrimaryVertex(const TObjArray *trkArray,
1731 AliVEvent *event) const
1733 // Returns primary vertex to be used for this candidate
1735 AliESDVertex *vertexESD = 0;
1736 AliAODVertex *vertexAOD = 0;
1739 if(!fRecoPrimVtxSkippingTrks && !fRmTrksFromPrimVtx) {
1740 // primary vertex from the input event
1742 vertexESD = new AliESDVertex(*fV1);
1745 // primary vertex specific to this candidate
1747 Int_t nTrks = trkArray->GetEntriesFast();
1748 AliVertexerTracks *vertexer = new AliVertexerTracks(event->GetMagneticField());
1750 if(fRecoPrimVtxSkippingTrks) {
1751 // recalculating the vertex
1753 if(strstr(fV1->GetTitle(),"VertexerTracksWithConstraint")) {
1754 Float_t diamondcovxy[3];
1755 event->GetDiamondCovXY(diamondcovxy);
1756 Double_t pos[3]={event->GetDiamondX(),event->GetDiamondY(),0.};
1757 Double_t cov[6]={diamondcovxy[0],diamondcovxy[1],diamondcovxy[2],0.,0.,10.*10.};
1758 AliESDVertex *diamond = new AliESDVertex(pos,cov,1.,1);
1759 vertexer->SetVtxStart(diamond);
1760 delete diamond; diamond=NULL;
1761 if(strstr(fV1->GetTitle(),"VertexerTracksWithConstraintOnlyFitter"))
1762 vertexer->SetOnlyFitter();
1764 Int_t skipped[1000];
1765 Int_t nTrksToSkip=0,id;
1766 AliExternalTrackParam *t = 0;
1767 for(Int_t i=0; i<nTrks; i++) {
1768 t = (AliExternalTrackParam*)trkArray->UncheckedAt(i);
1769 id = (Int_t)t->GetID();
1771 skipped[nTrksToSkip++] = id;
1774 // For AOD, skip also tracks without covariance matrix
1776 Double_t covtest[21];
1777 for(Int_t j=0; j<event->GetNumberOfTracks(); j++) {
1778 AliVTrack *vtrack = (AliVTrack*)event->GetTrack(j);
1779 if(!vtrack->GetCovarianceXYZPxPyPz(covtest)) {
1780 id = (Int_t)vtrack->GetID();
1782 skipped[nTrksToSkip++] = id;
1787 vertexer->SetSkipTracks(nTrksToSkip,skipped);
1788 vertexESD = (AliESDVertex*)vertexer->FindPrimaryVertex(event);
1790 } else if(fRmTrksFromPrimVtx) {
1791 // removing the prongs tracks
1793 TObjArray rmArray(nTrks);
1794 UShort_t *rmId = new UShort_t[nTrks];
1795 AliESDtrack *esdTrack = 0;
1797 for(Int_t i=0; i<nTrks; i++) {
1798 t = (AliESDtrack*)trkArray->UncheckedAt(i);
1799 esdTrack = new AliESDtrack(*t);
1800 rmArray.AddLast(esdTrack);
1801 if(esdTrack->GetID()>=0) {
1802 rmId[i]=(UShort_t)esdTrack->GetID();
1807 Float_t diamondxy[2]={event->GetDiamondX(),event->GetDiamondY()};
1808 vertexESD = vertexer->RemoveTracksFromVertex(fV1,&rmArray,rmId,diamondxy);
1809 delete [] rmId; rmId=NULL;
1814 if(!vertexESD) return vertexAOD;
1815 if(vertexESD->GetNContributors()<=0) {
1816 //AliDebug(2,"vertexing failed");
1817 delete vertexESD; vertexESD=NULL;
1821 delete vertexer; vertexer=NULL;
1825 // convert to AliAODVertex
1826 Double_t pos[3],cov[6],chi2perNDF;
1827 vertexESD->GetXYZ(pos); // position
1828 vertexESD->GetCovMatrix(cov); //covariance matrix
1829 chi2perNDF = vertexESD->GetChi2toNDF();
1830 delete vertexESD; vertexESD=NULL;
1832 vertexAOD = new AliAODVertex(pos,cov,chi2perNDF);
1836 //-----------------------------------------------------------------------------
1837 void AliAnalysisVertexingHF::PrintStatus() const {
1838 // Print parameters being used
1840 //printf("Preselections:\n");
1841 // fTrackFilter->Dump();
1843 printf("Secondary vertex with Kalman filter package (AliKFParticle)\n");
1845 printf("Secondary vertex with AliVertexerTracks\n");
1847 if(fRecoPrimVtxSkippingTrks) printf("RecoPrimVtxSkippingTrks\n");
1848 if(fRmTrksFromPrimVtx) printf("RmTrksFromPrimVtx\n");
1850 printf("Reconstruct D0->Kpi candidates with cuts:\n");
1851 if(fCutsD0toKpi) fCutsD0toKpi->PrintAll();
1854 printf("Reconstruct D*->D0pi candidates with cuts:\n");
1855 if(fFindVertexForDstar) {
1856 printf(" Reconstruct a secondary vertex for the D*\n");
1858 printf(" Assume the D* comes from the primary vertex\n");
1860 if(fCutsDStartoKpipi) fCutsDStartoKpipi->PrintAll();
1863 printf("Reconstruct J/psi from B candidates with cuts:\n");
1864 if(fCutsJpsitoee) fCutsJpsitoee->PrintAll();
1867 printf("Reconstruct 3 prong candidates.\n");
1868 printf(" D+->Kpipi cuts:\n");
1869 if(fCutsDplustoKpipi) fCutsDplustoKpipi->PrintAll();
1870 printf(" Ds->KKpi cuts:\n");
1871 if(fCutsDstoKKpi) fCutsDstoKKpi->PrintAll();
1872 printf(" Lc->pKpi cuts:\n");
1873 if(fCutsLctopKpi) fCutsLctopKpi->PrintAll();
1876 printf("Reconstruct 4 prong candidates.\n");
1877 printf(" D0->Kpipipi cuts:\n");
1878 if(fCutsD0toKpipipi) fCutsD0toKpipipi->PrintAll();
1881 printf("Reconstruct cascades candidates formed with v0s.\n");
1882 printf(" Lc -> k0s P & Lc -> L Pi cuts:\n");
1883 if(fCutsLctoV0) fCutsLctoV0->PrintAll();
1888 //-----------------------------------------------------------------------------
1889 AliAODVertex* AliAnalysisVertexingHF::ReconstructSecondaryVertex(TObjArray *trkArray,
1890 Double_t &dispersion,Bool_t useTRefArray) const
1892 // Secondary vertex reconstruction with AliVertexerTracks or AliKFParticle
1894 AliESDVertex *vertexESD = 0;
1895 AliAODVertex *vertexAOD = 0;
1897 if(!fSecVtxWithKF) { // AliVertexerTracks
1899 AliVertexerTracks *vertexer = new AliVertexerTracks(fBzkG);
1900 vertexer->SetVtxStart(fV1);
1901 vertexESD = (AliESDVertex*)vertexer->VertexForSelectedESDTracks(trkArray);
1902 delete vertexer; vertexer=NULL;
1904 if(!vertexESD) return vertexAOD;
1906 if(vertexESD->GetNContributors()!=trkArray->GetEntriesFast()) {
1907 //AliDebug(2,"vertexing failed");
1908 delete vertexESD; vertexESD=NULL;
1912 } else { // Kalman Filter vertexer (AliKFParticle)
1914 AliKFParticle::SetField(fBzkG);
1916 AliKFVertex vertexKF;
1918 Int_t nTrks = trkArray->GetEntriesFast();
1919 for(Int_t i=0; i<nTrks; i++) {
1920 AliESDtrack *esdTrack = (AliESDtrack*)trkArray->At(i);
1921 AliKFParticle daughterKF(*esdTrack,211);
1922 vertexKF.AddDaughter(daughterKF);
1924 vertexESD = new AliESDVertex(vertexKF.Parameters(),
1925 vertexKF.CovarianceMatrix(),
1927 vertexKF.GetNContributors());
1931 // convert to AliAODVertex
1932 Double_t pos[3],cov[6],chi2perNDF;
1933 vertexESD->GetXYZ(pos); // position
1934 vertexESD->GetCovMatrix(cov); //covariance matrix
1935 chi2perNDF = vertexESD->GetChi2toNDF();
1936 dispersion = vertexESD->GetDispersion();
1937 delete vertexESD; vertexESD=NULL;
1939 Int_t nprongs= (useTRefArray ? 0 : trkArray->GetEntriesFast());
1940 vertexAOD = new AliAODVertex(pos,cov,chi2perNDF,0x0,-1,AliAODVertex::kUndef,nprongs);
1944 //-----------------------------------------------------------------------------
1945 Bool_t AliAnalysisVertexingHF::SelectInvMassAndPt(TObjArray *trkArray) const {
1946 // Invariant mass cut on tracks
1948 Int_t nProngs=trkArray->GetEntriesFast();
1949 Int_t retval=kFALSE;
1951 Double_t momentum[3];
1952 Double_t px3[3],py3[3],pz3[3];
1953 Double_t px4[4],py4[4],pz4[4];
1954 AliESDtrack *postrack1=0;
1955 AliESDtrack *postrack2=0;
1956 AliESDtrack *negtrack1=0;
1957 AliESDtrack *negtrack2=0;
1961 // invariant mass cut for D+, Ds, Lc
1962 postrack1 = (AliESDtrack*)trkArray->UncheckedAt(0);
1963 negtrack1 = (AliESDtrack*)trkArray->UncheckedAt(1);
1964 postrack2 = (AliESDtrack*)trkArray->UncheckedAt(2);
1965 postrack1->GetPxPyPz(momentum);
1966 px3[0] = momentum[0]; py3[0] = momentum[1]; pz3[0] = momentum[2];
1967 negtrack1->GetPxPyPz(momentum);
1968 px3[1] = momentum[0]; py3[1] = momentum[1]; pz3[1] = momentum[2];
1969 postrack2->GetPxPyPz(momentum);
1970 px3[2] = momentum[0]; py3[2] = momentum[1]; pz3[2] = momentum[2];
1971 retval = SelectInvMassAndPt(2,3,px3,py3,pz3);
1974 // invariant mass cut for D0->4prong
1975 postrack1 = (AliESDtrack*)trkArray->UncheckedAt(0);
1976 negtrack1 = (AliESDtrack*)trkArray->UncheckedAt(1);
1977 postrack2 = (AliESDtrack*)trkArray->UncheckedAt(2);
1978 negtrack2 = (AliESDtrack*)trkArray->UncheckedAt(3);
1979 postrack1->GetPxPyPz(momentum);
1980 px4[0] = momentum[0]; py4[0] = momentum[1]; pz4[0] = momentum[2];
1981 negtrack1->GetPxPyPz(momentum);
1982 px4[1] = momentum[0]; py4[1] = momentum[1]; pz4[1] = momentum[2];
1983 postrack2->GetPxPyPz(momentum);
1984 px4[2] = momentum[0]; py4[2] = momentum[1]; pz4[2] = momentum[2];
1985 negtrack2->GetPxPyPz(momentum);
1986 px4[3] = momentum[0]; py4[3] = momentum[1]; pz4[3] = momentum[2];
1987 retval = SelectInvMassAndPt(4,4,px4,py4,pz4);
1990 printf("SelectInvMassAndPt(): wrong decay selection\n");
1996 //-----------------------------------------------------------------------------
1997 Bool_t AliAnalysisVertexingHF::SelectInvMassAndPt(Int_t decay,
2001 Double_t *pz) const {
2002 // Check invariant mass cut and pt candidate cut
2004 UInt_t pdg2[2],pdg3[3],pdg4[4];
2008 Bool_t retval=kFALSE;
2012 fMassCalc2->SetPxPyPzProngs(nprongs,px,py,pz);
2014 minPt=fCutsD0toKpi->GetMinPtCandidate();
2016 if(fMassCalc2->Pt2() < minPt*minPt) break;
2018 pdg2[0]=211; pdg2[1]=321;
2019 mPDG=TDatabasePDG::Instance()->GetParticle(421)->Mass();
2020 minv = fMassCalc2->InvMass(nprongs,pdg2);
2021 if(TMath::Abs(minv-mPDG)<fCutsD0toKpi->GetMassCut()) retval=kTRUE;
2022 pdg2[0]=321; pdg2[1]=211;
2023 minv = fMassCalc2->InvMass(nprongs,pdg2);
2024 if(TMath::Abs(minv-mPDG)<fCutsD0toKpi->GetMassCut()) retval=kTRUE;
2027 fMassCalc2->SetPxPyPzProngs(nprongs,px,py,pz);
2029 minPt=fCutsJpsitoee->GetMinPtCandidate();
2031 if(fMassCalc2->Pt2() < minPt*minPt) break;
2033 pdg2[0]=11; pdg2[1]=11;
2034 mPDG=TDatabasePDG::Instance()->GetParticle(443)->Mass();
2035 minv = fMassCalc2->InvMass(nprongs,pdg2);
2036 if(TMath::Abs(minv-mPDG)<fCutsJpsitoee->GetMassCut()) retval=kTRUE;
2038 case 2: // D+->Kpipi
2039 fMassCalc3->SetPxPyPzProngs(nprongs,px,py,pz);
2041 minPt=TMath::Min(fCutsDplustoKpipi->GetMinPtCandidate(),fCutsDstoKKpi->GetMinPtCandidate());
2042 minPt=TMath::Min(minPt,fCutsLctopKpi->GetMinPtCandidate());
2044 if(fMassCalc3->Pt2() < minPt*minPt) break;
2046 pdg3[0]=211; pdg3[1]=321; pdg3[2]=211;
2047 mPDG=TDatabasePDG::Instance()->GetParticle(411)->Mass();
2048 minv = fMassCalc3->InvMass(nprongs,pdg3);
2049 if(TMath::Abs(minv-mPDG)<fCutsDplustoKpipi->GetMassCut()) retval=kTRUE;
2051 pdg3[0]=321; pdg3[1]=321; pdg3[2]=211;
2052 mPDG=TDatabasePDG::Instance()->GetParticle(431)->Mass();
2053 minv = fMassCalc3->InvMass(nprongs,pdg3);
2054 if(TMath::Abs(minv-mPDG)<fCutsDstoKKpi->GetMassCut()) retval=kTRUE;
2055 pdg3[0]=211; pdg3[1]=321; pdg3[2]=321;
2056 minv = fMassCalc3->InvMass(nprongs,pdg3);
2057 if(TMath::Abs(minv-mPDG)<fCutsDstoKKpi->GetMassCut()) retval=kTRUE;
2059 pdg3[0]=2212; pdg3[1]=321; pdg3[2]=211;
2060 mPDG=TDatabasePDG::Instance()->GetParticle(4122)->Mass();
2061 minv = fMassCalc3->InvMass(nprongs,pdg3);
2062 if(TMath::Abs(minv-mPDG)<fCutsLctopKpi->GetMassCut()) retval=kTRUE;
2063 pdg3[0]=211; pdg3[1]=321; pdg3[2]=2212;
2064 minv = fMassCalc3->InvMass(nprongs,pdg3);
2065 if(TMath::Abs(minv-mPDG)<fCutsLctopKpi->GetMassCut()) retval=kTRUE;
2068 fMassCalc2->SetPxPyPzProngs(nprongs,px,py,pz);
2070 minPt=fCutsDStartoKpipi->GetMinPtCandidate();
2072 if(fMassCalc2->Pt2() < minPt*minPt) break;
2074 pdg2[0]=211; pdg2[1]=421; // in twoTrackArrayCasc we put the pion first
2075 mPDG=TDatabasePDG::Instance()->GetParticle(413)->Mass();
2076 minv = fMassCalc2->InvMass(nprongs,pdg2);
2077 if(TMath::Abs(minv-mPDG)<fCutsDStartoKpipi->GetMassCut()) retval=kTRUE;
2079 case 4: // D0->Kpipipi without PID
2080 fMassCalc4->SetPxPyPzProngs(nprongs,px,py,pz);
2082 minPt=fCutsD0toKpipipi->GetMinPtCandidate();
2084 if(fMassCalc4->Pt2() < minPt*minPt) break;
2086 pdg4[0]=321; pdg4[1]=211; pdg4[2]=211; pdg4[3]=211;
2087 mPDG=TDatabasePDG::Instance()->GetParticle(421)->Mass();
2088 minv = fMassCalc4->InvMass(nprongs,pdg4);
2089 if(TMath::Abs(minv-mPDG)<fCutsD0toKpipipi->GetMassCut()) retval=kTRUE;
2090 pdg4[0]=211; pdg4[1]=321; pdg4[2]=211; pdg4[3]=211;
2091 mPDG=TDatabasePDG::Instance()->GetParticle(421)->Mass();
2092 minv = fMassCalc4->InvMass(nprongs,pdg4);
2093 if(TMath::Abs(minv-mPDG)<fCutsD0toKpipipi->GetMassCut()) retval=kTRUE;
2094 pdg4[0]=211; pdg4[1]=211; pdg4[2]=321; pdg4[3]=211;
2095 mPDG=TDatabasePDG::Instance()->GetParticle(421)->Mass();
2096 minv = fMassCalc4->InvMass(nprongs,pdg4);
2097 if(TMath::Abs(minv-mPDG)<fCutsD0toKpipipi->GetMassCut()) retval=kTRUE;
2098 pdg4[0]=211; pdg4[1]=211; pdg4[2]=211; pdg4[3]=321;
2099 mPDG=TDatabasePDG::Instance()->GetParticle(421)->Mass();
2100 minv = fMassCalc4->InvMass(nprongs,pdg4);
2101 if(TMath::Abs(minv-mPDG)<fCutsD0toKpipipi->GetMassCut()) retval=kTRUE;
2104 printf("SelectInvMassAndPt(): wrong decay selection\n");
2110 //-----------------------------------------------------------------------------
2111 void AliAnalysisVertexingHF::SelectTracksAndCopyVertex(const AliVEvent *event,
2113 TObjArray &seleTrksArray,Int_t &nSeleTrks,
2114 UChar_t *seleFlags,Int_t *evtNumber)
2116 // Apply single-track preselection.
2117 // Fill a TObjArray with selected tracks (for displaced vertices or
2118 // soft pion from D*). Selection flag stored in seleFlags.
2119 // Create the AliESDVertex object (convert from AliAODVertex if necessary)
2120 // In case of AOD input, also fill fAODMap for track index<->ID
2122 const AliVVertex *vprimary = event->GetPrimaryVertex();
2124 if(fV1) { delete fV1; fV1=NULL; }
2125 if(fAODMap) { delete fAODMap; fAODMap=NULL; }
2128 UShort_t *indices = 0;
2129 Double_t pos[3],cov[6];
2131 if(!fInputAOD) { // ESD
2132 fV1 = new AliESDVertex(*((AliESDVertex*)vprimary));
2134 vprimary->GetXYZ(pos);
2135 vprimary->GetCovarianceMatrix(cov);
2136 fV1 = new AliESDVertex(pos,cov,100.,100,vprimary->GetName());
2137 indices = new UShort_t[event->GetNumberOfTracks()];
2138 fAODMapSize = 100000;
2139 fAODMap = new Int_t[fAODMapSize];
2143 Int_t entries = (Int_t)event->GetNumberOfTracks();
2144 Bool_t okDisplaced=kFALSE,okSoftPi=kFALSE;
2147 // transfer ITS tracks from event to arrays
2148 for(Int_t i=0; i<entries; i++) {
2150 track = (AliVTrack*)event->GetTrack(i);
2152 // skip pure ITS SA tracks
2153 if(track->GetStatus()&AliESDtrack::kITSpureSA) continue;
2155 // skip tracks without ITS
2156 if(!(track->GetStatus()&AliESDtrack::kITSin)) continue;
2158 // TEMPORARY: check that the cov matrix is there
2159 Double_t covtest[21];
2160 if(!track->GetCovarianceXYZPxPyPz(covtest)) continue;
2164 AliAODTrack *aodt = (AliAODTrack*)track;
2165 if(aodt->GetUsedForPrimVtxFit()) {
2166 indices[nindices]=aodt->GetID(); nindices++;
2168 fAODMap[(Int_t)aodt->GetID()] = i;
2171 AliESDtrack *esdt = 0;
2174 esdt = (AliESDtrack*)track;
2176 esdt = new AliESDtrack(track);
2179 // single track selection
2180 okDisplaced=kFALSE; okSoftPi=kFALSE;
2181 if(fMixEvent && i<trkEntries){
2182 evtNumber[i]=((AliMixedEvent*)event)->EventIndex(i);
2183 const AliVVertex* eventVtx=((AliMixedEvent*)event)->GetEventVertex(i);
2184 Double_t vtxPos[3],primPos[3],primCov[6],trasl[3];
2185 eventVtx->GetXYZ(vtxPos);
2186 vprimary->GetXYZ(primPos);
2187 eventVtx->GetCovarianceMatrix(primCov);
2188 for(Int_t ind=0;ind<3;ind++){
2189 trasl[ind]=vtxPos[ind]-primPos[ind];
2192 Bool_t isTransl=esdt->Translate(trasl,primCov);
2200 if(SingleTrkCuts(esdt,okDisplaced,okSoftPi) && nSeleTrks<trkEntries) {
2201 seleTrksArray.AddLast(esdt);
2202 seleFlags[nSeleTrks]=0;
2203 if(okDisplaced) SETBIT(seleFlags[nSeleTrks],kBitDispl);
2204 if(okSoftPi) SETBIT(seleFlags[nSeleTrks],kBitSoftPi);
2207 if(fInputAOD) delete esdt;
2212 } // end loop on tracks
2214 // primary vertex from AOD
2216 delete fV1; fV1=NULL;
2217 vprimary->GetXYZ(pos);
2218 vprimary->GetCovarianceMatrix(cov);
2219 Double_t chi2toNDF = vprimary->GetChi2perNDF();
2220 Int_t ncontr=nindices;
2221 if(!strcmp(vprimary->GetTitle(),"VertexerTracksWithContraint")) ncontr += 1;
2222 Double_t chi2=chi2toNDF*(2.*(Double_t)ncontr-3.);
2223 fV1 = new AliESDVertex(pos,cov,chi2,ncontr,vprimary->GetName());
2224 fV1->SetTitle(vprimary->GetTitle());
2225 fV1->SetIndices(nindices,indices);
2227 if(indices) { delete [] indices; indices=NULL; }
2232 //-----------------------------------------------------------------------------
2233 void AliAnalysisVertexingHF::SetSelectionBitForPID(AliRDHFCuts *cuts,AliAODRecoDecayHF *rd,Int_t bit) {
2235 // Set the selection bit for PID
2237 if(cuts->GetPidHF()) {
2238 Bool_t usepid=cuts->GetIsUsePID();
2239 cuts->SetUsePID(kTRUE);
2240 if(cuts->IsSelectedPID(rd))
2241 rd->SetSelectionBit(bit);
2242 cuts->SetUsePID(usepid);
2246 //-----------------------------------------------------------------------------
2247 Bool_t AliAnalysisVertexingHF::SingleTrkCuts(AliESDtrack *trk,
2248 Bool_t &okDisplaced,Bool_t &okSoftPi) const
2250 // Check if track passes some kinematical cuts
2252 // this is needed to store the impact parameters
2253 trk->RelateToVertex(fV1,fBzkG,kVeryBig);
2257 // Track selection, displaced tracks
2260 selectInfo = fTrackFilter->IsSelected(trk);
2262 if(selectInfo) okDisplaced=kTRUE;
2264 // Track selection, soft pions
2266 if(fDstar && fTrackFilterSoftPi) {
2267 selectInfo = fTrackFilterSoftPi->IsSelected(trk);
2269 if(selectInfo) okSoftPi=kTRUE;
2271 if(okDisplaced || okSoftPi) return kTRUE;
2277 //-----------------------------------------------------------------------------
2278 AliAODv0* AliAnalysisVertexingHF::TransformESDv0toAODv0(AliESDv0 *esdV0, TObjArray *twoTrackArrayV0){
2280 // Transform ESDv0 to AODv0
2282 // this function takes the ESDv0 vertex, computes the DCA variables from the ESDv0
2283 // and creates an AODv0 out of them
2285 Double_t vertex[3]; esdV0->GetXYZ(vertex[0],vertex[1],vertex[2]);
2286 AliAODVertex *vertexV0 = new AliAODVertex(vertex,esdV0->GetChi2V0(),AliAODVertex::kV0,2);
2288 // create the v0 neutral track to compute the DCA to the primary vertex
2289 Double_t xyz[3], pxpypz[3];
2291 esdV0->PxPyPz(pxpypz);
2292 Double_t cv[21]; for(int i=0; i<21; i++) cv[i]=0;
2293 AliNeutralTrackParam *trackesdV0 = new AliNeutralTrackParam(xyz,pxpypz,cv,0);
2298 Double_t d0z0[2],covd0z0[3];
2299 AliAODVertex *primVertexAOD = PrimaryVertex();
2300 trackesdV0->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
2301 Double_t dcaV0ToPrimVertex = TMath::Sqrt(covd0z0[0]);
2302 // get the v0 daughters to compute their DCA to the v0 vertex and get their momentum
2303 Double_t dcaV0DaughterToPrimVertex[2];
2304 AliExternalTrackParam *posV0track = (AliExternalTrackParam*)twoTrackArrayV0->UncheckedAt(0);
2305 AliExternalTrackParam *negV0track = (AliExternalTrackParam*)twoTrackArrayV0->UncheckedAt(1);
2306 if( !posV0track || !negV0track) {
2307 if(trackesdV0) {delete trackesdV0; trackesdV0=NULL;}
2309 delete primVertexAOD;
2312 posV0track->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
2313 // if ( covd0z0[0]<=0.) dcaV0DaughterToPrimVertex[0] = 0;
2315 dcaV0DaughterToPrimVertex[0] = TMath::Sqrt(covd0z0[0]);
2316 negV0track->PropagateToDCA(primVertexAOD,fBzkG,kVeryBig,d0z0,covd0z0);
2317 // if ( covd0z0[0]<=0.)dcaV0DaughterToPrimVertex[1] = 0;
2319 dcaV0DaughterToPrimVertex[1] = TMath::Sqrt(covd0z0[0]);
2320 Double_t dcaV0Daughters = esdV0->GetDcaV0Daughters();
2321 Double_t pmom[3],nmom[3];
2322 esdV0->GetNPxPyPz(nmom[0],nmom[1],nmom[2]);
2323 esdV0->GetPPxPyPz(pmom[0],pmom[1],pmom[2]);
2325 AliAODv0 *aodV0 = new AliAODv0(vertexV0,dcaV0Daughters,dcaV0ToPrimVertex,pmom,nmom,dcaV0DaughterToPrimVertex);
2326 aodV0->SetOnFlyStatus(esdV0->GetOnFlyStatus());
2329 delete primVertexAOD;
2333 //-----------------------------------------------------------------------------