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 #include "AliMUONRefitter.h"
19 #include "AliMUONGeometryTransformer.h"
20 #include "AliMUONClusterFinderCOG.h"
21 #include "AliMUONClusterFinderMLEM.h"
22 #include "AliMUONClusterFinderSimpleFit.h"
23 #include "AliMUONPreClusterFinder.h"
24 #include "AliMUONPreClusterFinderV2.h"
25 #include "AliMUONPreClusterFinderV3.h"
26 #include "AliMUONSimpleClusterServer.h"
27 #include "AliMUONTrackReconstructor.h"
28 #include "AliMUONTrackReconstructorK.h"
29 #include "AliMUONRecoParam.h"
30 #include "AliMUONESDInterface.h"
31 #include "AliMUONVClusterStore.h"
32 #include "AliMUONVTrackStore.h"
33 #include "AliMUONTrack.h"
37 //-----------------------------------------------------------------------------
38 /// \class AliMUONRefitter
40 /// create new MUON object from ESD objects given as input (through the ESDInterface):
42 /// - re-clusterize the ESD clusters using the attached ESD pads
43 /// (several new clusters can be reconstructed per ESD cluster)
44 /// - re-fit the ESD tracks using the attached ESD clusters
45 /// - reconstruct the ESD tracks from ESD pads (i.e. re-clusterized the attached clusters)
48 /// - connexion between an ESD cluster and corresponding MUON clusters from re-clustering
49 /// can be made through the detection element ID
50 /// - connexion between an ESD track and the corresponding refitted MUON track
51 /// can be made through their unique ID
53 /// \author Philippe Pillot
54 //-----------------------------------------------------------------------------
57 ClassImp(AliMUONRefitter)
60 //_____________________________________________________________________________
61 AliMUONRefitter::AliMUONRefitter()
63 fGeometryTransformer(0x0),
68 /// Default constructor
69 CreateGeometryTransformer();
70 CreateClusterServer(*fGeometryTransformer);
71 if (fClusterServer) CreateTrackReconstructor(*fClusterServer);
72 if (!fClusterServer || !fTracker) {
73 AliFatal("refitter initialization failed");
78 //_____________________________________________________________________________
79 AliMUONRefitter::~AliMUONRefitter()
82 delete fGeometryTransformer;
83 delete fClusterServer;
87 //_____________________________________________________________________________
88 AliMUONVTrackStore* AliMUONRefitter::ReconstructFromDigits()
90 /// re-reconstruct all tracks and attached clusters from the digits
91 /// it is the responsability of the user to delete the returned store
94 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
98 // prepare new track(s)
99 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
100 if (!newTrackStore) return 0x0;
102 // loop over tracks and refit them (create new tracks)
103 Int_t nTracks = fESDInterface->GetNTracks();
104 for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
105 AliMUONTrack *track = RetrackFromDigits(iTrack);
106 newTrackStore->Add(track);
110 return newTrackStore;
113 //_____________________________________________________________________________
114 AliMUONVTrackStore* AliMUONRefitter::ReconstructFromClusters()
116 /// refit all tracks from the attached clusters
117 /// it is the responsability of the user to delete the returned store
119 if (!fESDInterface) {
120 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
124 // prepare new track(s)
125 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
126 if (!newTrackStore) return 0x0;
128 // loop over tracks and refit them (create new tracks)
130 TIter next(fESDInterface->CreateTrackIterator());
131 while ((track = static_cast<AliMUONTrack*>(next()))) {
132 AliMUONTrack* newTrack = newTrackStore->Add(*track);
133 if (!fTracker->RefitTrack(*newTrack)) newTrackStore->Remove(*newTrack);
136 return newTrackStore;
139 //_____________________________________________________________________________
140 AliMUONTrack* AliMUONRefitter::RetrackFromDigits(Int_t iTrack)
142 /// refit track "iTrack" from the digits (i.e. re-clusterized the attached clusters):
143 /// several new clusters may be reconstructed per initial ESD cluster:
144 /// -> all the combinations of clusters are considered to build the new tracks
145 /// -> return the best track (largest number of clusters or best chi2 in case of equality)
146 /// it is the responsability of the user to delete the returned track
148 if (!fESDInterface) {
149 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
153 // get the track to refit
154 AliMUONTrack* track = fESDInterface->GetTrack(iTrack);
155 if (!track) return 0x0;
157 // check if digits exist
158 if (fESDInterface->GetNDigits(iTrack) == 0) {
159 AliError(Form("no digit attached to track #%d",iTrack));
163 // prepare new track(s)
164 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
165 if (!newTrackStore) return 0x0;
166 newTrackStore->Add(*track)->Clear("C");
168 // prepare new cluster store
169 AliMUONVClusterStore* newClusterStore = AliMUONESDInterface::NewClusterStore();
170 if (!newClusterStore) {
171 delete newTrackStore;
175 // loop over clusters, re-clusterize and build new tracks
176 Int_t nClusters = track->GetNClusters();
177 for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
179 // reset the new cluster store
180 newClusterStore->Clear();
182 // get the current cluster
183 AliMUONVCluster* cluster = fESDInterface->GetClusterFast(iTrack,iCluster);
185 // re-clusterize current cluster
186 TIter next(fESDInterface->CreateDigitIterator(iTrack, iCluster));
187 fClusterServer->UseDigits(next);
188 Int_t nNewClusters = fClusterServer->Clusterize(cluster->GetChamberId(),*newClusterStore,AliMpArea());
190 // check that re-clusterizing succeeded
191 if (nNewClusters == 0) {
192 AliWarning(Form("refit gave no cluster (chamber %d)",cluster->GetChamberId()));
193 AliInfo("initial ESD cluster:");
194 cluster->Print("FULL");
198 // add the new cluster(s) to the tracks
199 AddClusterToTracks(*newClusterStore, *newTrackStore);
203 // refit the tracks and pick up the best one
204 AliMUONTrack *currentTrack, *bestTrack = 0x0;
205 Double_t currentChi2, bestChi2 = 1.e10;
206 Int_t currentNCluster, bestNClusters = 0;
207 TIter next(newTrackStore->CreateIterator());
208 while ((currentTrack = static_cast<AliMUONTrack*>(next()))) {
210 // set the track parameters at first cluster if any (used as seed in original tracking)
211 AliMUONTrackParam* param = (AliMUONTrackParam*) currentTrack->GetTrackParamAtCluster()->First();
212 if (param) *param = *((AliMUONTrackParam*) track->GetTrackParamAtCluster()->First());
215 if (!fTracker->RefitTrack(*currentTrack)) break;
217 // find best track (the one with the higher number of cluster or the best chi2 in case of equality)
218 currentNCluster = currentTrack->GetNClusters();
219 currentChi2 = currentTrack->GetGlobalChi2();
220 if (currentNCluster > bestNClusters || (currentNCluster == bestNClusters && currentChi2 < bestChi2)) {
221 bestTrack = currentTrack;
222 bestNClusters = currentNCluster;
223 bestChi2 = currentChi2;
228 // copy best track and free memory
229 AliMUONTrack* newTrack = bestTrack ? new AliMUONTrack(*bestTrack) : 0x0;
230 delete newClusterStore;
231 delete newTrackStore;
236 //_____________________________________________________________________________
237 AliMUONTrack* AliMUONRefitter::RetrackFromClusters(Int_t iTrack)
239 /// refit track "iTrack" form the clusters (i.e. do not re-clusterize)
240 /// it is the responsability of the user to delete the returned track
242 if (!fESDInterface) {
243 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
247 // get the track to refit
248 AliMUONTrack* track = fESDInterface->GetTrack(iTrack);
249 if (!track) return 0x0;
251 // refit the track (create a new one)
252 AliMUONTrack* newTrack = new AliMUONTrack(*track);
253 if (!fTracker->RefitTrack(*newTrack)) {
261 //_____________________________________________________________________________
262 AliMUONVClusterStore* AliMUONRefitter::ReClusterize(Int_t iTrack, Int_t iCluster)
264 /// re-clusterize cluster numbered "iCluster" in track "iTrack"
265 /// several new clusters may be reconstructed
266 /// it is the responsability of the user to delete the returned store
268 if (!fESDInterface) {
269 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
273 // get the cluster to re-clusterize
274 AliMUONVCluster* cluster = fESDInterface->GetCluster(iTrack,iCluster);
275 if (!cluster) return 0x0;
277 // check if digits exist
278 if (cluster->GetNDigits() == 0) {
279 AliError(Form("no digit attached to cluster #%d in track %d",iCluster,iTrack));
283 // create the cluster store
284 AliMUONVClusterStore* clusterStore = AliMUONESDInterface::NewClusterStore();
285 if (!clusterStore) return 0x0;
288 TIter next(fESDInterface->CreateDigitIterator(iTrack, iCluster));
289 fClusterServer->UseDigits(next);
290 fClusterServer->Clusterize(cluster->GetChamberId(),*clusterStore,AliMpArea());
295 //_____________________________________________________________________________
296 AliMUONVClusterStore* AliMUONRefitter::ReClusterize(UInt_t clusterId)
298 /// re-clusterize cluster "clusterId"
299 /// several new clusters may be reconstructed
300 /// it is the responsability of the user to delete the returned store
302 if (!fESDInterface) {
303 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
307 // get the cluster to re-clusterize
308 AliMUONVCluster* cluster = fESDInterface->FindCluster(clusterId);
309 if (!cluster) return 0x0;
311 // check if digits exist
312 if (cluster->GetNDigits() == 0) {
313 AliError(Form("no digit attached to cluster %d",clusterId));
317 // create the cluster store
318 AliMUONVClusterStore* clusterStore = AliMUONESDInterface::NewClusterStore();
319 if (!clusterStore) return 0x0;
322 TIter next(fESDInterface->CreateDigitIteratorInCluster(clusterId));
323 fClusterServer->UseDigits(next);
324 fClusterServer->Clusterize(cluster->GetChamberId(),*clusterStore,AliMpArea());
329 //_____________________________________________________________________________
330 void AliMUONRefitter::CreateGeometryTransformer()
332 /// Create geometry transformer (local<->global)
333 /// and load geometry data
334 fGeometryTransformer = new AliMUONGeometryTransformer();
335 fGeometryTransformer->LoadGeometryData();
338 //_____________________________________________________________________________
339 void AliMUONRefitter::CreateClusterServer(AliMUONGeometryTransformer& transformer)
341 /// Create cluster server
342 AliMUONVClusterFinder* clusterFinder = CreateClusterFinder();
343 fClusterServer = clusterFinder ? new AliMUONSimpleClusterServer(*clusterFinder,transformer) : 0x0;
346 //_____________________________________________________________________________
347 AliMUONVClusterFinder* AliMUONRefitter::CreateClusterFinder()
349 /// Create a given cluster finder instance
350 AliMUONVClusterFinder* clusterFinder;
351 Option_t *opt = AliMUONReconstructor::GetRecoParam()->GetClusteringMode();
353 if (strstr(opt,"PRECLUSTERV2")) clusterFinder = new AliMUONPreClusterFinderV2;
354 else if (strstr(opt,"PRECLUSTERV3")) clusterFinder = new AliMUONPreClusterFinderV3;
355 else if (strstr(opt,"PRECLUSTER")) clusterFinder = new AliMUONPreClusterFinder;
356 else if (strstr(opt,"COG")) clusterFinder = new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder);
357 else if (strstr(opt,"SIMPLEFITV3")) clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinderV3));
358 else if (strstr(opt,"SIMPLEFIT")) clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder));
359 else if (strstr(opt,"MLEM:DRAW")) clusterFinder = new AliMUONClusterFinderMLEM(kTRUE,new AliMUONPreClusterFinder);
360 else if (strstr(opt,"MLEMV3")) clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV3);
361 else if (strstr(opt,"MLEMV2")) clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV2);
362 else if (strstr(opt,"MLEM")) clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinder);
363 else clusterFinder = 0x0;
366 AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
368 AliError(Form("clustering mode \"%s\" does not exist",opt));
371 return clusterFinder;
374 //_____________________________________________________________________________
375 void AliMUONRefitter::CreateTrackReconstructor(AliMUONVClusterServer& clusterServer)
377 /// Create track reconstructor, depending on tracking mode set in RecoParam
378 Option_t *opt = AliMUONReconstructor::GetRecoParam()->GetTrackingMode();
380 if (strstr(opt,"ORIGINAL")) fTracker = new AliMUONTrackReconstructor(clusterServer);
381 else if (strstr(opt,"KALMAN")) fTracker = new AliMUONTrackReconstructorK(clusterServer);
385 AliInfo(Form("Will use %s for tracking",fTracker->ClassName()));
387 AliError(Form("tracking mode \"%s\" does not exist",opt));
391 //_____________________________________________________________________________
392 void AliMUONRefitter::AddClusterToTracks(const AliMUONVClusterStore &clusterStore, AliMUONVTrackStore &trackStore)
394 /// add clusters to each of the given tracks
395 /// duplicate the tracks if there are several clusters and add one cluster per copy
397 // create new track store if there are more than 1 cluster to add per track
398 Int_t nClusters = clusterStore.GetSize();
399 if (nClusters < 1) return;
401 AliMUONTrackParam dummyParam;
402 AliMUONTrack *currentTrack, *track;
403 AliMUONVCluster *newCluster;
404 Int_t nTracks = trackStore.GetSize();
408 // loop over existing tracks to add the cluster(s)
409 TIter nextTrack(trackStore.CreateIterator());
410 while ((currentTrack = static_cast<AliMUONTrack*>(nextTrack())) && (iTrack < nTracks)) {
414 // add the new cluster(s) to the tracks
415 // duplicate the tracks if there are several clusters
416 // the loop after loading the last cluster which is added to the current track
418 TIter nextCluster(clusterStore.CreateIterator());
419 while ((newCluster = static_cast<AliMUONVCluster*>(nextCluster())) && (iCluster < nClusters - 1)) {
423 // add a copy of the current track to the store
424 track = trackStore.Add(AliMUONTrack(*currentTrack));
426 // only set Z parameter to avoid error in AddTrackParamAtCluster()
427 // the rest will be recomputed during refit
428 dummyParam.SetZ(newCluster->GetZ());
430 // add new cluster to the new track
431 track->AddTrackParamAtCluster(dummyParam, *newCluster, kTRUE);
435 // only set Z parameter to avoid error in AddTrackParamAtCluster()
436 // the rest will be recomputed during refit
437 dummyParam.SetZ(newCluster->GetZ());
439 // add new cluster to the current track
440 currentTrack->AddTrackParamAtCluster(dummyParam, *newCluster, kTRUE);