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 **************************************************************************/
19 #include "AliMUONRefitter.h"
20 #include "AliMUONGeometryTransformer.h"
21 #include "AliMUONClusterFinderCOG.h"
22 #include "AliMUONClusterFinderMLEM.h"
23 #include "AliMUONClusterFinderSimpleFit.h"
24 #include "AliMUONPreClusterFinder.h"
25 #include "AliMUONPreClusterFinderV2.h"
26 #include "AliMUONPreClusterFinderV3.h"
27 #include "AliMUONSimpleClusterServer.h"
28 #include "AliMUONReconstructor.h"
29 #include "AliMUONTrackReconstructor.h"
30 #include "AliMUONTrackReconstructorK.h"
31 #include "AliMUONRecoParam.h"
32 #include "AliMUONESDInterface.h"
33 #include "AliMUONVClusterStore.h"
34 #include "AliMUONVTrackStore.h"
35 #include "AliMUONTrack.h"
36 #include "AliMUONTracker.h"
37 #include "AliMUONTrackParam.h"
40 //-----------------------------------------------------------------------------
41 /// \class AliMUONRefitter
43 /// This class has been developped to simplify the re-reconstruction of the MUON tracks
44 /// stored into ESD with different recoParams and/or after having re-calibrated the digits.
45 /// It creates new MUON object from ESD objects given as input (through the ESDInterface) then:
47 /// - re-clusterize the ESD clusters using the attached ESD pads
48 /// (several new clusters can be reconstructed per ESD cluster)
49 /// - re-fit the ESD tracks using the attached ESD clusters
50 /// - reconstruct the ESD tracks from ESD pads (i.e. re-clusterized the attached clusters)
53 /// - connexion between an ESD cluster and corresponding MUON clusters from re-clustering
54 /// can be made through the detection element ID
55 /// - connexion between an ESD track and the corresponding refitted MUON track
56 /// can be made through their unique ID
58 /// \author Philippe Pillot
59 //-----------------------------------------------------------------------------
62 ClassImp(AliMUONRefitter)
65 //_____________________________________________________________________________
66 AliMUONRefitter::AliMUONRefitter(const AliMUONRecoParam* recoParam)
68 fkRecoParam(recoParam),
70 fGeometryTransformer(0x0),
74 /// Default constructor
75 CreateGeometryTransformer();
76 CreateClusterServer(*fGeometryTransformer);
77 if (fClusterServer) fTracker = AliMUONTracker::CreateTrackReconstructor(recoParam,fClusterServer);
78 if (!fClusterServer || !fTracker) {
79 AliFatal("refitter initialization failed");
84 //_____________________________________________________________________________
85 AliMUONRefitter::~AliMUONRefitter()
88 delete fGeometryTransformer;
89 delete fClusterServer;
93 //_____________________________________________________________________________
94 AliMUONVTrackStore* AliMUONRefitter::ReconstructFromDigits()
96 /// re-reconstruct all tracks and attached clusters from the digits
97 /// it is the responsability of the user to delete the returned store
99 if (!fkESDInterface) {
100 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
104 // prepare new track(s)
105 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
106 if (!newTrackStore) return 0x0;
108 // loop over tracks and refit them (create new tracks)
110 TIter next(fkESDInterface->CreateTrackIterator());
111 while ((track = static_cast<AliMUONTrack*>(next()))) {
112 AliMUONTrack *newTrack = RetrackFromDigits(*track);
113 newTrackStore->Add(newTrack);
117 return newTrackStore;
120 //_____________________________________________________________________________
121 AliMUONVTrackStore* AliMUONRefitter::ReconstructFromClusters()
123 /// refit all tracks from the attached clusters
124 /// it is the responsability of the user to delete the returned store
126 if (!fkESDInterface) {
127 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
131 // prepare new track(s)
132 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
133 if (!newTrackStore) return 0x0;
135 // loop over tracks and refit them (create new tracks)
137 TIter next(fkESDInterface->CreateTrackIterator());
138 while ((track = static_cast<AliMUONTrack*>(next()))) {
139 AliMUONTrack* newTrack = newTrackStore->Add(*track);
140 if (!fTracker->RefitTrack(*newTrack)) newTrackStore->Remove(*newTrack);
143 return newTrackStore;
146 //_____________________________________________________________________________
147 AliMUONTrack* AliMUONRefitter::RetrackFromDigits(UInt_t trackId)
149 /// refit track "trackId" from the digits (i.e. re-clusterized the attached clusters)
150 /// it is the responsability of the user to delete the returned track
152 if (!fkESDInterface) {
153 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
157 // get the track to refit
158 AliMUONTrack* track = fkESDInterface->FindTrack(trackId);
160 return track ? RetrackFromDigits(*track) : 0x0;
163 //_____________________________________________________________________________
164 AliMUONTrack* AliMUONRefitter::RetrackFromClusters(UInt_t trackId)
166 /// refit track "trackId" from the clusters (i.e. do not re-clusterize)
167 /// it is the responsability of the user to delete the returned track
169 if (!fkESDInterface) {
170 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
174 // get the track to refit
175 AliMUONTrack* track = fkESDInterface->FindTrack(trackId);
176 if (!track) return 0x0;
178 // refit the track (create a new one)
179 AliMUONTrack* newTrack = new AliMUONTrack(*track);
180 if (!fTracker->RefitTrack(*newTrack)) {
188 //_____________________________________________________________________________
189 AliMUONVClusterStore* AliMUONRefitter::ReClusterize(UInt_t trackId, UInt_t clusterId)
191 /// re-clusterize cluster numbered "clusterId" in track "trackId"
192 /// several new clusters may be reconstructed
193 /// it is the responsability of the user to delete the returned store
195 if (!fkESDInterface) {
196 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
200 // get the cluster to re-clusterize
201 AliMUONVCluster* cluster = fkESDInterface->FindCluster(trackId,clusterId);
202 if (!cluster) return 0x0;
204 // check if digits exist
205 if (cluster->GetNDigits() == 0) {
206 AliError(Form("no digit attached to cluster #%d in track %d",clusterId,trackId));
210 // create the cluster store
211 AliMUONVClusterStore* clusterStore = AliMUONESDInterface::NewClusterStore();
212 if (!clusterStore) return 0x0;
215 TIter next(fkESDInterface->CreateDigitIterator(trackId, clusterId));
216 fClusterServer->UseDigits(next,fkESDInterface->GetDigits());
217 fClusterServer->Clusterize(cluster->GetChamberId(),*clusterStore,AliMpArea(),fkRecoParam);
222 //_____________________________________________________________________________
223 AliMUONVClusterStore* AliMUONRefitter::ReClusterize(UInt_t clusterId)
225 /// re-clusterize cluster "clusterId"
226 /// several new clusters may be reconstructed
227 /// it is the responsability of the user to delete the returned store
229 if (!fkESDInterface) {
230 AliError("the refitter must be connected to an ESDInterface containing the ESD event to reconstruct");
234 // get the cluster to re-clusterize
235 AliMUONVCluster* cluster = fkESDInterface->FindCluster(clusterId);
236 if (!cluster) return 0x0;
238 // check if digits exist
239 if (cluster->GetNDigits() == 0) {
240 AliError(Form("no digit attached to cluster %d",clusterId));
244 // create the cluster store
245 AliMUONVClusterStore* clusterStore = AliMUONESDInterface::NewClusterStore();
246 if (!clusterStore) return 0x0;
249 TIter next(fkESDInterface->CreateDigitIteratorInCluster(clusterId));
250 fClusterServer->UseDigits(next,fkESDInterface->GetDigits());
251 fClusterServer->Clusterize(cluster->GetChamberId(),*clusterStore,AliMpArea(),fkRecoParam);
256 //_____________________________________________________________________________
257 void AliMUONRefitter::CreateGeometryTransformer()
259 /// Create geometry transformer (local<->global)
260 /// and load geometry data
261 fGeometryTransformer = new AliMUONGeometryTransformer();
262 fGeometryTransformer->LoadGeometryData();
265 //_____________________________________________________________________________
266 void AliMUONRefitter::CreateClusterServer(AliMUONGeometryTransformer& transformer)
268 /// Create cluster server
269 AliMUONVClusterFinder* clusterFinder = AliMUONReconstructor::CreateClusterFinder(fkRecoParam->GetClusteringMode());
270 fClusterServer = clusterFinder ? new AliMUONSimpleClusterServer(clusterFinder,transformer) : 0x0;
273 //_____________________________________________________________________________
274 AliMUONTrack* AliMUONRefitter::RetrackFromDigits(const AliMUONTrack& track)
276 /// refit the given track from the digits (i.e. re-clusterized the attached clusters):
277 /// several new clusters may be reconstructed per initial ESD cluster:
278 /// -> all the combinations of clusters are considered to build the new tracks
279 /// -> return the best track (largest number of clusters or best chi2 in case of equality)
281 // check if digits exist
282 UInt_t trackId = track.GetUniqueID();
283 if (fkESDInterface->GetNDigits(trackId) == 0) {
284 AliError(Form("no digit attached to track #%d",trackId));
288 // prepare new track(s)
289 AliMUONVTrackStore* newTrackStore = AliMUONESDInterface::NewTrackStore();
290 if (!newTrackStore) return 0x0;
291 newTrackStore->Add(track)->Clear("C");
293 // prepare new cluster store
294 AliMUONVClusterStore* newClusterStore = AliMUONESDInterface::NewClusterStore();
295 if (!newClusterStore) {
296 delete newTrackStore;
300 // loop over clusters, re-clusterize and build new tracks
301 AliMUONVCluster* cluster;
302 TIter nextCluster(fkESDInterface->CreateClusterIterator(trackId));
303 while ((cluster = static_cast<AliMUONVCluster*>(nextCluster()))) {
305 // reset the new cluster store
306 newClusterStore->Clear();
308 // re-clusterize current cluster
309 TIter nextDigit(fkESDInterface->CreateDigitIterator(trackId, cluster->GetUniqueID()));
310 fClusterServer->UseDigits(nextDigit,fkESDInterface->GetDigits());
311 Int_t nNewClusters = fClusterServer->Clusterize(cluster->GetChamberId(),*newClusterStore,AliMpArea(),fkRecoParam);
313 // check that re-clusterizing succeeded
314 if (nNewClusters == 0) {
315 AliWarning(Form("refit gave no cluster (chamber %d)",cluster->GetChamberId()));
316 AliInfo("initial ESD cluster:");
317 cluster->Print("FULL");
321 // add the new cluster(s) to the tracks
322 AddClusterToTracks(*newClusterStore, *newTrackStore);
326 // refit the tracks and pick up the best one
327 AliMUONTrack *currentTrack, *bestTrack = 0x0;
328 Double_t currentChi2, bestChi2 = 1.e10;
329 Int_t currentNCluster, bestNClusters = 0;
330 TIter next(newTrackStore->CreateIterator());
331 while ((currentTrack = static_cast<AliMUONTrack*>(next()))) {
333 // set the track parameters at first cluster if any (used as seed in original tracking)
334 AliMUONTrackParam* param = (AliMUONTrackParam*) currentTrack->GetTrackParamAtCluster()->First();
335 if (param) *param = *((AliMUONTrackParam*) track.GetTrackParamAtCluster()->First());
338 if (!fTracker->RefitTrack(*currentTrack)) break;
340 // find best track (the one with the higher number of cluster or the best chi2 in case of equality)
341 currentNCluster = currentTrack->GetNClusters();
342 currentChi2 = currentTrack->GetGlobalChi2();
343 if (currentNCluster > bestNClusters || (currentNCluster == bestNClusters && currentChi2 < bestChi2)) {
344 bestTrack = currentTrack;
345 bestNClusters = currentNCluster;
346 bestChi2 = currentChi2;
351 // copy best track and free memory
352 AliMUONTrack* newTrack = bestTrack ? new AliMUONTrack(*bestTrack) : 0x0;
353 delete newClusterStore;
354 delete newTrackStore;
359 //_____________________________________________________________________________
360 void AliMUONRefitter::AddClusterToTracks(const AliMUONVClusterStore &clusterStore, AliMUONVTrackStore &trackStore)
362 /// add clusters to each of the given tracks
363 /// duplicate the tracks if there are several clusters and add one cluster per copy
365 // create new track store if there are more than 1 cluster to add per track
366 Int_t nClusters = clusterStore.GetSize();
367 if (nClusters < 1) return;
369 AliMUONTrackParam dummyParam;
370 AliMUONTrack *currentTrack, *track;
371 AliMUONVCluster *newCluster;
372 Int_t nTracks = trackStore.GetSize();
376 // loop over existing tracks to add the cluster(s)
377 TIter nextTrack(trackStore.CreateIterator());
378 while ((currentTrack = static_cast<AliMUONTrack*>(nextTrack())) && (iTrack < nTracks)) {
382 // add the new cluster(s) to the tracks
383 // duplicate the tracks if there are several clusters
384 // the loop after loading the last cluster which is added to the current track
386 TIter nextCluster(clusterStore.CreateIterator());
387 while ((newCluster = static_cast<AliMUONVCluster*>(nextCluster())) && (iCluster < nClusters - 1)) {
391 // add a copy of the current track to the store
392 track = trackStore.Add(AliMUONTrack(*currentTrack));
394 // only set Z parameter to avoid error in AddTrackParamAtCluster()
395 // the rest will be recomputed during refit
396 dummyParam.SetZ(newCluster->GetZ());
398 // add new cluster to the new track
399 track->AddTrackParamAtCluster(dummyParam, *newCluster, kTRUE);
403 // only set Z parameter to avoid error in AddTrackParamAtCluster()
404 // the rest will be recomputed during refit
405 dummyParam.SetZ(newCluster->GetZ());
407 // add new cluster to the current track
408 currentTrack->AddTrackParamAtCluster(dummyParam, *newCluster, kTRUE);