1 /**************************************************************************
2 * Copyright(c) 1998-2013, 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 **************************************************************************/
19 /// Implementation of an AliAODBranchReplicator to produce slim muon and dimuon aods.
21 /// This replicator is in charge of replicating the tracks,vertices,dimuons
22 /// (vzero, tzero, zdc, and, optionally, the SPD tracklets) branches
23 /// of the standard AOD into muon AODs (AliAOD.Muons.root and AliAOD.Dimuons.root)
25 /// The tracks are filtered so that only muon tracks (and only muon tracks
26 /// that pass the trackCut if present) make it to the output aods
28 /// The vertices are filtered so that only the primary (and pileup) vertices make it
29 /// to the output aods.
31 /// The dimuons are recreated here, according to the set of tracks
32 /// that pass the trackCut (that set may be the same as the input set,
33 /// but to be 100% safe, we always recreate the dimuons).
35 /// \author L. Aphecetche (Subatech)
37 #include "AliAODMuonReplicator.h"
39 #include "AliAODDimuon.h"
40 #include "AliAODEvent.h"
41 #include "AliAODMCHeader.h"
42 #include "AliAODMCParticle.h"
43 #include "AliAODTZERO.h"
44 #include "AliAODTrack.h"
45 #include "AliAODVZERO.h"
46 #include "AliAnalysisCuts.h"
50 ClassImp(AliAODMuonReplicator)
53 //_____________________________________________________________________________
54 AliAODMuonReplicator::AliAODMuonReplicator(const char* name, const char* title,
55 AliAnalysisCuts* trackCut,
56 AliAnalysisCuts* vertexCut,
58 Bool_t replicateHeader,
59 Bool_t replicateTracklets)
60 :AliAODBranchReplicator(name,title),
61 fTrackCut(trackCut), fTracks(0x0),
62 fVertexCut(vertexCut), fVertices(0x0),
75 fReplicateHeader(replicateHeader),
76 fReplicateTracklets(replicateTracklets)
80 /// \param trackCut if present will filter out tracks
81 /// \param vertexCut if present will filter out vertices
82 /// \param mcMode what to do with MC information (0: skip it, 1: copy all,
83 /// 2: copy only for events with at least one muon )
84 /// \param replicateHeader whether or not to handle the replication of the
86 /// \param replicateTracklets whether or not to include the SPD tracklets branch
90 //_____________________________________________________________________________
91 AliAODMuonReplicator::~AliAODMuonReplicator()
99 //_____________________________________________________________________________
100 void AliAODMuonReplicator::SelectParticle(Int_t i)
102 /// taking the absolute values here, need to take care
103 /// of negative daughter and mother
104 /// IDs when setting!
106 if (!IsParticleSelected(TMath::Abs(i)))
108 fParticleSelected.Add(TMath::Abs(i),1);
112 //_____________________________________________________________________________
113 Bool_t AliAODMuonReplicator::IsParticleSelected(Int_t i)
115 /// taking the absolute values here, need to take
116 /// care with negative daughter and mother
117 /// IDs when setting!
118 return (fParticleSelected.GetValue(TMath::Abs(i))==1);
122 //_____________________________________________________________________________
123 void AliAODMuonReplicator::CreateLabelMap(const AliAODEvent& source)
126 // this should be called once all selections are done
131 TClonesArray* mcParticles = static_cast<TClonesArray*>(source.FindListObject(AliAODMCParticle::StdBranchName()));
136 TIter next(mcParticles);
140 if (IsParticleSelected(i))
142 fLabelMap.Add(i,j++);
148 //_____________________________________________________________________________
149 Int_t AliAODMuonReplicator::GetNewLabel(Int_t i)
151 /// Gets the label from the new created Map
152 /// Call CreatLabelMap before
153 /// otherwise only 0 returned
154 return fLabelMap.GetValue(TMath::Abs(i));
157 //_____________________________________________________________________________
158 void AliAODMuonReplicator::FilterMC(const AliAODEvent& source)
160 /// Filter MC information
163 fMCParticles->Clear("C");
165 AliAODMCHeader* mcHeader(0x0);
166 TClonesArray* mcParticles(0x0);
168 fParticleSelected.Delete();
170 if ( fMCMode>=2 && !fTracks->GetEntries() ) return;
171 // for fMCMode>=2 we only copy MC information for events where there's at least one muon track
173 mcHeader = static_cast<AliAODMCHeader*>(source.FindListObject(AliAODMCHeader::StdBranchName()));
177 *fMCHeader = *mcHeader;
180 mcParticles = static_cast<TClonesArray*>(source.FindListObject(AliAODMCParticle::StdBranchName()));
182 if ( mcParticles && fMCMode>=2 )
184 // loop on (kept) muon tracks to find their ancestors
185 TIter nextMT(fTracks);
188 while ( ( mt = static_cast<AliAODTrack*>(nextMT()) ) )
190 Int_t label = mt->GetLabel();
194 SelectParticle(label);
195 AliAODMCParticle* mother = static_cast<AliAODMCParticle*>(mcParticles->UncheckedAt(label));
198 AliError("Got a null mother ! Check that !");
203 label = mother->GetMother();
208 CreateLabelMap(source);
210 // Actual filtering and label remapping (shamelessly taken for the implementation of AliAODHandler::StoreMCParticles)
211 TIter nextMC(mcParticles);
216 while ( ( p = static_cast<AliAODMCParticle*>(nextMC()) ) )
218 AliAODMCParticle c(*p);
220 if ( IsParticleSelected(nmc) )
223 Int_t d0 = p->GetDaughter(0);
224 Int_t d1 = p->GetDaughter(1);
225 Int_t m = p->GetMother();
227 // other than for the track labels, negative values mean
228 // no daughter/mother so preserve it
232 // no first daughter -> no second daughter
233 // nothing to be done
234 // second condition not needed just for sanity check at the end
237 } else if(d1 < 0 && d0 >= 0)
240 // second condition not needed just for sanity check at the end
241 if(IsParticleSelected(d0))
243 c.SetDaughter(0,GetNewLabel(d0));
250 else if (d0 > 0 && d1 > 0 )
252 // we have two or more daughters loop on the stack to see if they are
256 for (int id = d0; id<=d1;++id)
258 if (IsParticleSelected(id))
263 d0tmp = GetNewLabel(id);
264 d1tmp = d0tmp; // this is to have the same schema as on the stack i.e. with one daugther d0 and d1 are the same
266 else d1tmp = GetNewLabel(id);
269 c.SetDaughter(0,d0tmp);
270 c.SetDaughter(1,d1tmp);
273 AliError(Form("Unxpected indices %d %d",d0,d1));
281 if (IsParticleSelected(m))
283 c.SetMother(GetNewLabel(m));
287 AliError(Form("PROBLEM Mother not selected %d", m));
291 new ((*fMCParticles)[nmcout++]) AliAODMCParticle(c);
297 // now remap the tracks...
299 TIter nextTrack(fTracks);
302 while ( ( t = static_cast<AliAODTrack*>(nextTrack()) ) )
304 t->SetLabel(GetNewLabel(t->GetLabel()));
308 else if ( mcParticles )
310 // simple copy of input MC particles to ouput MC particles
311 TIter nextMC(mcParticles);
315 while ( ( p = static_cast<AliAODMCParticle*>(nextMC()) ) )
317 new ((*fMCParticles)[nmcout++]) AliAODMCParticle(*p);
321 AliDebug(1,Form("input mc %d output mc %d",
322 mcParticles ? mcParticles->GetEntries() : 0,
323 fMCParticles ? fMCParticles->GetEntries() : 0));
327 //_____________________________________________________________________________
328 TList* AliAODMuonReplicator::GetList() const
330 /// return (and build if not already done) our internal list of managed objects
333 if ( fReplicateHeader )
335 fHeader = new AliAODHeader;
338 if ( fReplicateTracklets )
340 fTracklets = new AliAODTracklets;
341 fTracklets->SetName("tracklets");
344 fTracks = new TClonesArray("AliAODTrack",30);
345 fTracks->SetName("tracks");
347 fVertices = new TClonesArray("AliAODVertex",2);
348 fVertices->SetName("vertices");
350 fDimuons = new TClonesArray("AliAODDimuon",20);
351 fDimuons->SetName("dimuons");
353 fVZERO = new AliAODVZERO;
355 fTZERO = new AliAODTZERO;
357 fZDC = new AliAODZDC;
360 fList->SetOwner(kTRUE);
364 fList->Add(fVertices);
365 fList->Add(fTracklets);
366 fList->Add(fDimuons);
373 fMCHeader = new AliAODMCHeader;
374 fMCParticles = new TClonesArray("AliAODMCParticle",1000);
375 fMCParticles->SetName(AliAODMCParticle::StdBranchName());
376 fList->Add(fMCHeader);
377 fList->Add(fMCParticles);
383 //_____________________________________________________________________________
384 void AliAODMuonReplicator::ReplicateAndFilter(const AliAODEvent& source)
386 /// Replicate (and filter if filters are there) the relevant
387 /// parts we're interested in AODEvent
389 assert(fTracks!=0x0);
391 if (fReplicateHeader)
393 *fHeader = *(source.GetHeader());
396 if (fReplicateTracklets)
398 *fTracklets = *(source.GetTracklets());
401 *fVZERO = *(source.GetVZEROData());
403 *fTZERO = *(source.GetTZEROData());
405 *fZDC = *(source.GetZDCData());
408 TIter next(source.GetTracks());
413 while (( t = static_cast<AliAODTrack*>(next()) )) {
415 if (t->IsMuonTrack() || t->IsMuonGlobalTrack()) ++inputMuons; // just a counter: MUON and MUON+MFT tracks before track cuts are applied
417 // MUON and MUON+MFT tracks selected // AU
418 if (!fTrackCut || fTrackCut->IsSelected(t)) {
419 new ((*fTracks)[nMuons++]) AliAODTrack(*t);
424 assert(fVertices!=0x0);
425 fVertices->Clear("C");
426 TIter nextV(source.GetVertices());
430 while ( ( v = static_cast<AliAODVertex*>(nextV()) ) ) {
431 if ( !fVertexCut || fVertexCut->IsSelected(v) ) {
432 AliAODVertex* tmp = v->CloneWithoutRefs();
433 AliAODVertex* copiedVertex = new((*fVertices)[nvertices++]) AliAODVertex(*tmp);
434 // to insure the main vertex retains the ncontributors information
435 // (which is otherwise computed dynamically from
436 // references to tracks, which we do not keep in muon aods...)
438 copiedVertex->SetNContributors(v->GetNContributors());
443 fDimuons->Clear("C");
445 // as there might be a track cut (different from the one of the main filtering),
446 // we must recreate the dimuon completely from scratch to be 100% safe...
450 // Dimuons built of 2 MUON tracks or 2 MUON+MFT tracks // AU
451 for (Int_t i=0; i<nMuons; ++i) {
452 for (Int_t j=i+1; j<nMuons; ++j) {
453 if ( (((AliAODTrack*) fTracks->At(i))->IsMuonTrack() && ((AliAODTrack*) fTracks->At(j))->IsMuonTrack()) ||
454 (((AliAODTrack*) fTracks->At(i))->IsMuonGlobalTrack() && ((AliAODTrack*) fTracks->At(j))->IsMuonGlobalTrack()) ) {
455 new((*fDimuons)[nDimuons++]) AliAODDimuon(fTracks->At(i), fTracks->At(j));
460 AliDebug(1,Form("input mu tracks=%d tracks=%d vertices=%d ndimuons=%d",
461 inputMuons,fTracks->GetEntries(),fVertices->GetEntries(),fDimuons->GetEntries()));
463 // Finally, deal with MC information, if needed
465 if (fMCMode>0) FilterMC(source);