1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 /// \class AliMUONRecoCheck
20 /// Utility class to check reconstruction
21 /// Reconstructed tracks are compared to reference tracks.
22 /// The reference tracks are built from AliTrackReference for the
23 /// hit in chamber (0..9) and from kinematics for the vertex parameters.
24 //-----------------------------------------------------------------------------
27 // Added a method to create a list of reconstructed AliMUONTrack objects from
28 // ESD data. This is necessary since the track objects that are actually created
29 // during offline reconstruction are no longer stored to disk.
30 // - Artur Szostak <artursz@iafrica.com>
32 // Use the new ESDInterface to create MUON objects from ESD data
36 #include "AliMUONRecoCheck.h"
37 #include "AliMUONTrack.h"
38 #include "AliMUONVTrackStore.h"
39 #include "AliMUONVCluster.h"
40 #include "AliMUONVClusterStore.h"
41 #include "AliMUONConstants.h"
42 #include "AliMUONESDInterface.h"
43 #include "AliMUONTrackParam.h"
44 #include "AliMCEventHandler.h"
45 #include "AliMCEvent.h"
47 #include "AliTrackReference.h"
49 #include "AliESDEvent.h"
50 #include "AliESDMuonTrack.h"
54 #include <TParticle.h>
55 #include <TParticlePDG.h>
56 #include <Riostream.h>
59 ClassImp(AliMUONRecoCheck)
62 //_____________________________________________________________________________
63 AliMUONRecoCheck::AliMUONRecoCheck(const Char_t *esdFileName, const Char_t *pathSim)
65 fMCEventHandler(new AliMCEventHandler()),
66 fESDEvent(new AliESDEvent()),
71 fRecoTrackRefStore(0x0),
77 // TrackRefs and Particules
78 fMCEventHandler->SetInputPath(pathSim);
79 fMCEventHandler->InitIO("");
82 fESDFile = TFile::Open(esdFileName); // open the file
83 if (!fESDFile || !fESDFile->IsOpen()) {
84 AliError(Form("opening ESD file %s failed", esdFileName));
88 fESDTree = (TTree*) fESDFile->Get("esdTree"); // get the tree
90 AliError("no ESD tree found");
95 fESDEvent->ReadFromTree(fESDTree); // link fESDEvent to the tree
98 //_____________________________________________________________________________
99 AliMUONRecoCheck::AliMUONRecoCheck(AliESDEvent *esdEvent, AliMCEventHandler *mcEventHandler)
107 fRecoTrackRefStore(0x0),
108 fRecoTrackStore(0x0),
109 fESDEventOwner(kFALSE)
113 // TrackRefs and Particules
114 fMCEventHandler = mcEventHandler;
117 fESDEvent = esdEvent;
121 //_____________________________________________________________________________
122 AliMUONRecoCheck::~AliMUONRecoCheck()
125 if (fESDEventOwner) {
126 delete fMCEventHandler;
128 if (fESDFile) fESDFile->Close();
133 //_____________________________________________________________________________
134 void AliMUONRecoCheck::ResetStores()
136 /// Deletes all the store objects that have been created and resets the pointers to 0x0
137 delete fTrackRefStore; fTrackRefStore = 0x0;
138 delete fRecoTrackRefStore; fRecoTrackRefStore = 0x0;
139 delete fRecoTrackStore; fRecoTrackStore = 0x0;
142 //_____________________________________________________________________________
143 Int_t AliMUONRecoCheck::GetRunNumber()
145 /// Return the run number of the current ESD event
147 if (fESDEventOwner && fRecoTrackStore == 0x0) {
148 if (!fESDTree || fESDTree->GetEvent(fCurrentEvent) <= 0) {
149 AliError(Form("fails to read ESD object for event %d: cannot get the run number",fCurrentEvent));
154 return fESDEvent->GetRunNumber();
157 //_____________________________________________________________________________
158 Int_t AliMUONRecoCheck::NumberOfEvents() const
160 /// Return the number of events
161 if (fESDEventOwner && fESDTree) return fESDTree->GetEntries();
165 //_____________________________________________________________________________
166 AliMUONVTrackStore* AliMUONRecoCheck::ReconstructedTracks(Int_t event, Bool_t refit)
168 /// Return a track store containing the reconstructed tracks (converted into
169 /// MUONTrack objects) for a given event.
170 /// Track parameters at each clusters are computed or not depending on the flag "refit".
171 /// If not, only the track parameters at first cluster are valid.
173 if (!fESDEventOwner) {
174 if (fRecoTrackStore == 0x0) MakeReconstructedTracks(refit);
175 return fRecoTrackStore;
178 if (event != fCurrentEvent) {
180 fCurrentEvent = event;
183 if (fRecoTrackStore != 0x0) return fRecoTrackStore;
185 if (!fESDTree) return 0x0;
186 if (fESDTree->GetEvent(event) <= 0) {
187 AliError(Form("fails to read ESD object for event %d", event));
190 MakeReconstructedTracks(refit);
191 return fRecoTrackStore;
195 //_____________________________________________________________________________
196 AliMUONVTrackStore* AliMUONRecoCheck::TrackRefs(Int_t event)
198 /// Return a track store containing the track references (converted into
199 /// MUONTrack objects) for a given event
201 if (!fESDEventOwner) {
202 if (fTrackRefStore == 0x0) MakeTrackRefs();
203 return fTrackRefStore;
206 if (event != fCurrentEvent) {
208 fCurrentEvent = event;
211 if (fTrackRefStore != 0x0) return fTrackRefStore;
213 if (!fMCEventHandler->GetEvent(event)) {
214 AliError(Form("fails to read MC objects for event %d", event));
218 return fTrackRefStore;
222 //_____________________________________________________________________________
223 AliMUONVTrackStore* AliMUONRecoCheck::ReconstructibleTracks(Int_t event, UInt_t requestedStationMask, Bool_t request2ChInSameSt45)
225 /// Return a track store containing the reconstructible tracks for a given event,
226 /// according to the mask of requested stations and the minimum number of chambers hit in stations 4 & 5.
228 if (!fESDEventOwner) {
229 if (fRecoTrackRefStore == 0x0) {
230 if (TrackRefs(event) == 0x0) return 0x0;
231 MakeReconstructibleTracks(requestedStationMask, request2ChInSameSt45);
233 return fRecoTrackRefStore;
236 if (event != fCurrentEvent) {
238 fCurrentEvent = event;
241 if (fRecoTrackRefStore != 0x0) return fRecoTrackRefStore;
243 if (TrackRefs(event) == 0x0) return 0x0;
244 MakeReconstructibleTracks(requestedStationMask, request2ChInSameSt45);
245 return fRecoTrackRefStore;
249 //_____________________________________________________________________________
250 void AliMUONRecoCheck::MakeReconstructedTracks(Bool_t refit)
252 /// Make reconstructed tracks
253 if (!(fRecoTrackStore = AliMUONESDInterface::NewTrackStore())) return;
255 // loop over all reconstructed tracks and add them to the store (skip ghosts)
256 Int_t nTracks = (Int_t) fESDEvent->GetNumberOfMuonTracks();
257 for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
258 AliESDMuonTrack* esdTrack = fESDEvent->GetMuonTrack(iTrack);
259 if (esdTrack->ContainTrackerData()) AliMUONESDInterface::Add(*esdTrack, *fRecoTrackStore, refit);
264 //_____________________________________________________________________________
265 void AliMUONRecoCheck::MakeTrackRefs()
267 /// Make reconstructible tracks
268 AliMUONVTrackStore *tmpTrackRefStore = AliMUONESDInterface::NewTrackStore();
269 if (!tmpTrackRefStore) return;
271 Double_t x, y, z, pX, pY, pZ, bendingSlope, nonBendingSlope, inverseBendingMomentum;
273 TClonesArray* trackRefs;
274 Int_t nTrackRef = fMCEventHandler->MCEvent()->GetNumberOfTracks();
275 AliMUONVClusterStore* cStore = AliMUONESDInterface::NewClusterStore();
277 AliMUONVCluster* hit = cStore->CreateCluster(0,0,0);
279 // loop over simulated tracks
280 for (Int_t iTrackRef = 0; iTrackRef < nTrackRef; ++iTrackRef) {
281 Int_t nHits = fMCEventHandler->GetParticleAndTR(iTrackRef, particle, trackRefs);
283 // skip empty trackRefs
284 if (nHits < 1) continue;
286 // get the particle charge for further calculation
287 TParticlePDG* ppdg = particle->GetPDG();
288 Int_t charge = ppdg != NULL ? (Int_t)(ppdg->Charge()/3.0) : 0;
292 // loop over simulated track hits
293 for (Int_t iHit = 0; iHit < nHits; ++iHit) {
294 AliTrackReference* trackReference = static_cast<AliTrackReference*>(trackRefs->UncheckedAt(iHit));
296 // skip trackRefs not in MUON
297 if (trackReference->DetectorId() != AliTrackReference::kMUON) continue;
299 // Get track parameters of current hit
300 x = trackReference->X();
301 y = trackReference->Y();
302 z = trackReference->Z();
303 pX = trackReference->Px();
304 pY = trackReference->Py();
305 pZ = trackReference->Pz();
307 // check chamberId of current trackReference
308 Int_t detElemId = trackReference->UserId();
309 Int_t chamberId = detElemId / 100 - 1;
310 if (chamberId < 0 || chamberId >= AliMUONConstants::NTrackingCh()) continue;
312 // set hit parameters
313 hit->SetUniqueID(AliMUONVCluster::BuildUniqueID(chamberId, detElemId, iHit));
315 hit->SetErrXY(0.,0.);
317 // compute track parameters at hit
320 inverseBendingMomentum = 0;
321 if (TMath::Abs(pZ) > 0) {
322 bendingSlope = pY/pZ;
323 nonBendingSlope = pX/pZ;
325 Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
326 if (pYZ >0) inverseBendingMomentum = 1/pYZ;
327 inverseBendingMomentum *= charge;
329 // set track parameters at hit
330 AliMUONTrackParam trackParam;
331 trackParam.SetNonBendingCoor(x);
332 trackParam.SetBendingCoor(y);
334 trackParam.SetBendingSlope(bendingSlope);
335 trackParam.SetNonBendingSlope(nonBendingSlope);
336 trackParam.SetInverseBendingMomentum(inverseBendingMomentum);
338 // add track parameters at current hit to the track
339 track.AddTrackParamAtCluster(trackParam, *hit, kTRUE);
342 // if none of the track hits was in MUON, goto the next track
343 if (track.GetNClusters() < 1) continue;
345 // get track parameters at particle's vertex
353 // compute rest of track parameters at particle's vertex
356 inverseBendingMomentum = 0;
357 if (TMath::Abs(pZ) > 0) {
358 bendingSlope = pY/pZ;
359 nonBendingSlope = pX/pZ;
361 Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
362 if (pYZ >0) inverseBendingMomentum = 1/pYZ;
363 inverseBendingMomentum *= charge;
365 // set track parameters at particle's vertex
366 AliMUONTrackParam trackParamAtVertex;
367 trackParamAtVertex.SetNonBendingCoor(x);
368 trackParamAtVertex.SetBendingCoor(y);
369 trackParamAtVertex.SetZ(z);
370 trackParamAtVertex.SetBendingSlope(bendingSlope);
371 trackParamAtVertex.SetNonBendingSlope(nonBendingSlope);
372 trackParamAtVertex.SetInverseBendingMomentum(inverseBendingMomentum);
374 // add track parameters at vertex
375 track.SetTrackParamAtVertex(&trackParamAtVertex);
378 track.SetUniqueID(iTrackRef);
379 tmpTrackRefStore->Add(track);
382 CleanMuonTrackRef(tmpTrackRefStore);
386 delete tmpTrackRefStore;
389 //_____________________________________________________________________________
390 void AliMUONRecoCheck::CleanMuonTrackRef(const AliMUONVTrackStore *tmpTrackRefStore)
392 /// Re-calculate hits parameters because two AliTrackReferences are recorded for
393 /// each chamber (one when particle is entering + one when particle is leaving
394 /// the sensitive volume)
395 if (!(fTrackRefStore = AliMUONESDInterface::NewTrackStore())) return;
397 Double_t maxGasGap = 1.; // cm
398 Double_t x, y, z, pX, pY, pZ, x1, y1, z1, pX1, pY1, pZ1, z2;
399 Double_t bendingSlope,nonBendingSlope,inverseBendingMomentum;
400 AliMUONVClusterStore* cStore = AliMUONESDInterface::NewClusterStore();
402 AliMUONVCluster* hit = cStore->CreateCluster(0,0,0);
405 TIter next(tmpTrackRefStore->CreateIterator());
407 // loop over tmpTrackRef
409 while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
411 AliMUONTrack newTrack;
413 // loop over tmpTrackRef's hits
415 Int_t nTrackHits = track->GetNClusters();
416 while (iHit1 < nTrackHits) {
417 AliMUONTrackParam *trackParam1 = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->UncheckedAt(iHit1);
419 // get track parameters at hit1
420 x1 = trackParam1->GetNonBendingCoor();
421 y1 = trackParam1->GetBendingCoor();
422 z1 = trackParam1->GetZ();
423 pX1 = trackParam1->Px();
424 pY1 = trackParam1->Py();
425 pZ1 = trackParam1->Pz();
427 // prepare new track parameters
435 // loop over next tmpTrackRef's hits
436 Int_t nCombinedHits = 1;
437 for (Int_t iHit2 = iHit1+1; iHit2 < nTrackHits; iHit2++) {
438 AliMUONTrackParam *trackParam2 = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->UncheckedAt(iHit2);
440 // get z position of hit2
441 z2 = trackParam2->GetZ();
443 // complete new track parameters if hit2 is on the same detection element
444 if ( TMath::Abs(z2-z1) < maxGasGap ) {
445 x += trackParam2->GetNonBendingCoor();
446 y += trackParam2->GetBendingCoor();
448 pX += trackParam2->Px();
449 pY += trackParam2->Py();
450 pZ += trackParam2->Pz();
457 // finalize new track parameters
458 x /= (Double_t)nCombinedHits;
459 y /= (Double_t)nCombinedHits;
460 z /= (Double_t)nCombinedHits;
461 pX /= (Double_t)nCombinedHits;
462 pY /= (Double_t)nCombinedHits;
463 pZ /= (Double_t)nCombinedHits;
466 inverseBendingMomentum = 0;
467 if (TMath::Abs(pZ) > 0) {
468 bendingSlope = pY/pZ;
469 nonBendingSlope = pX/pZ;
471 Double_t pYZ = TMath::Sqrt(pY*pY+pZ*pZ);
472 if (pYZ >0) inverseBendingMomentum = 1/pYZ;
473 inverseBendingMomentum *= trackParam1->GetCharge();
475 // set hit parameters
476 hit->SetUniqueID(trackParam1->GetClusterPtr()->GetUniqueID());
478 hit->SetErrXY(0.,0.);
480 // set new track parameters at new hit
481 AliMUONTrackParam trackParam;
482 trackParam.SetNonBendingCoor(x);
483 trackParam.SetBendingCoor(y);
485 trackParam.SetBendingSlope(bendingSlope);
486 trackParam.SetNonBendingSlope(nonBendingSlope);
487 trackParam.SetInverseBendingMomentum(inverseBendingMomentum);
489 // add track parameters at current hit to the track
490 newTrack.AddTrackParamAtCluster(trackParam, *hit, kTRUE);
495 newTrack.SetUniqueID(track->GetUniqueID());
496 newTrack.SetTrackParamAtVertex(track->GetTrackParamAtVertex());
497 fTrackRefStore->Add(newTrack);
505 //_____________________________________________________________________________
506 void AliMUONRecoCheck::MakeReconstructibleTracks(UInt_t requestedStationMask, Bool_t request2ChInSameSt45)
508 /// Isolate the reconstructible tracks
509 if (!(fRecoTrackRefStore = AliMUONESDInterface::NewTrackStore())) return;
511 // create iterator on trackRef
512 TIter next(fTrackRefStore->CreateIterator());
514 // loop over trackRef and add reconstructible tracks to fRecoTrackRefStore
516 while ( ( track = static_cast<AliMUONTrack*>(next()) ) ) {
517 if (track->IsValid(requestedStationMask, request2ChInSameSt45)) fRecoTrackRefStore->Add(*track);
522 //_____________________________________________________________________________
523 AliMUONTrack* AliMUONRecoCheck::FindCompatibleTrack(AliMUONTrack &track, AliMUONVTrackStore &trackStore,
524 Int_t &nMatchClusters, Bool_t useLabel, Double_t sigmaCut)
526 /// Return the track from the store matched with the given track (or 0x0) and the number of matched clusters.
527 /// Matching is done by using the MC label of by comparing cluster/TrackRef positions according to the flag "useLabel".
528 /// WARNING: Who match who matters since the matching algorithm uses the *fraction* of matched clusters of the given track
530 AliMUONTrack *matchedTrack = 0x0;
533 if (useLabel) { // by using the MC label
535 // get the corresponding simulated track if any
536 Int_t label = track.GetMCLabel();
537 matchedTrack = (AliMUONTrack*) trackStore.FindObject(label);
539 // get the fraction of matched clusters
541 Int_t nClusters = track.GetNClusters();
542 for (Int_t iCl = 0; iCl < nClusters; iCl++)
543 if (((AliMUONTrackParam*) track.GetTrackParamAtCluster()->UncheckedAt(iCl))->GetClusterPtr()->GetMCLabel() == label)
547 } else { // by comparing cluster/TrackRef positions
549 // look for the corresponding simulated track if any
550 TIter next(trackStore.CreateIterator());
551 AliMUONTrack* track2;
552 while ( ( track2 = static_cast<AliMUONTrack*>(next()) ) ) {
554 // check compatibility
556 if (track.Match(*track2, sigmaCut, n)) {
557 matchedTrack = track2;