1 #if !defined(__CINT__) || defined(__MAKECINT__)
10 #include "AliAODEvent.h"
11 #include "AliAODHeader.h"
12 #include "AliAODVertex.h"
13 #include "AliAODTrack.h"
14 #include "AliAODCaloCluster.h"
15 #include "AliAODPmdCluster.h"
16 #include "AliAODTracklets.h"
18 #include "AliESDEvent.h"
19 #include "AliESDtrack.h"
20 #include "AliESDMuonTrack.h"
21 #include "AliESDVertex.h"
23 #include "AliESDkink.h"
24 #include "AliESDcascade.h"
25 #include "AliESDCaloCluster.h"
26 #include "AliESDPmdTrack.h"
27 #include "AliMultiplicity.h"
31 void CreateAODfromESD(const char *inFileName = "AliESDs.root",
32 const char *outFileName = "AliAOD.root") {
35 TFile *inFile = TFile::Open(inFileName, "READ");
37 // create an AliAOD object
38 AliAODEvent *aod = new AliAODEvent();
39 aod->CreateStdContent();
42 TFile *outFile = TFile::Open(outFileName, "RECREATE");
46 TTree *aodTree = new TTree("aodTree", "AliAOD tree");
47 aodTree->Branch(aod->GetList());
50 TTree *t = (TTree*) inFile->Get("esdTree");
51 AliESDEvent *esd = new AliESDEvent();
54 Int_t nEvents = t->GetEntries();
56 // set arrays and pointers
66 // loop over events and fill them
67 for (Int_t iEvent = 0; iEvent < nEvents; ++iEvent) {
68 //cout << "event: " << iEvent << endl;
71 // Multiplicity information needed by the header (to be revised!)
72 Int_t nTracks = esd->GetNumberOfTracks();
74 for (Int_t iTrack=0; iTrack<nTracks; ++iTrack)
75 if (esd->GetTrack(iTrack)->Charge()> 0) nPosTracks++;
78 AliAODHeader *header = aod->GetHeader();
81 header->SetRunNumber (esd->GetRunNumber() );
82 header->SetBunchCrossNumber(esd->GetBunchCrossNumber());
83 header->SetOrbitNumber (esd->GetOrbitNumber() );
84 header->SetPeriodNumber (esd->GetPeriodNumber() );
85 header->SetTriggerMask (esd->GetTriggerMask() );
86 header->SetTriggerCluster (esd->GetTriggerCluster() );
87 header->SetEventType (esd->GetEventType() );
88 header->SetMagneticField (esd->GetMagneticField() );
89 header->SetZDCN1Energy (esd->GetZDCN1Energy() );
90 header->SetZDCP1Energy (esd->GetZDCP1Energy() );
91 header->SetZDCN2Energy (esd->GetZDCN2Energy() );
92 header->SetZDCP2Energy (esd->GetZDCP2Energy() );
93 header->SetZDCEMEnergy (esd->GetZDCEMEnergy() );
94 header->SetRefMultiplicity (nTracks);
95 header->SetRefMultiplicityPos(nPosTracks);
96 header->SetRefMultiplicityNeg(nTracks - nPosTracks);
97 header->SetMuonMagFieldScale(-999.); // FIXME
98 header->SetCentrality(-999.); // FIXME
100 Int_t nV0s = esd->GetNumberOfV0s();
101 Int_t nCascades = esd->GetNumberOfCascades();
102 Int_t nKinks = esd->GetNumberOfKinks();
103 Int_t nVertices = nV0s + nCascades + nKinks + 1 /* = prim. vtx*/;
105 Int_t nCaloClus = esd->GetNumberOfCaloClusters();
107 Int_t nPmdClus = esd->GetNumberOfPmdTracks();
109 aod->ResetStd(nTracks, nVertices, nV0s+nCascades, nJets, nCaloClus, nFmdClus, nPmdClus);
111 // Array to take into account the tracks already added to the AOD
112 Bool_t * usedTrack = NULL;
114 usedTrack = new Bool_t[nTracks];
115 for (Int_t iTrack=0; iTrack<nTracks; ++iTrack) usedTrack[iTrack]=kFALSE;
117 // Array to take into account the V0s already added to the AOD
118 Bool_t * usedV0 = NULL;
120 usedV0 = new Bool_t[nV0s];
121 for (Int_t iV0=0; iV0<nV0s; ++iV0) usedV0[iV0]=kFALSE;
123 // Array to take into account the kinks already added to the AOD
124 Bool_t * usedKink = NULL;
126 usedKink = new Bool_t[nKinks];
127 for (Int_t iKink=0; iKink<nKinks; ++iKink) usedKink[iKink]=kFALSE;
130 // Access to the AOD container of vertices
131 TClonesArray &vertices = *(aod->GetVertices());
134 // Access to the AOD container of tracks
135 TClonesArray &tracks = *(aod->GetTracks());
138 // Access to the AOD container of V0s
139 TClonesArray &V0s = *(aod->GetV0s());
142 // Add primary vertex. The primary tracks will be defined
143 // after the loops on the composite objects (V0, cascades, kinks)
144 const AliESDVertex *vtx = esd->GetPrimaryVertex();
146 vtx->GetXYZ(pos); // position
147 vtx->GetCovMatrix(covVtx); //covariance matrix
149 AliAODVertex * primary = new(vertices[jVertices++])
150 AliAODVertex(pos, covVtx, vtx->GetChi2toNDF(), NULL, -1, AliAODVertex::kPrimary);
153 AliAODTrack *aodTrack = 0x0;
155 // Create vertices starting from the most complex objects
158 for (Int_t nCascade = 0; nCascade < nCascades; ++nCascade) {
159 AliESDcascade *cascade = esd->GetCascade(nCascade);
161 cascade->GetXYZ(pos[0], pos[1], pos[2]);
162 cascade->GetPosCovXi(covVtx);
164 // Add the cascade vertex
165 AliAODVertex * vcascade = new(vertices[jVertices++]) AliAODVertex(pos,
167 cascade->GetChi2Xi(), // = chi2/NDF since NDF = 2*2-3
170 AliAODVertex::kCascade);
172 primary->AddDaughter(vcascade); // the cascade 'particle' (represented by a vertex) is added as a daughter to the primary vertex
174 // Add the V0 from the cascade. The ESD class have to be optimized...
175 // Now we have to search for the corresponding V0 in the list of V0s
176 // using the indeces of the positive and negative tracks
178 Int_t posFromV0 = cascade->GetPindex();
179 Int_t negFromV0 = cascade->GetNindex();
185 for (Int_t iV0=0; iV0<nV0s; ++iV0) {
187 v0 = esd->GetV0(iV0);
188 Int_t posV0 = v0->GetPindex();
189 Int_t negV0 = v0->GetNindex();
191 if (posV0==posFromV0 && negV0==negFromV0) {
197 AliAODVertex * vV0FromCascade = 0x0;
199 if (indV0>-1 && !usedV0[indV0]) {
201 // the V0 exists in the array of V0s and is not used
203 usedV0[indV0] = kTRUE;
205 v0->GetXYZ(pos[0], pos[1], pos[2]);
206 v0->GetPosCov(covVtx);
208 vV0FromCascade = new(vertices[jVertices++]) AliAODVertex(pos,
210 v0->GetChi2V0(), // = chi2/NDF since NDF = 2*2-3
216 // the V0 doesn't exist in the array of V0s or was used
217 cerr << "Error: event " << iEvent << " cascade " << nCascade
218 << " The V0 " << indV0
219 << " doesn't exist in the array of V0s or was used!" << endl;
221 cascade->GetXYZ(pos[0], pos[1], pos[2]);
222 cascade->GetPosCov(covVtx);
224 vV0FromCascade = new(vertices[jVertices++]) AliAODVertex(pos,
226 v0->GetChi2V0(), // = chi2/NDF since NDF = 2*2-3
230 vcascade->AddDaughter(vV0FromCascade);
234 // Add the positive tracks from the V0
236 if (! usedTrack[posFromV0]) {
238 usedTrack[posFromV0] = kTRUE;
240 AliESDtrack *esdTrack = esd->GetTrack(posFromV0);
241 esdTrack->GetPxPyPz(p_pos);
242 esdTrack->GetXYZ(pos);
243 esdTrack->GetCovarianceXYZPxPyPz(covTr);
244 esdTrack->GetESDpid(pid);
246 vV0FromCascade->AddDaughter(aodTrack =
247 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
248 esdTrack->GetLabel(),
254 (Short_t)esdTrack->Charge(),
255 esdTrack->GetITSClusterMap(),
258 kTRUE, // check if this is right
259 kFALSE, // check if this is right
260 AliAODTrack::kSecondary)
262 aodTrack->ConvertAliPIDtoAODPID();
265 cerr << "Error: event " << iEvent << " cascade " << nCascade
266 << " track " << posFromV0 << " has already been used!" << endl;
269 // Add the negative tracks from the V0
271 if (!usedTrack[negFromV0]) {
273 usedTrack[negFromV0] = kTRUE;
275 AliESDtrack *esdTrack = esd->GetTrack(negFromV0);
276 esdTrack->GetPxPyPz(p_neg);
277 esdTrack->GetXYZ(pos);
278 esdTrack->GetCovarianceXYZPxPyPz(covTr);
279 esdTrack->GetESDpid(pid);
281 vV0FromCascade->AddDaughter(aodTrack =
282 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
283 esdTrack->GetLabel(),
289 (Short_t)esdTrack->Charge(),
290 esdTrack->GetITSClusterMap(),
293 kTRUE, // check if this is right
294 kFALSE, // check if this is right
295 AliAODTrack::kSecondary)
297 aodTrack->ConvertAliPIDtoAODPID();
300 cerr << "Error: event " << iEvent << " cascade " << nCascade
301 << " track " << negFromV0 << " has already been used!" << endl;
304 // add it to the V0 array as well
305 Double_t d0[2] = { -999., -99.};
306 // counting is probably wrong
307 new(V0s[jV0s++]) AliAODv0(vV0FromCascade, -999., -99., p_pos, p_neg, d0); // to be refined
309 // Add the bachelor track from the cascade
311 Int_t bachelor = cascade->GetBindex();
313 if(!usedTrack[bachelor]) {
315 usedTrack[bachelor] = kTRUE;
317 AliESDtrack *esdTrack = esd->GetTrack(bachelor);
318 esdTrack->GetPxPyPz(p);
319 esdTrack->GetXYZ(pos);
320 esdTrack->GetCovarianceXYZPxPyPz(covTr);
321 esdTrack->GetESDpid(pid);
323 vcascade->AddDaughter(aodTrack =
324 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
325 esdTrack->GetLabel(),
331 (Short_t)esdTrack->Charge(),
332 esdTrack->GetITSClusterMap(),
335 kTRUE, // check if this is right
336 kFALSE, // check if this is right
337 AliAODTrack::kSecondary)
339 aodTrack->ConvertAliPIDtoAODPID();
342 cerr << "Error: event " << iEvent << " cascade " << nCascade
343 << " track " << bachelor << " has already been used!" << endl;
346 // Add the primary track of the cascade (if any)
348 } // end of the loop on cascades
352 for (Int_t nV0 = 0; nV0 < nV0s; ++nV0) {
354 if (usedV0[nV0]) continue; // skip if aready added to the AOD
356 AliESDv0 *v0 = esd->GetV0(nV0);
358 v0->GetXYZ(pos[0], pos[1], pos[2]);
359 v0->GetPosCov(covVtx);
362 new(vertices[jVertices++]) AliAODVertex(pos,
364 v0->GetChi2V0(), // = chi2/NDF since NDF = 2*2-3
368 primary->AddDaughter(vV0);
370 Int_t posFromV0 = v0->GetPindex();
371 Int_t negFromV0 = v0->GetNindex();
373 // Add the positive tracks from the V0
375 if (!usedTrack[posFromV0]) {
377 usedTrack[posFromV0] = kTRUE;
379 AliESDtrack *esdTrack = esd->GetTrack(posFromV0);
380 esdTrack->GetPxPyPz(p_pos);
381 esdTrack->GetXYZ(pos);
382 esdTrack->GetCovarianceXYZPxPyPz(covTr);
383 esdTrack->GetESDpid(pid);
385 vV0->AddDaughter(aodTrack =
386 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
387 esdTrack->GetLabel(),
393 (Short_t)esdTrack->Charge(),
394 esdTrack->GetITSClusterMap(),
397 kTRUE, // check if this is right
398 kFALSE, // check if this is right
399 AliAODTrack::kSecondary)
401 aodTrack->ConvertAliPIDtoAODPID();
404 cerr << "Error: event " << iEvent << " V0 " << nV0
405 << " track " << posFromV0 << " has already been used!" << endl;
408 // Add the negative tracks from the V0
410 if (!usedTrack[negFromV0]) {
412 usedTrack[negFromV0] = kTRUE;
414 AliESDtrack *esdTrack = esd->GetTrack(negFromV0);
415 esdTrack->GetPxPyPz(p_neg);
416 esdTrack->GetXYZ(pos);
417 esdTrack->GetCovarianceXYZPxPyPz(covTr);
418 esdTrack->GetESDpid(pid);
420 vV0->AddDaughter(aodTrack =
421 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
422 esdTrack->GetLabel(),
428 (Short_t)esdTrack->Charge(),
429 esdTrack->GetITSClusterMap(),
432 kTRUE, // check if this is right
433 kFALSE, // check if this is right
434 AliAODTrack::kSecondary)
436 aodTrack->ConvertAliPIDtoAODPID();
439 cerr << "Error: event " << iEvent << " V0 " << nV0
440 << " track " << negFromV0 << " has already been used!" << endl;
443 // add it to the V0 array as well
444 Double_t d0[2] = { 999., 99.};
445 new(V0s[jV0s++]) AliAODv0(vV0, 999., 99., p_pos, p_neg, d0); // to be refined
446 } // end of the loop on V0s
448 // Kinks: it is a big mess the access to the information in the kinks
449 // The loop is on the tracks in order to find the mother and daugther of each kink
452 for (Int_t iTrack=0; iTrack<nTracks; ++iTrack) {
455 AliESDtrack * esdTrack = esd->GetTrack(iTrack);
457 Int_t ikink = esdTrack->GetKinkIndex(0);
460 // Negative kink index: mother, positive: daughter
462 // Search for the second track of the kink
464 for (Int_t jTrack = iTrack+1; jTrack<nTracks; ++jTrack) {
466 AliESDtrack * esdTrack1 = esd->GetTrack(jTrack);
468 Int_t jkink = esdTrack1->GetKinkIndex(0);
470 if ( TMath::Abs(ikink)==TMath::Abs(jkink) ) {
472 // The two tracks are from the same kink
474 if (usedKink[TMath::Abs(ikink)-1]) continue; // skip used kinks
477 Int_t idaughter = -1;
479 if (ikink<0 && jkink>0) {
484 else if (ikink>0 && jkink<0) {
490 cerr << "Error: Wrong combination of kink indexes: "
491 << ikink << " " << jkink << endl;
495 // Add the mother track
497 AliAODTrack * mother = NULL;
499 if (!usedTrack[imother]) {
501 usedTrack[imother] = kTRUE;
503 AliESDtrack *esdTrack = esd->GetTrack(imother);
504 esdTrack->GetPxPyPz(p);
505 esdTrack->GetXYZ(pos);
506 esdTrack->GetCovarianceXYZPxPyPz(covTr);
507 esdTrack->GetESDpid(pid);
510 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
511 esdTrack->GetLabel(),
517 (Short_t)esdTrack->Charge(),
518 esdTrack->GetITSClusterMap(),
521 kTRUE, // check if this is right
522 kTRUE, // check if this is right
523 AliAODTrack::kPrimary);
524 primary->AddDaughter(mother);
525 mother->ConvertAliPIDtoAODPID();
528 cerr << "Error: event " << iEvent << " kink " << TMath::Abs(ikink)-1
529 << " track " << imother << " has already been used!" << endl;
532 // Add the kink vertex
533 AliESDkink * kink = esd->GetKink(TMath::Abs(ikink)-1);
535 AliAODVertex * vkink =
536 new(vertices[jVertices++]) AliAODVertex(kink->GetPosition(),
540 esdTrack->GetID(), // This is the track ID of the mother's track!
541 AliAODVertex::kKink);
542 // Add the daughter track
544 AliAODTrack * daughter = NULL;
546 if (!usedTrack[idaughter]) {
548 usedTrack[idaughter] = kTRUE;
550 AliESDtrack *esdTrack = esd->GetTrack(idaughter);
551 esdTrack->GetPxPyPz(p);
552 esdTrack->GetXYZ(pos);
553 esdTrack->GetCovarianceXYZPxPyPz(covTr);
554 esdTrack->GetESDpid(pid);
557 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
558 esdTrack->GetLabel(),
564 (Short_t)esdTrack->Charge(),
565 esdTrack->GetITSClusterMap(),
568 kTRUE, // check if this is right
569 kTRUE, // check if this is right
570 AliAODTrack::kPrimary);
571 vkink->AddDaughter(daughter);
572 daughter->ConvertAliPIDtoAODPID();
575 cerr << "Error: event " << iEvent << " kink " << TMath::Abs(ikink)-1
576 << " track " << idaughter << " has already been used!" << endl;
583 // Tracks (primary and orphan)
584 for (Int_t nTrack = 0; nTrack < nTracks; ++nTrack) {
586 if (usedTrack[nTrack]) continue;
588 AliESDtrack *esdTrack = esd->GetTrack(nTrack);
589 esdTrack->GetPxPyPz(p);
590 esdTrack->GetXYZ(pos);
591 esdTrack->GetCovarianceXYZPxPyPz(covTr);
592 esdTrack->GetESDpid(pid);
594 Float_t impactXY, impactZ;
596 esdTrack->GetImpactParameters(impactXY,impactZ);
599 // track inside the beam pipe
601 primary->AddDaughter(aodTrack =
602 new(tracks[jTracks++]) AliAODTrack(esdTrack->GetID(),
603 esdTrack->GetLabel(),
609 (Short_t)esdTrack->Charge(),
610 esdTrack->GetITSClusterMap(),
613 kTRUE, // check if this is right
614 kTRUE, // check if this is right
615 AliAODTrack::kPrimary)
617 aodTrack->ConvertAliPIDtoAODPID();
620 // outside the beam pipe: orphan track
621 // Don't write them anymore!
624 } // end of loop on tracks
627 Int_t nMuTracks = esd->GetNumberOfMuonTracks();
628 for (Int_t nMuTrack = 0; nMuTrack < nMuTracks; ++nMuTrack) {
630 AliESDMuonTrack *esdMuTrack = esd->GetMuonTrack(nMuTrack);
631 p[0] = esdMuTrack->Px();
632 p[1] = esdMuTrack->Py();
633 p[2] = esdMuTrack->Pz();
634 pos[0] = primary->GetX();
635 pos[1] = primary->GetY();
636 pos[2] = primary->GetZ();
638 // has to be changed once the muon pid is provided by the ESD
639 for (Int_t i = 0; i < 10; pid[i++] = 0.); pid[AliAODTrack::kMuon]=1.;
641 primary->AddDaughter(aodTrack =
642 new(tracks[jTracks++]) AliAODTrack(0, // no ID provided
643 0, // no label provided
648 NULL, // no covariance matrix provided
649 esdMuTrack->Charge(),
650 0, // ITSClusterMap is set below
653 kFALSE, // muon tracks are not used to fit the primary vtx
654 kFALSE, // not used for vertex fit
655 AliAODTrack::kPrimary)
658 aodTrack->SetHitsPatternInTrigCh(esdMuTrack->GetHitsPatternInTrigCh());
659 Int_t track2Trigger = esdMuTrack->GetMatchTrigger();
660 aodTrack->SetMatchTrigger(track2Trigger);
662 aodTrack->SetChi2MatchTrigger(esdMuTrack->GetChi2MatchTrigger());
664 aodTrack->SetChi2MatchTrigger(0.);
667 // Access to the AOD container of PMD clusters
668 TClonesArray &pmdClusters = *(aod->GetPmdClusters());
669 Int_t jPmdClusters=0;
671 for (Int_t iPmd = 0; iPmd < nPmdClus; ++iPmd) {
672 // file pmd clusters, to be revised!
673 AliESDPmdTrack *pmdTrack = esd->GetPmdTrack(iPmd);
676 Double_t pos[3] = { pmdTrack->GetClusterX(), pmdTrack->GetClusterY(), pmdTrack->GetClusterZ() };
677 Double_t pid[9] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. }; // to be revised!
679 // assoc cluster not set
680 new(pmdClusters[jPmdClusters++]) AliAODPmdCluster(iPmd, nLabel, label, pmdTrack->GetClusterADC(), pos, pid);
683 // Access to the AOD container of clusters
684 TClonesArray &caloClusters = *(aod->GetCaloClusters());
688 TArrayS EMCCellNumber(15000);
689 TArrayD EMCCellAmplitude(15000);
691 const Float_t fEMCAmpScale = 1./500;
693 for (Int_t iClust=0; iClust<nCaloClus; ++iClust) {
695 AliESDCaloCluster * cluster = esd->GetCaloCluster(iClust);
697 Int_t id = cluster->GetID();
700 Float_t energy = cluster->E();
701 cluster->GetPosition(posF);
702 Char_t ttype=AliAODCluster::kUndef;
704 if (cluster->GetClusterType() == AliESDCaloCluster::kPHOSCluster) {
705 ttype=AliAODCluster::kPHOSNeutral;
707 else if (cluster->GetClusterType() == AliESDCaloCluster::kEMCALClusterv1) {
708 ttype = AliAODCluster::kEMCALClusterv1;
710 else if (cluster->GetClusterType() == AliESDCaloCluster::kEMCALPseudoCluster) {
711 // Collect raw tower info
712 for (Int_t iDig = 0; iDig < cluster->GetNumberOfDigits(); iDig++) {
713 EMCCellNumber[nEMCCells] = cluster->GetDigitIndex()->At(iDig);
714 EMCCellAmplitude[nEMCCells] = fEMCAmpScale*cluster->GetDigitAmplitude()->At(iDig);
717 // don't write cluster data (it's just a pseudo cluster, holding the tower information)
721 AliAODCaloCluster *caloCluster = new(caloClusters[jClusters++]) AliAODCaloCluster(id,
729 caloCluster->SetCaloCluster(); // to be refined!
731 } // end of loop on calo clusters
733 // fill EMC cell info
734 AliAODCaloCells &EMCCells = *(aod->GetCaloCells());
735 EMCCells.CreateContainer(nEMCCells);
736 EMCCells.SetType(AliAODCaloCells::kEMCAL);
737 for (Int_t iCell = 0; iCell < nEMCCells; iCell++) {
738 EMCCells.SetCell(iCell,EMCCellNumber[iCell],EMCCellAmplitude[iCell]);
743 AliAODTracklets &SPDTracklets = *(aod->GetTracklets());
744 const AliMultiplicity *mult = esd->GetMultiplicity();
746 if (mult->GetNumberOfTracklets()>0) {
747 SPDTracklets.CreateContainer(mult->GetNumberOfTracklets());
749 for (Int_t n=0; n<mult->GetNumberOfTracklets(); n++) {
750 SPDTracklets.SetTracklet(n, mult->GetTheta(n), mult->GetPhi(n), mult->GetDeltaPhi(n), mult->GetLabel(n));
754 Printf("ERROR: AliMultiplicity could not be retrieved from ESD");
761 // fill the tree for this event
763 } // end of event loop
765 aodTree->GetUserInfo()->Add(aod);
770 // write the tree to the specified file
771 outFile = aodTree->GetCurrentFile();