]>
Commit | Line | Data |
---|---|---|
8cc77df0 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
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 | **************************************************************************/ | |
15 | ||
16 | /* $Id$ */ | |
17 | ||
3d1463c8 | 18 | //----------------------------------------------------------------------------- |
06ca6d7b | 19 | /// \class AliMUONTrackReconstructorK |
06ca6d7b | 20 | /// |
21 | /// MUON track reconstructor using the kalman method | |
22 | /// | |
23 | /// This class contains as data: | |
24 | /// - the parameters for the track reconstruction | |
25 | /// | |
26 | /// It contains as methods, among others: | |
27 | /// - MakeTracks to build the tracks | |
28 | /// | |
3d1463c8 | 29 | //----------------------------------------------------------------------------- |
8cc77df0 | 30 | |
8cc77df0 | 31 | #include "AliMUONTrackReconstructorK.h" |
96ebe67e | 32 | |
8cc77df0 | 33 | #include "AliMUONConstants.h" |
96ebe67e | 34 | #include "AliMUONVCluster.h" |
1fef78c8 | 35 | #include "AliMUONVClusterServer.h" |
96ebe67e | 36 | #include "AliMUONVClusterStore.h" |
ea94c18b | 37 | #include "AliMUONTrack.h" |
38 | #include "AliMUONTrackParam.h" | |
39 | #include "AliMUONTrackExtrap.h" | |
8cde4af5 | 40 | |
1fef78c8 | 41 | #include "AliMpArea.h" |
42 | ||
8cc77df0 | 43 | #include "AliLog.h" |
44 | ||
8cde4af5 | 45 | #include <Riostream.h> |
ea94c18b | 46 | #include <TMath.h> |
47 | #include <TMatrixD.h> | |
8cde4af5 | 48 | |
49 | /// \cond CLASSIMP | |
8cc77df0 | 50 | ClassImp(AliMUONTrackReconstructorK) // Class implementation in ROOT context |
8cde4af5 | 51 | /// \endcond |
8cc77df0 | 52 | |
019df241 | 53 | //__________________________________________________________________________ |
1fef78c8 | 54 | AliMUONTrackReconstructorK::AliMUONTrackReconstructorK(AliMUONVClusterServer& clusterServer) |
55 | : AliMUONVTrackReconstructor(clusterServer) | |
8cc77df0 | 56 | { |
96ebe67e | 57 | /// Constructor |
8cc77df0 | 58 | } |
59 | ||
019df241 | 60 | //__________________________________________________________________________ |
ea94c18b | 61 | AliMUONTrackReconstructorK::~AliMUONTrackReconstructorK() |
8cc77df0 | 62 | { |
ea94c18b | 63 | /// Destructor |
64 | } | |
8cc77df0 | 65 | |
66 | //__________________________________________________________________________ | |
1fef78c8 | 67 | void AliMUONTrackReconstructorK::MakeTrackCandidates(AliMUONVClusterStore& clusterStore) |
8cc77df0 | 68 | { |
019df241 | 69 | /// To make track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE): |
ea94c18b | 70 | /// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4. |
96ebe67e | 71 | /// Good candidates are made of at least three clusters. |
ea94c18b | 72 | /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks. |
b709ac13 | 73 | |
208f139e | 74 | TClonesArray *segments; |
ea94c18b | 75 | AliMUONTrack *track; |
76 | Int_t iCandidate = 0; | |
96ebe67e | 77 | Bool_t clusterFound; |
8cc77df0 | 78 | |
ea94c18b | 79 | AliDebug(1,"Enter MakeTrackCandidates"); |
8cc77df0 | 80 | |
1fef78c8 | 81 | // Unless we're doing combined tracking, we'll clusterize all stations at once |
82 | Int_t firstChamber(0); | |
83 | Int_t lastChamber(9); | |
84 | ||
85 | if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) { | |
86 | // ... Here's the exception : ask the clustering to reconstruct | |
87 | // clusters *only* in station 4 and 5 for combined tracking | |
88 | firstChamber = 6; | |
89 | } | |
90 | ||
91 | for (Int_t i = firstChamber; i <= lastChamber; ++i ) | |
92 | { | |
93 | fClusterServer.Clusterize(i, clusterStore, AliMpArea()); | |
94 | } | |
95 | ||
ea94c18b | 96 | // Loop over stations(1..) 5 and 4 and make track candidates |
97 | for (Int_t istat=4; istat>=3; istat--) { | |
98 | ||
208f139e | 99 | // Make segments in the station |
96ebe67e | 100 | segments = MakeSegmentsInStation(clusterStore, istat); |
ea94c18b | 101 | |
102 | // Loop over segments | |
103 | for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) { | |
104 | AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate)); | |
105 | ||
106 | // Transform segments to tracks and put them at the end of fRecTracksPtr | |
107 | track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg])); | |
108 | fNRecTracks++; | |
109 | ||
ea94c18b | 110 | // Printout for debuging |
111 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) { | |
96ebe67e | 112 | cout<<endl<<"Track parameter covariances at first cluster:"<<endl; |
113 | ((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->First()))->GetCovariances().Print(); | |
ea94c18b | 114 | } |
115 | ||
96ebe67e | 116 | // Look for compatible cluster(s) in the other station |
117 | if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast()) | |
118 | clusterFound = FollowLinearTrackInStation(*track, clusterStore, 7-istat); | |
019df241 | 119 | else { |
120 | // First recompute track parameters and covariances on station(1..) 5 using Kalman filter | |
121 | // (to make sure all tracks are treated in the same way) | |
96ebe67e | 122 | if (istat == 4) RetraceTrack(*track, kFALSE); |
123 | clusterFound = FollowTrackInStation(*track, clusterStore, 7-istat); | |
019df241 | 124 | } |
125 | ||
96ebe67e | 126 | // Remove track if no cluster found |
127 | if (!clusterFound) { | |
ea94c18b | 128 | fRecTracksPtr->Remove(track); |
129 | fNRecTracks--; | |
130 | } | |
131 | ||
132 | } | |
133 | // delete the array of segments | |
7ec3b9cf | 134 | delete segments; |
ea94c18b | 135 | } |
136 | ||
ea94c18b | 137 | |
019df241 | 138 | // Retrace tracks using Kalman filter and remove bad ones |
3304fa09 | 139 | if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast()) { |
019df241 | 140 | fRecTracksPtr->Compress(); // this is essential before checking tracks |
ea94c18b | 141 | |
019df241 | 142 | Int_t currentNRecTracks = fNRecTracks; |
143 | for (Int_t iRecTrack = 0; iRecTrack < currentNRecTracks; iRecTrack++) { | |
144 | track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack); | |
145 | ||
146 | // Recompute track parameters and covariances using Kalman filter | |
147 | RetraceTrack(*track,kTRUE); | |
148 | ||
149 | // Remove the track if the normalized chi2 is too high | |
3304fa09 | 150 | if (track->GetNormalizedChi2() > AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * |
151 | AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking()) { | |
019df241 | 152 | fRecTracksPtr->Remove(track); |
153 | fNRecTracks--; | |
154 | } | |
155 | ||
ea94c18b | 156 | } |
157 | ||
158 | } | |
159 | ||
160 | fRecTracksPtr->Compress(); // this is essential before checking tracks | |
161 | ||
162 | // Keep all different tracks or only the best ones as required | |
3304fa09 | 163 | if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks(); |
ea94c18b | 164 | else RemoveDoubleTracks(); |
165 | ||
166 | AliDebug(1,Form("Number of good candidates = %d",fNRecTracks)); | |
167 | ||
8cc77df0 | 168 | } |
169 | ||
ea94c18b | 170 | //__________________________________________________________________________ |
171 | void AliMUONTrackReconstructorK::RetraceTrack(AliMUONTrack &trackCandidate, Bool_t resetSeed) | |
8cc77df0 | 172 | { |
96ebe67e | 173 | /// Re-run the kalman filter from the most downstream cluster to the most uptream one |
ea94c18b | 174 | AliDebug(1,"Enter RetraceTrack"); |
175 | ||
96ebe67e | 176 | AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Last(); |
ea94c18b | 177 | |
96ebe67e | 178 | // Reset the "seed" (= track parameters and their covariances at last cluster) if required |
ea94c18b | 179 | if (resetSeed) { |
96ebe67e | 180 | // => Shift track parameters at the position of the last cluster |
181 | AliMUONVCluster* cluster = startingTrackParam->GetClusterPtr(); | |
182 | startingTrackParam->SetNonBendingCoor(cluster->GetX()); | |
183 | startingTrackParam->SetBendingCoor(cluster->GetY()); | |
ea94c18b | 184 | |
96ebe67e | 185 | // => Re-compute and reset track parameters covariances at last cluster (as if the other clusters did not exist) |
ea94c18b | 186 | const TMatrixD& kParamCov = startingTrackParam->GetCovariances(); |
187 | TMatrixD newParamCov(5,5); | |
188 | newParamCov.Zero(); | |
189 | // Non bending plane | |
96ebe67e | 190 | newParamCov(0,0) = cluster->GetErrX2(); |
ea94c18b | 191 | newParamCov(1,1) = 100.*kParamCov(1,1); |
192 | // Bending plane | |
96ebe67e | 193 | newParamCov(2,2) = cluster->GetErrY2(); |
ea94c18b | 194 | newParamCov(3,3) = 100.*kParamCov(3,3); |
195 | // Inverse bending momentum | |
196 | newParamCov(4,4) = 0.5*startingTrackParam->GetInverseBendingMomentum() * 0.5*startingTrackParam->GetInverseBendingMomentum(); | |
197 | startingTrackParam->SetCovariances(newParamCov); | |
198 | ||
199 | // Reset the track chi2 | |
200 | startingTrackParam->SetTrackChi2(0.); | |
201 | ||
202 | } | |
203 | ||
204 | // Redo the tracking | |
205 | RetracePartialTrack(trackCandidate, startingTrackParam); | |
206 | ||
207 | } | |
8cc77df0 | 208 | |
ea94c18b | 209 | //__________________________________________________________________________ |
210 | void AliMUONTrackReconstructorK::RetracePartialTrack(AliMUONTrack &trackCandidate, const AliMUONTrackParam* startingTrackParam) | |
211 | { | |
96ebe67e | 212 | /// Re-run the kalman filter from the cluster attached to startingTrackParam to the most uptream cluster |
ea94c18b | 213 | AliDebug(1,"Enter RetracePartialTrack"); |
214 | ||
215 | // Printout for debuging | |
216 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 217 | cout << "RetracePartialTrack: track chi2 before re-tracking: " << trackCandidate.GetGlobalChi2() << endl; |
ea94c18b | 218 | } |
219 | ||
220 | // Reset the track chi2 | |
96ebe67e | 221 | trackCandidate.SetGlobalChi2(startingTrackParam->GetTrackChi2()); |
ea94c18b | 222 | |
96ebe67e | 223 | // loop over attached clusters until the first one and recompute track parameters and covariances using kalman filter |
224 | Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() - 1; | |
ea94c18b | 225 | Int_t currentChamber; |
96ebe67e | 226 | Double_t addChi2TrackAtCluster; |
227 | AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Before(startingTrackParam); | |
228 | while (trackParamAtCluster) { | |
ea94c18b | 229 | |
230 | // reset track parameters and their covariances | |
96ebe67e | 231 | trackParamAtCluster->SetParameters(startingTrackParam->GetParameters()); |
232 | trackParamAtCluster->SetZ(startingTrackParam->GetZ()); | |
233 | trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances()); | |
ea94c18b | 234 | |
235 | // add MCS effect | |
96ebe67e | 236 | AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.); |
ea94c18b | 237 | |
238 | // reset propagator for smoother | |
96ebe67e | 239 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) trackParamAtCluster->ResetPropagator(); |
ea94c18b | 240 | |
241 | // add MCS in missing chambers if any (at most 2 chambers can be missing according to tracking criteria) | |
96ebe67e | 242 | currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId(); |
ea94c18b | 243 | while (currentChamber < expectedChamber) { |
244 | // extrapolation to the missing chamber (update the propagator) | |
96ebe67e | 245 | AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber), |
3304fa09 | 246 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); |
ea94c18b | 247 | // add MCS effect |
96ebe67e | 248 | AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.); |
ea94c18b | 249 | expectedChamber--; |
250 | } | |
251 | ||
96ebe67e | 252 | // extrapolation to the plane of the cluster attached to the current trackParamAtCluster (update the propagator) |
253 | AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ(), | |
3304fa09 | 254 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); |
ea94c18b | 255 | |
3304fa09 | 256 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) { |
ea94c18b | 257 | // save extrapolated parameters for smoother |
96ebe67e | 258 | trackParamAtCluster->SetExtrapParameters(trackParamAtCluster->GetParameters()); |
ea94c18b | 259 | |
260 | // save extrapolated covariance matrix for smoother | |
96ebe67e | 261 | trackParamAtCluster->SetExtrapCovariances(trackParamAtCluster->GetCovariances()); |
ea94c18b | 262 | } |
263 | ||
96ebe67e | 264 | // Compute new track parameters including "clusterCh2" using kalman filter |
265 | addChi2TrackAtCluster = RunKalmanFilter(*trackParamAtCluster); | |
ea94c18b | 266 | |
267 | // Update the track chi2 | |
96ebe67e | 268 | trackCandidate.SetGlobalChi2(trackCandidate.GetGlobalChi2() + addChi2TrackAtCluster); |
269 | trackParamAtCluster->SetTrackChi2(trackCandidate.GetGlobalChi2()); | |
ea94c18b | 270 | |
96ebe67e | 271 | // prepare next step |
272 | expectedChamber = currentChamber - 1; | |
273 | startingTrackParam = trackParamAtCluster; | |
274 | trackParamAtCluster = (AliMUONTrackParam*) (trackCandidate.GetTrackParamAtCluster()->Before(startingTrackParam)); | |
ea94c18b | 275 | } |
276 | ||
277 | // Printout for debuging | |
278 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 279 | cout << "RetracePartialTrack: track chi2 after re-tracking: " << trackCandidate.GetGlobalChi2() << endl; |
ea94c18b | 280 | } |
281 | ||
282 | } | |
8cc77df0 | 283 | |
ea94c18b | 284 | //__________________________________________________________________________ |
1fef78c8 | 285 | void AliMUONTrackReconstructorK::FollowTracks(AliMUONVClusterStore& clusterStore) |
ea94c18b | 286 | { |
287 | /// Follow tracks in stations(1..) 3, 2 and 1 | |
288 | AliDebug(1,"Enter FollowTracks"); | |
289 | ||
290 | AliMUONTrack *track; | |
291 | Int_t currentNRecTracks; | |
96ebe67e | 292 | Bool_t clusterFound; |
ea94c18b | 293 | |
294 | for (Int_t station = 2; station >= 0; station--) { | |
295 | ||
296 | // Save the actual number of reconstructed track in case of | |
297 | // tracks are added or suppressed during the tracking procedure | |
298 | // !! Do not compress fRecTracksPtr until the end of the loop over tracks !! | |
299 | currentNRecTracks = fNRecTracks; | |
300 | ||
301 | for (Int_t iRecTrack = 0; iRecTrack <currentNRecTracks; iRecTrack++) { | |
302 | AliDebug(1,Form("FollowTracks: track candidate(1..) %d", iRecTrack+1)); | |
303 | ||
304 | track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack); | |
305 | ||
306 | // Printout for debuging | |
307 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) { | |
96ebe67e | 308 | cout<<endl<<"Track parameter covariances at first cluster:"<<endl; |
309 | ((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->First()))->GetCovariances().Print(); | |
ea94c18b | 310 | } |
311 | ||
96ebe67e | 312 | // Look for compatible cluster(s) in station(0..) "station" |
313 | clusterFound = FollowTrackInStation(*track, clusterStore, station); | |
ea94c18b | 314 | |
315 | // Try to recover track if required | |
96ebe67e | 316 | if (!clusterFound && AliMUONReconstructor::GetRecoParam()->RecoverTracks()) |
317 | clusterFound = RecoverTrack(*track, clusterStore, station); | |
ea94c18b | 318 | |
96ebe67e | 319 | // remove track if no cluster found |
320 | if (!clusterFound) { | |
ea94c18b | 321 | fRecTracksPtr->Remove(track); |
322 | fNRecTracks--; | |
8cc77df0 | 323 | } |
ea94c18b | 324 | |
8cc77df0 | 325 | } |
ea94c18b | 326 | |
327 | fRecTracksPtr->Compress(); // this is essential before checking tracks | |
328 | ||
ea94c18b | 329 | // Keep only the best tracks if required |
3304fa09 | 330 | if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks(); |
ea94c18b | 331 | |
332 | } | |
333 | ||
334 | } | |
b0e4c598 | 335 | |
ea94c18b | 336 | //__________________________________________________________________________ |
1fef78c8 | 337 | Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation) |
ea94c18b | 338 | { |
96ebe67e | 339 | /// Follow trackCandidate in station(0..) nextStation and search for compatible cluster(s) |
ea94c18b | 340 | /// Keep all possibilities or only the best one(s) according to the flag fgkTrackAllTracks: |
341 | /// kTRUE: duplicate "trackCandidate" if there are several possibilities and add the new tracks at the end of | |
342 | /// fRecTracksPtr to avoid conficts with other track candidates at this current stage of the tracking procedure. | |
343 | /// Remove the obsolete "trackCandidate" at the end. | |
96ebe67e | 344 | /// kFALSE: add only the best cluster(s) to the "trackCandidate". Try to add a couple of clusters in priority. |
345 | /// return kTRUE if new cluster(s) have been found (otherwise return kFALSE) | |
ea94c18b | 346 | AliDebug(1,Form("Enter FollowTrackInStation(1..) %d", nextStation+1)); |
347 | ||
348 | // Order the chamber according to the propagation direction (tracking starts with chamber 2): | |
349 | // - nextStation == station(1...) 5 => forward propagation | |
350 | // - nextStation < station(1...) 5 => backward propagation | |
351 | Int_t ch1, ch2; | |
352 | if (nextStation==4) { | |
353 | ch1 = 2*nextStation+1; | |
354 | ch2 = 2*nextStation; | |
355 | } else { | |
356 | ch1 = 2*nextStation; | |
357 | ch2 = 2*nextStation+1; | |
358 | } | |
359 | ||
96ebe67e | 360 | Double_t chi2OfCluster; |
361 | Double_t maxChi2OfCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * | |
362 | AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2 | |
363 | Double_t addChi2TrackAtCluster1; | |
364 | Double_t addChi2TrackAtCluster2; | |
365 | Double_t bestAddChi2TrackAtCluster1 = 1.e10; | |
366 | Double_t bestAddChi2TrackAtCluster2 = 1.e10; | |
367 | Bool_t foundOneCluster = kFALSE; | |
368 | Bool_t foundTwoClusters = kFALSE; | |
ea94c18b | 369 | AliMUONTrack *newTrack = 0x0; |
96ebe67e | 370 | AliMUONVCluster *clusterCh1, *clusterCh2; |
ea94c18b | 371 | AliMUONTrackParam extrapTrackParam; |
96ebe67e | 372 | AliMUONTrackParam extrapTrackParamAtCluster1; |
373 | AliMUONTrackParam extrapTrackParamAtCluster2; | |
374 | AliMUONTrackParam bestTrackParamAtCluster1; | |
375 | AliMUONTrackParam bestTrackParamAtCluster2; | |
376 | ||
377 | Int_t nClusters = clusterStore.GetSize(); | |
378 | Bool_t *clusterCh1Used = new Bool_t[nClusters]; | |
379 | for (Int_t i = 0; i < nClusters; i++) clusterCh1Used[i] = kFALSE; | |
380 | Int_t iCluster1; | |
381 | ||
019df241 | 382 | // Get track parameters |
96ebe67e | 383 | AliMUONTrackParam extrapTrackParamAtCh(*(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First()); |
ea94c18b | 384 | |
385 | // Add MCS effect | |
019df241 | 386 | AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.); |
ea94c18b | 387 | |
388 | // reset propagator for smoother | |
3304fa09 | 389 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator(); |
ea94c18b | 390 | |
391 | // Add MCS in the missing chamber if any (only 1 chamber can be missing according to tracking criteria) | |
96ebe67e | 392 | if (ch1 < ch2 && extrapTrackParamAtCh.GetClusterPtr()->GetChamberId() > ch2 + 1) { |
ea94c18b | 393 | // extrapolation to the missing chamber |
3304fa09 | 394 | AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch2 + 1), |
395 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
ea94c18b | 396 | // add MCS effect |
019df241 | 397 | AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.); |
ea94c18b | 398 | } |
399 | ||
400 | //Extrapolate trackCandidate to chamber "ch2" | |
3304fa09 | 401 | AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch2), |
402 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
ea94c18b | 403 | |
404 | // Printout for debuging | |
405 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) { | |
96ebe67e | 406 | cout<<endl<<"Track parameter covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl; |
019df241 | 407 | extrapTrackParamAtCh.GetCovariances().Print(); |
ea94c18b | 408 | } |
409 | ||
410 | // Printout for debuging | |
411 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 412 | cout << "FollowTrackInStation: look for clusters in chamber(1..): " << ch2+1 << endl; |
ea94c18b | 413 | } |
414 | ||
1fef78c8 | 415 | // Ask the clustering to reconstruct new clusters around the track position in the current station |
416 | // except for station 4 and 5 that are already entirely clusterized | |
417 | if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) { | |
418 | if (nextStation < 3) AskForNewClustersInStation(extrapTrackParamAtCh, clusterStore, nextStation); | |
419 | } | |
420 | ||
96ebe67e | 421 | // Create iterators to loop over clusters in both chambers |
422 | TIter nextInCh1(clusterStore.CreateChamberIterator(ch1,ch1)); | |
423 | TIter nextInCh2(clusterStore.CreateChamberIterator(ch2,ch2)); | |
424 | ||
425 | // look for candidates in chamber 2 | |
426 | while ( ( clusterCh2 = static_cast<AliMUONVCluster*>(nextInCh2()) ) ) { | |
ea94c18b | 427 | |
96ebe67e | 428 | // try to add the current cluster fast |
429 | if (!TryOneClusterFast(extrapTrackParamAtCh, clusterCh2)) continue; | |
019df241 | 430 | |
96ebe67e | 431 | // try to add the current cluster accuratly |
432 | chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh2, extrapTrackParamAtCluster2, | |
433 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
ea94c18b | 434 | |
96ebe67e | 435 | // if good chi2 then try to attach a cluster in the other chamber too |
436 | if (chi2OfCluster < maxChi2OfCluster) { | |
437 | Bool_t foundSecondCluster = kFALSE; | |
ea94c18b | 438 | |
439 | // Printout for debuging | |
440 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 441 | cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch2+1 |
442 | << " (Chi2 = " << chi2OfCluster << ")" << endl; | |
443 | cout << " look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl; | |
8cc77df0 | 444 | } |
ea94c18b | 445 | |
3304fa09 | 446 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) { |
ea94c18b | 447 | // save extrapolated parameters for smoother |
96ebe67e | 448 | extrapTrackParamAtCluster2.SetExtrapParameters(extrapTrackParamAtCluster2.GetParameters()); |
ea94c18b | 449 | |
450 | // save extrapolated covariance matrix for smoother | |
96ebe67e | 451 | extrapTrackParamAtCluster2.SetExtrapCovariances(extrapTrackParamAtCluster2.GetCovariances()); |
ea94c18b | 452 | } |
453 | ||
96ebe67e | 454 | // Compute new track parameters including "clusterCh2" using kalman filter |
455 | addChi2TrackAtCluster2 = RunKalmanFilter(extrapTrackParamAtCluster2); | |
ea94c18b | 456 | |
457 | // copy new track parameters for next step | |
96ebe67e | 458 | extrapTrackParam = extrapTrackParamAtCluster2; |
ea94c18b | 459 | |
460 | // add MCS effect | |
461 | AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.); | |
462 | ||
463 | // reset propagator for smoother | |
3304fa09 | 464 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) extrapTrackParam.ResetPropagator(); |
ea94c18b | 465 | |
019df241 | 466 | //Extrapolate track parameters to chamber "ch1" |
3304fa09 | 467 | AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(ch1), |
468 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
019df241 | 469 | |
96ebe67e | 470 | // reset cluster iterator of chamber 1 |
471 | nextInCh1.Reset(); | |
472 | iCluster1 = -1; | |
473 | ||
474 | // look for second candidates in chamber 1 | |
475 | while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) { | |
476 | iCluster1++; | |
ea94c18b | 477 | |
96ebe67e | 478 | // try to add the current cluster fast |
479 | if (!TryOneClusterFast(extrapTrackParam, clusterCh1)) continue; | |
019df241 | 480 | |
96ebe67e | 481 | // try to add the current cluster accuratly |
482 | chi2OfCluster = TryOneCluster(extrapTrackParam, clusterCh1, extrapTrackParamAtCluster1, | |
3304fa09 | 483 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); |
019df241 | 484 | |
96ebe67e | 485 | // if good chi2 then consider to add the 2 clusters to the "trackCandidate" |
486 | if (chi2OfCluster < maxChi2OfCluster) { | |
487 | foundSecondCluster = kTRUE; | |
488 | foundTwoClusters = kTRUE; | |
ea94c18b | 489 | |
490 | // Printout for debuging | |
491 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 492 | cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1 |
493 | << " (Chi2 = " << chi2OfCluster << ")" << endl; | |
ea94c18b | 494 | } |
019df241 | 495 | |
3304fa09 | 496 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) { |
ea94c18b | 497 | // save extrapolated parameters for smoother |
96ebe67e | 498 | extrapTrackParamAtCluster1.SetExtrapParameters(extrapTrackParamAtCluster1.GetParameters()); |
ea94c18b | 499 | |
500 | // save extrapolated covariance matrix for smoother | |
96ebe67e | 501 | extrapTrackParamAtCluster1.SetExtrapCovariances(extrapTrackParamAtCluster1.GetCovariances()); |
ea94c18b | 502 | } |
503 | ||
96ebe67e | 504 | // Compute new track parameters including "clusterCh1" using kalman filter |
505 | addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1); | |
ea94c18b | 506 | |
3304fa09 | 507 | if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) { |
96ebe67e | 508 | // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new clusters |
ea94c18b | 509 | newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate); |
96ebe67e | 510 | UpdateTrack(*newTrack,extrapTrackParamAtCluster1,extrapTrackParamAtCluster2,addChi2TrackAtCluster1,addChi2TrackAtCluster2); |
ea94c18b | 511 | fNRecTracks++; |
512 | ||
513 | // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station | |
514 | // (going in the right direction) | |
515 | if (nextStation == 4) RetraceTrack(*newTrack,kTRUE); | |
516 | ||
96ebe67e | 517 | // Tag clusterCh1 as used |
518 | clusterCh1Used[iCluster1] = kTRUE; | |
ea94c18b | 519 | |
520 | // Printout for debuging | |
521 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 522 | cout << "FollowTrackInStation: added two clusters in station(1..): " << nextStation+1 << endl; |
ea94c18b | 523 | if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump(); |
524 | } | |
525 | ||
96ebe67e | 526 | } else if (addChi2TrackAtCluster1+addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1+bestAddChi2TrackAtCluster2) { |
527 | // keep track of the best couple of clusters | |
528 | bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster1; | |
529 | bestAddChi2TrackAtCluster2 = addChi2TrackAtCluster2; | |
530 | bestTrackParamAtCluster1 = extrapTrackParamAtCluster1; | |
531 | bestTrackParamAtCluster2 = extrapTrackParamAtCluster2; | |
ea94c18b | 532 | } |
533 | ||
b0e4c598 | 534 | } |
ea94c18b | 535 | |
8cc77df0 | 536 | } |
ea94c18b | 537 | |
96ebe67e | 538 | // if no clusterCh1 found then consider to add clusterCh2 only |
539 | if (!foundSecondCluster) { | |
540 | foundOneCluster = kTRUE; | |
ea94c18b | 541 | |
3304fa09 | 542 | if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) { |
96ebe67e | 543 | // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster |
ea94c18b | 544 | newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate); |
96ebe67e | 545 | UpdateTrack(*newTrack,extrapTrackParamAtCluster2,addChi2TrackAtCluster2); |
ea94c18b | 546 | fNRecTracks++; |
547 | ||
548 | // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station | |
549 | // (going in the right direction) | |
550 | if (nextStation == 4) RetraceTrack(*newTrack,kTRUE); | |
551 | ||
552 | // Printout for debuging | |
553 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 554 | cout << "FollowTrackInStation: added one cluster in chamber(1..): " << ch2+1 << endl; |
ea94c18b | 555 | if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump(); |
556 | } | |
557 | ||
96ebe67e | 558 | } else if (!foundTwoClusters && addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1) { |
559 | // keep track of the best single cluster except if a couple of clusters has already been found | |
560 | bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster2; | |
561 | bestTrackParamAtCluster1 = extrapTrackParamAtCluster2; | |
ea94c18b | 562 | } |
563 | ||
564 | } | |
565 | ||
8cc77df0 | 566 | } |
ea94c18b | 567 | |
568 | } | |
569 | ||
570 | // look for candidates in chamber 1 not already attached to a track | |
96ebe67e | 571 | // if we want to keep all possible tracks or if no good couple of clusters has been found |
572 | if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() || !foundTwoClusters) { | |
ea94c18b | 573 | |
574 | // Printout for debuging | |
575 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 576 | cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl; |
8cc77df0 | 577 | } |
ea94c18b | 578 | |
579 | // add MCS effect for next step | |
019df241 | 580 | AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.); |
581 | ||
582 | //Extrapolate trackCandidate to chamber "ch1" | |
3304fa09 | 583 | AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch1), |
584 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
019df241 | 585 | |
96ebe67e | 586 | // reset cluster iterator of chamber 1 |
587 | nextInCh1.Reset(); | |
588 | iCluster1 = -1; | |
589 | ||
590 | // look for second candidates in chamber 1 | |
591 | while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) { | |
592 | iCluster1++; | |
ea94c18b | 593 | |
96ebe67e | 594 | if (clusterCh1Used[iCluster1]) continue; // Skip clusters already used |
ea94c18b | 595 | |
96ebe67e | 596 | // try to add the current cluster fast |
597 | if (!TryOneClusterFast(extrapTrackParamAtCh, clusterCh1)) continue; | |
019df241 | 598 | |
96ebe67e | 599 | // try to add the current cluster accuratly |
600 | chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh1, extrapTrackParamAtCluster1, | |
601 | AliMUONReconstructor::GetRecoParam()->UseSmoother()); | |
019df241 | 602 | |
96ebe67e | 603 | // if good chi2 then consider to add clusterCh1 |
604 | // We do not try to attach a cluster in the other chamber too since it has already been done above | |
605 | if (chi2OfCluster < maxChi2OfCluster) { | |
606 | foundOneCluster = kTRUE; | |
ea94c18b | 607 | |
608 | // Printout for debuging | |
609 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 610 | cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1 |
611 | << " (Chi2 = " << chi2OfCluster << ")" << endl; | |
ea94c18b | 612 | } |
019df241 | 613 | |
3304fa09 | 614 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) { |
ea94c18b | 615 | // save extrapolated parameters for smoother |
96ebe67e | 616 | extrapTrackParamAtCluster1.SetExtrapParameters(extrapTrackParamAtCluster1.GetParameters()); |
ea94c18b | 617 | |
618 | // save extrapolated covariance matrix for smoother | |
96ebe67e | 619 | extrapTrackParamAtCluster1.SetExtrapCovariances(extrapTrackParamAtCluster1.GetCovariances()); |
ea94c18b | 620 | } |
621 | ||
96ebe67e | 622 | // Compute new track parameters including "clusterCh1" using kalman filter |
623 | addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1); | |
ea94c18b | 624 | |
3304fa09 | 625 | if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) { |
96ebe67e | 626 | // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster |
ea94c18b | 627 | newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate); |
96ebe67e | 628 | UpdateTrack(*newTrack,extrapTrackParamAtCluster1,addChi2TrackAtCluster1); |
ea94c18b | 629 | fNRecTracks++; |
630 | ||
631 | // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station | |
632 | // (going in the right direction) | |
633 | if (nextStation == 4) RetraceTrack(*newTrack,kTRUE); | |
634 | ||
635 | // Printout for debuging | |
636 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 637 | cout << "FollowTrackInStation: added one cluster in chamber(1..): " << ch1+1 << endl; |
ea94c18b | 638 | if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump(); |
639 | } | |
640 | ||
96ebe67e | 641 | } else if (addChi2TrackAtCluster1 < bestAddChi2TrackAtCluster1) { |
642 | // keep track of the best single cluster except if a couple of clusters has already been found | |
643 | bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster1; | |
644 | bestTrackParamAtCluster1 = extrapTrackParamAtCluster1; | |
ea94c18b | 645 | } |
646 | ||
647 | } | |
648 | ||
8cc77df0 | 649 | } |
ea94c18b | 650 | |
651 | } | |
652 | ||
653 | // fill out the best track if required else clean up the fRecTracksPtr array | |
3304fa09 | 654 | if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) { |
96ebe67e | 655 | if (foundTwoClusters) { |
656 | UpdateTrack(trackCandidate,bestTrackParamAtCluster1,bestTrackParamAtCluster2,bestAddChi2TrackAtCluster1,bestAddChi2TrackAtCluster2); | |
ea94c18b | 657 | |
658 | // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station | |
659 | // (going in the right direction) | |
660 | if (nextStation == 4) RetraceTrack(trackCandidate,kTRUE); | |
8cc77df0 | 661 | |
ea94c18b | 662 | // Printout for debuging |
663 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 664 | cout << "FollowTrackInStation: added the two best clusters in station(1..): " << nextStation+1 << endl; |
ea94c18b | 665 | if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump(); |
666 | } | |
667 | ||
96ebe67e | 668 | } else if (foundOneCluster) { |
669 | UpdateTrack(trackCandidate,bestTrackParamAtCluster1,bestAddChi2TrackAtCluster1); | |
ea94c18b | 670 | |
671 | // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station | |
672 | // (going in the right direction) | |
673 | if (nextStation == 4) RetraceTrack(trackCandidate,kTRUE); | |
674 | ||
675 | // Printout for debuging | |
676 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
96ebe67e | 677 | cout << "FollowTrackInStation: added the best cluster in chamber(1..): " << bestTrackParamAtCluster1.GetClusterPtr()->GetChamberId()+1 << endl; |
ea94c18b | 678 | if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump(); |
679 | } | |
680 | ||
17773e2e | 681 | } else { |
96ebe67e | 682 | delete [] clusterCh1Used; |
17773e2e | 683 | return kFALSE; |
684 | } | |
96ebe67e | 685 | } else if (foundOneCluster || foundTwoClusters) { |
ea94c18b | 686 | |
687 | // remove obsolete track | |
688 | fRecTracksPtr->Remove(&trackCandidate); | |
689 | fNRecTracks--; | |
690 | ||
17773e2e | 691 | } else { |
96ebe67e | 692 | delete [] clusterCh1Used; |
17773e2e | 693 | return kFALSE; |
694 | } | |
96ebe67e | 695 | delete [] clusterCh1Used; |
ea94c18b | 696 | return kTRUE; |
697 | ||
698 | } | |
8cc77df0 | 699 | |
ea94c18b | 700 | //__________________________________________________________________________ |
96ebe67e | 701 | Double_t AliMUONTrackReconstructorK::RunKalmanFilter(AliMUONTrackParam &trackParamAtCluster) |
ea94c18b | 702 | { |
96ebe67e | 703 | /// Compute new track parameters and their covariances including new cluster using kalman filter |
ea94c18b | 704 | /// return the additional track chi2 |
705 | AliDebug(1,"Enter RunKalmanFilter"); | |
706 | ||
707 | // Get actual track parameters (p) | |
96ebe67e | 708 | TMatrixD param(trackParamAtCluster.GetParameters()); |
ea94c18b | 709 | |
96ebe67e | 710 | // Get new cluster parameters (m) |
711 | AliMUONVCluster *cluster = trackParamAtCluster.GetClusterPtr(); | |
712 | TMatrixD clusterParam(5,1); | |
713 | clusterParam.Zero(); | |
714 | clusterParam(0,0) = cluster->GetX(); | |
715 | clusterParam(2,0) = cluster->GetY(); | |
ea94c18b | 716 | |
717 | // Compute the actual parameter weight (W) | |
96ebe67e | 718 | TMatrixD paramWeight(trackParamAtCluster.GetCovariances()); |
ea94c18b | 719 | if (paramWeight.Determinant() != 0) { |
720 | paramWeight.Invert(); | |
721 | } else { | |
722 | AliWarning(" Determinant = 0"); | |
723 | return 1.e10; | |
8cc77df0 | 724 | } |
ea94c18b | 725 | |
96ebe67e | 726 | // Compute the new cluster weight (U) |
727 | TMatrixD clusterWeight(5,5); | |
728 | clusterWeight.Zero(); | |
729 | clusterWeight(0,0) = 1. / cluster->GetErrX2(); | |
730 | clusterWeight(2,2) = 1. / cluster->GetErrY2(); | |
8cc77df0 | 731 | |
ea94c18b | 732 | // Compute the new parameters covariance matrix ( (W+U)^-1 ) |
96ebe67e | 733 | TMatrixD newParamCov(paramWeight,TMatrixD::kPlus,clusterWeight); |
ea94c18b | 734 | if (newParamCov.Determinant() != 0) { |
735 | newParamCov.Invert(); | |
736 | } else { | |
737 | AliWarning(" Determinant = 0"); | |
738 | return 1.e10; | |
739 | } | |
740 | ||
741 | // Save the new parameters covariance matrix | |
96ebe67e | 742 | trackParamAtCluster.SetCovariances(newParamCov); |
ea94c18b | 743 | |
744 | // Compute the new parameters (p' = ((W+U)^-1)U(m-p) + p) | |
96ebe67e | 745 | TMatrixD tmp(clusterParam,TMatrixD::kMinus,param); |
746 | TMatrixD tmp2(clusterWeight,TMatrixD::kMult,tmp); // U(m-p) | |
ea94c18b | 747 | TMatrixD newParam(newParamCov,TMatrixD::kMult,tmp2); // ((W+U)^-1)U(m-p) |
748 | newParam += param; // ((W+U)^-1)U(m-p) + p | |
749 | ||
750 | // Save the new parameters | |
96ebe67e | 751 | trackParamAtCluster.SetParameters(newParam); |
ea94c18b | 752 | |
753 | // Compute the additional chi2 (= ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m)) | |
754 | tmp = newParam; // p' | |
755 | tmp -= param; // (p'-p) | |
756 | TMatrixD tmp3(paramWeight,TMatrixD::kMult,tmp); // W(p'-p) | |
757 | TMatrixD addChi2Track(tmp,TMatrixD::kTransposeMult,tmp3); // ((p'-p)^-1)W(p'-p) | |
758 | tmp = newParam; // p' | |
96ebe67e | 759 | tmp -= clusterParam; // (p'-m) |
760 | TMatrixD tmp4(clusterWeight,TMatrixD::kMult,tmp); // U(p'-m) | |
ea94c18b | 761 | addChi2Track += TMatrixD(tmp,TMatrixD::kTransposeMult,tmp4); // ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m) |
762 | ||
763 | return addChi2Track(0,0); | |
764 | ||
8cc77df0 | 765 | } |
766 | ||
ea94c18b | 767 | //__________________________________________________________________________ |
96ebe67e | 768 | void AliMUONTrackReconstructorK::UpdateTrack(AliMUONTrack &track, AliMUONTrackParam &trackParamAtCluster, Double_t addChi2) |
8cc77df0 | 769 | { |
96ebe67e | 770 | /// Add 1 cluster to the track candidate |
ea94c18b | 771 | /// Update chi2 of the track |
772 | ||
96ebe67e | 773 | // Flag cluster as being not removable |
774 | trackParamAtCluster.SetRemovable(kFALSE); | |
775 | trackParamAtCluster.SetLocalChi2(0.); // --> Local chi2 not used | |
5f4ceff2 | 776 | |
96ebe67e | 777 | // Update the track chi2 into trackParamAtCluster |
778 | trackParamAtCluster.SetTrackChi2(track.GetGlobalChi2() + addChi2); | |
ea94c18b | 779 | |
780 | // Update the chi2 of the new track | |
96ebe67e | 781 | track.SetGlobalChi2(trackParamAtCluster.GetTrackChi2()); |
ea94c18b | 782 | |
96ebe67e | 783 | // Update array of TrackParamAtCluster |
784 | track.AddTrackParamAtCluster(trackParamAtCluster,*(trackParamAtCluster.GetClusterPtr())); | |
785 | track.GetTrackParamAtCluster()->Sort(); | |
ea94c18b | 786 | |
787 | } | |
8cc77df0 | 788 | |
ea94c18b | 789 | //__________________________________________________________________________ |
96ebe67e | 790 | void AliMUONTrackReconstructorK::UpdateTrack(AliMUONTrack &track, AliMUONTrackParam &trackParamAtCluster1, AliMUONTrackParam &trackParamAtCluster2, |
791 | Double_t addChi2AtCluster1, Double_t addChi2AtCluster2) | |
ea94c18b | 792 | { |
96ebe67e | 793 | /// Add 2 clusters to the track candidate (order is important) |
ea94c18b | 794 | /// Update track and local chi2 |
795 | ||
96ebe67e | 796 | // Update local chi2 at first cluster |
797 | AliMUONVCluster* cluster1 = trackParamAtCluster1.GetClusterPtr(); | |
798 | Double_t deltaX = trackParamAtCluster1.GetNonBendingCoor() - cluster1->GetX(); | |
799 | Double_t deltaY = trackParamAtCluster1.GetBendingCoor() - cluster1->GetY(); | |
800 | Double_t localChi2AtCluster1 = deltaX*deltaX / cluster1->GetErrX2() + | |
801 | deltaY*deltaY / cluster1->GetErrY2(); | |
802 | trackParamAtCluster1.SetLocalChi2(localChi2AtCluster1); | |
ea94c18b | 803 | |
96ebe67e | 804 | // Flag first cluster as being removable |
805 | trackParamAtCluster1.SetRemovable(kTRUE); | |
ea94c18b | 806 | |
96ebe67e | 807 | // Update local chi2 at second cluster |
808 | AliMUONVCluster* cluster2 = trackParamAtCluster2.GetClusterPtr(); | |
809 | AliMUONTrackParam extrapTrackParamAtCluster2(trackParamAtCluster1); | |
810 | AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParamAtCluster2, trackParamAtCluster2.GetZ()); | |
811 | deltaX = extrapTrackParamAtCluster2.GetNonBendingCoor() - cluster2->GetX(); | |
812 | deltaY = extrapTrackParamAtCluster2.GetBendingCoor() - cluster2->GetY(); | |
813 | Double_t localChi2AtCluster2 = deltaX*deltaX / cluster2->GetErrX2() + | |
814 | deltaY*deltaY / cluster2->GetErrY2(); | |
815 | trackParamAtCluster2.SetLocalChi2(localChi2AtCluster2); | |
ea94c18b | 816 | |
96ebe67e | 817 | // Flag second cluster as being removable |
818 | trackParamAtCluster2.SetRemovable(kTRUE); | |
ea94c18b | 819 | |
96ebe67e | 820 | // Update the track chi2 into trackParamAtCluster2 |
821 | trackParamAtCluster2.SetTrackChi2(track.GetGlobalChi2() + addChi2AtCluster2); | |
ea94c18b | 822 | |
96ebe67e | 823 | // Update the track chi2 into trackParamAtCluster1 |
824 | trackParamAtCluster1.SetTrackChi2(trackParamAtCluster2.GetTrackChi2() + addChi2AtCluster1); | |
ea94c18b | 825 | |
826 | // Update the chi2 of the new track | |
96ebe67e | 827 | track.SetGlobalChi2(trackParamAtCluster1.GetTrackChi2()); |
ea94c18b | 828 | |
96ebe67e | 829 | // Update array of trackParamAtCluster |
830 | track.AddTrackParamAtCluster(trackParamAtCluster1,*cluster1); | |
831 | track.AddTrackParamAtCluster(trackParamAtCluster2,*cluster2); | |
832 | track.GetTrackParamAtCluster()->Sort(); | |
ea94c18b | 833 | |
834 | } | |
8cc77df0 | 835 | |
ea94c18b | 836 | //__________________________________________________________________________ |
1fef78c8 | 837 | Bool_t AliMUONTrackReconstructorK::RecoverTrack(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation) |
ea94c18b | 838 | { |
839 | /// Try to recover the track candidate in the next station | |
96ebe67e | 840 | /// by removing the worst of the two clusters attached in the current station |
ea94c18b | 841 | /// Return kTRUE if recovering succeeds |
842 | AliDebug(1,"Enter RecoverTrack"); | |
843 | ||
96ebe67e | 844 | // Do not try to recover track until we have attached cluster(s) on station(1..) 3 |
ea94c18b | 845 | if (nextStation > 1) return kFALSE; |
846 | ||
96ebe67e | 847 | Int_t worstClusterNumber = -1; |
848 | Double_t localChi2, worstLocalChi2 = 0.; | |
ea94c18b | 849 | |
96ebe67e | 850 | // Look for the cluster to remove |
851 | for (Int_t clusterNumber = 0; clusterNumber < 2; clusterNumber++) { | |
852 | AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(clusterNumber); | |
ea94c18b | 853 | |
96ebe67e | 854 | // check if current cluster is removable |
855 | if (!trackParamAtCluster->IsRemovable()) return kFALSE; | |
ea94c18b | 856 | |
96ebe67e | 857 | // Pick up cluster with the worst chi2 |
858 | localChi2 = trackParamAtCluster->GetLocalChi2(); | |
859 | if (localChi2 > worstLocalChi2) { | |
860 | worstLocalChi2 = localChi2; | |
861 | worstClusterNumber = clusterNumber; | |
8cc77df0 | 862 | } |
ea94c18b | 863 | } |
864 | ||
96ebe67e | 865 | // Reset best cluster as being NOT removable |
866 | ((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt((worstClusterNumber+1)%2))->SetRemovable(kFALSE); | |
ea94c18b | 867 | |
96ebe67e | 868 | // Remove the worst cluster |
869 | trackCandidate.RemoveTrackParamAtCluster((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(worstClusterNumber)); | |
ea94c18b | 870 | |
96ebe67e | 871 | // Re-calculate track parameters at the (new) first cluster |
872 | RetracePartialTrack(trackCandidate,(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(1)); | |
ea94c18b | 873 | |
96ebe67e | 874 | // Look for new cluster(s) in next station |
875 | return FollowTrackInStation(trackCandidate, clusterStore, nextStation); | |
ea94c18b | 876 | |
8cc77df0 | 877 | } |
878 | ||
879 | //__________________________________________________________________________ | |
ea94c18b | 880 | Bool_t AliMUONTrackReconstructorK::RunSmoother(AliMUONTrack &track) |
8cc77df0 | 881 | { |
ea94c18b | 882 | /// Compute new track parameters and their covariances using smoother |
3304fa09 | 883 | AliDebug(1,"Enter UseSmoother"); |
ea94c18b | 884 | |
96ebe67e | 885 | AliMUONTrackParam *previousTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->First(); |
ea94c18b | 886 | |
96ebe67e | 887 | // Smoothed parameters and covariances at first cluster = filtered parameters and covariances |
ea94c18b | 888 | previousTrackParam->SetSmoothParameters(previousTrackParam->GetParameters()); |
889 | previousTrackParam->SetSmoothCovariances(previousTrackParam->GetCovariances()); | |
890 | ||
96ebe67e | 891 | // Compute local chi2 at first cluster |
892 | AliMUONVCluster *cluster = previousTrackParam->GetClusterPtr(); | |
893 | Double_t dX = cluster->GetX() - previousTrackParam->GetNonBendingCoor(); | |
894 | Double_t dY = cluster->GetY() - previousTrackParam->GetBendingCoor(); | |
895 | Double_t localChi2 = dX * dX / cluster->GetErrX2() + dY * dY / cluster->GetErrY2(); | |
ea94c18b | 896 | |
96ebe67e | 897 | // Save local chi2 at first cluster |
ea94c18b | 898 | previousTrackParam->SetLocalChi2(localChi2); |
899 | ||
96ebe67e | 900 | AliMUONTrackParam *currentTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(previousTrackParam); |
ea94c18b | 901 | while (currentTrackParam) { |
902 | ||
903 | // Get variables | |
904 | const TMatrixD &extrapParameters = previousTrackParam->GetExtrapParameters(); // X(k+1 k) | |
905 | const TMatrixD &filteredParameters = currentTrackParam->GetParameters(); // X(k k) | |
906 | const TMatrixD &previousSmoothParameters = previousTrackParam->GetSmoothParameters(); // X(k+1 n) | |
907 | const TMatrixD &propagator = previousTrackParam->GetPropagator(); // F(k) | |
908 | const TMatrixD &extrapCovariances = previousTrackParam->GetExtrapCovariances(); // C(k+1 k) | |
909 | const TMatrixD &filteredCovariances = currentTrackParam->GetCovariances(); // C(k k) | |
910 | const TMatrixD &previousSmoothCovariances = previousTrackParam->GetSmoothCovariances(); // C(k+1 n) | |
911 | ||
912 | // Compute smoother gain: A(k) = C(kk) * F(f)^t * (C(k+1 k))^-1 | |
913 | TMatrixD extrapWeight(extrapCovariances); | |
914 | if (extrapWeight.Determinant() != 0) { | |
915 | extrapWeight.Invert(); // (C(k+1 k))^-1 | |
916 | } else { | |
917 | AliWarning(" Determinant = 0"); | |
918 | return kFALSE; | |
919 | } | |
920 | TMatrixD smootherGain(filteredCovariances,TMatrixD::kMultTranspose,propagator); // C(kk) * F(f)^t | |
921 | smootherGain *= extrapWeight; // C(kk) * F(f)^t * (C(k+1 k))^-1 | |
922 | ||
923 | // Compute smoothed parameters: X(k n) = X(k k) + A(k) * (X(k+1 n) - X(k+1 k)) | |
924 | TMatrixD tmpParam(previousSmoothParameters,TMatrixD::kMinus,extrapParameters); // X(k+1 n) - X(k+1 k) | |
925 | TMatrixD smoothParameters(smootherGain,TMatrixD::kMult,tmpParam); // A(k) * (X(k+1 n) - X(k+1 k)) | |
926 | smoothParameters += filteredParameters; // X(k k) + A(k) * (X(k+1 n) - X(k+1 k)) | |
927 | ||
928 | // Save smoothed parameters | |
929 | currentTrackParam->SetSmoothParameters(smoothParameters); | |
930 | ||
931 | // Compute smoothed covariances: C(k n) = C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t | |
932 | TMatrixD tmpCov(previousSmoothCovariances,TMatrixD::kMinus,extrapCovariances); // C(k+1 n) - C(k+1 k) | |
933 | TMatrixD tmpCov2(tmpCov,TMatrixD::kMultTranspose,smootherGain); // (C(k+1 n) - C(k+1 k)) * (A(k))^t | |
934 | TMatrixD smoothCovariances(smootherGain,TMatrixD::kMult,tmpCov2); // A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t | |
935 | smoothCovariances += filteredCovariances; // C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t | |
936 | ||
937 | // Save smoothed covariances | |
938 | currentTrackParam->SetSmoothCovariances(smoothCovariances); | |
939 | ||
96ebe67e | 940 | // Compute smoothed residual: r(k n) = cluster - X(k n) |
941 | cluster = currentTrackParam->GetClusterPtr(); | |
ea94c18b | 942 | TMatrixD smoothResidual(2,1); |
943 | smoothResidual.Zero(); | |
96ebe67e | 944 | smoothResidual(0,0) = cluster->GetX() - smoothParameters(0,0); |
945 | smoothResidual(1,0) = cluster->GetY() - smoothParameters(2,0); | |
ea94c18b | 946 | |
96ebe67e | 947 | // Compute weight of smoothed residual: W(k n) = (clusterCov - C(k n))^-1 |
ea94c18b | 948 | TMatrixD smoothResidualWeight(2,2); |
96ebe67e | 949 | smoothResidualWeight(0,0) = cluster->GetErrX2() - smoothCovariances(0,0); |
ea94c18b | 950 | smoothResidualWeight(0,1) = - smoothCovariances(0,2); |
951 | smoothResidualWeight(1,0) = - smoothCovariances(2,0); | |
96ebe67e | 952 | smoothResidualWeight(1,1) = cluster->GetErrY2() - smoothCovariances(2,2); |
ea94c18b | 953 | if (smoothResidualWeight.Determinant() != 0) { |
954 | smoothResidualWeight.Invert(); | |
955 | } else { | |
956 | AliWarning(" Determinant = 0"); | |
957 | return kFALSE; | |
958 | } | |
959 | ||
960 | // Compute local chi2 = (r(k n))^t * W(k n) * r(k n) | |
961 | TMatrixD tmpChi2(smoothResidual,TMatrixD::kTransposeMult,smoothResidualWeight); // (r(k n))^t * W(k n) | |
962 | TMatrixD localChi2(tmpChi2,TMatrixD::kMult,smoothResidual); // (r(k n))^t * W(k n) * r(k n) | |
963 | ||
964 | // Save local chi2 | |
965 | currentTrackParam->SetLocalChi2(localChi2(0,0)); | |
966 | ||
967 | previousTrackParam = currentTrackParam; | |
96ebe67e | 968 | currentTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(previousTrackParam); |
ea94c18b | 969 | } |
970 | ||
971 | return kTRUE; | |
972 | ||
8cc77df0 | 973 | } |
974 | ||
8cc77df0 | 975 | //__________________________________________________________________________ |
96ebe67e | 976 | void AliMUONTrackReconstructorK::ComplementTracks(const AliMUONVClusterStore& clusterStore) |
b709ac13 | 977 | { |
978 | /// Complete tracks by adding missing clusters (if there is an overlap between | |
979 | /// two detection elements, the track may have two clusters in the same chamber) | |
980 | /// Recompute track parameters and covariances at each clusters | |
981 | AliDebug(1,"Enter ComplementTracks"); | |
982 | ||
983 | Int_t chamberId, detElemId; | |
96ebe67e | 984 | Double_t chi2OfCluster, addChi2TrackAtCluster, bestAddChi2TrackAtCluster; |
985 | Double_t maxChi2OfCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * | |
986 | AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2 | |
987 | Bool_t foundOneCluster, trackModified; | |
988 | AliMUONVCluster *cluster; | |
989 | AliMUONTrackParam *trackParam, *previousTrackParam, *nextTrackParam, trackParamAtCluster, bestTrackParamAtCluster; | |
b709ac13 | 990 | |
991 | // Remove double track to complete only "good" tracks | |
992 | RemoveDoubleTracks(); | |
993 | ||
994 | AliMUONTrack *track = (AliMUONTrack*) fRecTracksPtr->First(); | |
995 | while (track) { | |
996 | trackModified = kFALSE; | |
997 | ||
96ebe67e | 998 | trackParam = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->First(); |
b709ac13 | 999 | previousTrackParam = trackParam; |
1000 | while (trackParam) { | |
96ebe67e | 1001 | foundOneCluster = kFALSE; |
1002 | bestAddChi2TrackAtCluster = 1.e10; | |
1003 | chamberId = trackParam->GetClusterPtr()->GetChamberId(); | |
1004 | detElemId = trackParam->GetClusterPtr()->GetDetElemId(); | |
b709ac13 | 1005 | |
1006 | // prepare nextTrackParam before adding new cluster because of the sorting | |
96ebe67e | 1007 | nextTrackParam = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->After(trackParam); |
b709ac13 | 1008 | |
96ebe67e | 1009 | // Create iterators to loop over clusters in current chamber |
1010 | TIter nextInCh(clusterStore.CreateChamberIterator(chamberId,chamberId)); | |
b709ac13 | 1011 | |
1012 | // look for one second candidate in the same chamber | |
96ebe67e | 1013 | while ( ( cluster = static_cast<AliMUONVCluster*>(nextInCh()) ) ) { |
b709ac13 | 1014 | |
1015 | // look for a cluster in another detection element | |
96ebe67e | 1016 | if (cluster->GetDetElemId() == detElemId) continue; |
b709ac13 | 1017 | |
96ebe67e | 1018 | // try to add the current cluster fast |
1019 | if (!TryOneClusterFast(*trackParam, cluster)) continue; | |
b709ac13 | 1020 | |
96ebe67e | 1021 | // try to add the current cluster accurately |
b709ac13 | 1022 | // never use track parameters at last cluster because the covariance matrix is meaningless |
96ebe67e | 1023 | if (nextTrackParam) chi2OfCluster = TryOneCluster(*trackParam, cluster, trackParamAtCluster); |
1024 | else chi2OfCluster = TryOneCluster(*previousTrackParam, cluster, trackParamAtCluster); | |
b709ac13 | 1025 | |
1026 | // if good chi2 then consider to add this cluster to the track | |
96ebe67e | 1027 | if (chi2OfCluster < maxChi2OfCluster) { |
b709ac13 | 1028 | |
96ebe67e | 1029 | // Compute local track parameters including current cluster using kalman filter |
1030 | addChi2TrackAtCluster = RunKalmanFilter(trackParamAtCluster); | |
b709ac13 | 1031 | |
1032 | // keep track of the best cluster | |
96ebe67e | 1033 | if (addChi2TrackAtCluster < bestAddChi2TrackAtCluster) { |
1034 | bestAddChi2TrackAtCluster = addChi2TrackAtCluster; | |
1035 | bestTrackParamAtCluster = trackParamAtCluster; | |
1036 | foundOneCluster = kTRUE; | |
b709ac13 | 1037 | } |
1038 | ||
1039 | } | |
1040 | ||
1041 | } | |
1042 | ||
1043 | // add new cluster if any | |
96ebe67e | 1044 | if (foundOneCluster) { |
1045 | UpdateTrack(*track,bestTrackParamAtCluster,bestAddChi2TrackAtCluster); | |
1046 | bestTrackParamAtCluster.SetAloneInChamber(kFALSE); | |
b709ac13 | 1047 | trackParam->SetAloneInChamber(kFALSE); |
1048 | trackModified = kTRUE; | |
1049 | } | |
1050 | ||
1051 | previousTrackParam = trackParam; | |
1052 | trackParam = nextTrackParam; | |
1053 | } | |
1054 | ||
1055 | // re-compute track parameters using kalman filter if needed | |
1056 | if (trackModified) RetraceTrack(*track,kTRUE); | |
1057 | ||
1058 | track = (AliMUONTrack*) fRecTracksPtr->After(track); | |
1059 | } | |
1060 | ||
1061 | } | |
1062 | ||
1063 | //__________________________________________________________________________ | |
ea94c18b | 1064 | void AliMUONTrackReconstructorK::ImproveTracks() |
8cc77df0 | 1065 | { |
ea94c18b | 1066 | /// Improve tracks by removing clusters with local chi2 highter than the defined cut |
1067 | /// Recompute track parameters and covariances at the remaining clusters | |
1068 | AliDebug(1,"Enter ImproveTracks"); | |
1069 | ||
1070 | Double_t localChi2, worstLocalChi2; | |
b709ac13 | 1071 | Int_t worstChamber, previousChamber; |
1072 | AliMUONTrack *track, *nextTrack; | |
96ebe67e | 1073 | AliMUONTrackParam *trackParamAtCluster, *worstTrackParamAtCluster, *previousTrackParam, *nextTrackParam; |
ea94c18b | 1074 | Bool_t smoothed; |
3304fa09 | 1075 | Double_t sigmaCut2 = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForImprovement() * |
1076 | AliMUONReconstructor::GetRecoParam()->GetSigmaCutForImprovement(); | |
ea94c18b | 1077 | |
1078 | // Remove double track to improve only "good" tracks | |
1079 | RemoveDoubleTracks(); | |
1080 | ||
b709ac13 | 1081 | track = (AliMUONTrack*) fRecTracksPtr->First(); |
8cc77df0 | 1082 | while (track) { |
ea94c18b | 1083 | |
b709ac13 | 1084 | // prepare next track in case the actual track is suppressed |
1085 | nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track); | |
1086 | ||
ea94c18b | 1087 | while (!track->IsImproved()) { |
1088 | ||
1089 | // Run smoother if required | |
1090 | smoothed = kFALSE; | |
3304fa09 | 1091 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) smoothed = RunSmoother(*track); |
ea94c18b | 1092 | |
1093 | // Use standard procedure to compute local chi2 if smoother not required or not working | |
1094 | if (!smoothed) { | |
1095 | ||
1096 | // Update track parameters and covariances | |
96ebe67e | 1097 | track->UpdateCovTrackParamAtCluster(); |
ea94c18b | 1098 | |
96ebe67e | 1099 | // Compute local chi2 of each clusters |
ea94c18b | 1100 | track->ComputeLocalChi2(kTRUE); |
1101 | } | |
1102 | ||
96ebe67e | 1103 | // Look for the cluster to remove |
1104 | worstTrackParamAtCluster = NULL; | |
ea94c18b | 1105 | worstLocalChi2 = 0.; |
96ebe67e | 1106 | trackParamAtCluster = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->First(); |
1107 | while (trackParamAtCluster) { | |
ea94c18b | 1108 | |
9d2332ab | 1109 | // save parameters into smooth parameters in case of smoother did not work properly |
1110 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother() && !smoothed) { | |
1111 | trackParamAtCluster->SetSmoothParameters(trackParamAtCluster->GetParameters()); | |
1112 | trackParamAtCluster->SetSmoothCovariances(trackParamAtCluster->GetCovariances()); | |
1113 | } | |
1114 | ||
1115 | // Pick up cluster with the worst chi2 | |
96ebe67e | 1116 | localChi2 = trackParamAtCluster->GetLocalChi2(); |
ea94c18b | 1117 | if (localChi2 > worstLocalChi2) { |
1118 | worstLocalChi2 = localChi2; | |
96ebe67e | 1119 | worstTrackParamAtCluster = trackParamAtCluster; |
ea94c18b | 1120 | } |
1121 | ||
96ebe67e | 1122 | trackParamAtCluster = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->After(trackParamAtCluster); |
ea94c18b | 1123 | } |
1124 | ||
96ebe67e | 1125 | // Check if bad removable cluster found |
1126 | if (!worstTrackParamAtCluster) { | |
ea94c18b | 1127 | track->SetImproved(kTRUE); |
1128 | break; | |
1129 | } | |
1130 | ||
b709ac13 | 1131 | // Check whether the worst chi2 is under requirement or not |
3304fa09 | 1132 | if (worstLocalChi2 < 2. * sigmaCut2) { // 2 because 2 quantities in chi2 |
ea94c18b | 1133 | track->SetImproved(kTRUE); |
1134 | break; | |
1135 | } | |
1136 | ||
96ebe67e | 1137 | // if the worst cluster is not removable then remove the entire track |
1138 | if (!worstTrackParamAtCluster->IsRemovable() && worstTrackParamAtCluster->IsAloneInChamber()) { | |
b709ac13 | 1139 | fRecTracksPtr->Remove(track); |
1140 | fNRecTracks--; | |
ea94c18b | 1141 | break; |
1142 | } | |
1143 | ||
96ebe67e | 1144 | // Reset the second cluster in the same station as being not removable |
1145 | // or reset the second cluster in the same chamber as being alone | |
1146 | worstChamber = worstTrackParamAtCluster->GetClusterPtr()->GetChamberId(); | |
1147 | previousTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->Before(worstTrackParamAtCluster); | |
1148 | nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(worstTrackParamAtCluster); | |
1149 | if (worstTrackParamAtCluster->IsAloneInChamber()) { // Worst cluster removable and alone in chamber | |
b709ac13 | 1150 | |
1151 | if (worstChamber%2 == 0) { // Modify flags in next chamber | |
1152 | ||
1153 | nextTrackParam->SetRemovable(kFALSE); | |
96ebe67e | 1154 | if (!nextTrackParam->IsAloneInChamber()) // Make sure both clusters in second chamber are not removable anymore |
1155 | ((AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(nextTrackParam))->SetRemovable(kFALSE); | |
b709ac13 | 1156 | |
1157 | } else { // Modify flags in previous chamber | |
1158 | ||
1159 | previousTrackParam->SetRemovable(kFALSE); | |
96ebe67e | 1160 | if (!previousTrackParam->IsAloneInChamber()) // Make sure both clusters in second chamber are not removable anymore |
1161 | ((AliMUONTrackParam*) track->GetTrackParamAtCluster()->Before(previousTrackParam))->SetRemovable(kFALSE); | |
b709ac13 | 1162 | |
1163 | } | |
1164 | ||
96ebe67e | 1165 | } else { // Worst cluster not alone in its chamber |
b709ac13 | 1166 | |
96ebe67e | 1167 | if (previousTrackParam) previousChamber = previousTrackParam->GetClusterPtr()->GetChamberId(); |
b709ac13 | 1168 | else previousChamber = -1; |
1169 | ||
96ebe67e | 1170 | if (previousChamber == worstChamber) { // the second cluster on the same chamber is the previous one |
b709ac13 | 1171 | |
1172 | previousTrackParam->SetAloneInChamber(kTRUE); | |
96ebe67e | 1173 | // transfert the removability to the second cluster |
1174 | if (worstTrackParamAtCluster->IsRemovable()) previousTrackParam->SetRemovable(kTRUE); | |
b709ac13 | 1175 | |
96ebe67e | 1176 | } else { // the second cluster on the same chamber is the next one |
b709ac13 | 1177 | |
1178 | nextTrackParam->SetAloneInChamber(kTRUE); | |
96ebe67e | 1179 | // transfert the removability to the second cluster |
1180 | if (worstTrackParamAtCluster->IsRemovable()) nextTrackParam->SetRemovable(kTRUE); | |
b709ac13 | 1181 | |
1182 | } | |
1183 | ||
1184 | } | |
ea94c18b | 1185 | |
96ebe67e | 1186 | // Remove the worst cluster |
1187 | track->RemoveTrackParamAtCluster(worstTrackParamAtCluster); | |
ea94c18b | 1188 | |
1189 | // Re-calculate track parameters | |
96ebe67e | 1190 | // - from the cluster immediately downstream the one suppressed |
ea94c18b | 1191 | // - or from the begining - if parameters have been re-computed using the standard method (kalman parameters have been lost) |
96ebe67e | 1192 | // - or if the removed cluster was the last one |
b709ac13 | 1193 | if (smoothed && nextTrackParam) RetracePartialTrack(*track,nextTrackParam); |
ea94c18b | 1194 | else RetraceTrack(*track,kTRUE); |
1195 | ||
1196 | // Printout for debuging | |
1197 | if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) { | |
1198 | cout << "ImproveTracks: track " << fRecTracksPtr->IndexOf(track)+1 << " improved " << endl; | |
1199 | } | |
1200 | ||
1201 | } | |
1202 | ||
b709ac13 | 1203 | track = nextTrack; |
ea94c18b | 1204 | } |
1205 | ||
b709ac13 | 1206 | // compress the array in case of some tracks have been removed |
1207 | fRecTracksPtr->Compress(); | |
1208 | ||
8cc77df0 | 1209 | } |
1210 | ||
b0e4c598 | 1211 | //__________________________________________________________________________ |
ea94c18b | 1212 | void AliMUONTrackReconstructorK::Finalize() |
b0e4c598 | 1213 | { |
96ebe67e | 1214 | /// Update track parameters and covariances at each attached cluster |
b709ac13 | 1215 | |
ea94c18b | 1216 | AliMUONTrack *track; |
96ebe67e | 1217 | AliMUONTrackParam *trackParamAtCluster; |
ea94c18b | 1218 | Bool_t smoothed = kFALSE; |
1219 | ||
1220 | track = (AliMUONTrack*) fRecTracksPtr->First(); | |
1221 | while (track) { | |
1222 | ||
1223 | // update track parameters (using smoother if required) if not already done | |
1224 | if (!track->IsImproved()) { | |
1225 | smoothed = kFALSE; | |
3304fa09 | 1226 | if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) smoothed = RunSmoother(*track); |
96ebe67e | 1227 | if (!smoothed) track->UpdateCovTrackParamAtCluster(); |
9d2332ab | 1228 | } else smoothed = AliMUONReconstructor::GetRecoParam()->UseSmoother(); |
ea94c18b | 1229 | |
96ebe67e | 1230 | // copy smoothed parameters and covariances if any |
1231 | if (smoothed) { | |
ea94c18b | 1232 | |
96ebe67e | 1233 | trackParamAtCluster = (AliMUONTrackParam*) (track->GetTrackParamAtCluster()->First()); |
1234 | while (trackParamAtCluster) { | |
1235 | ||
1236 | trackParamAtCluster->SetParameters(trackParamAtCluster->GetSmoothParameters()); | |
1237 | trackParamAtCluster->SetCovariances(trackParamAtCluster->GetSmoothCovariances()); | |
1238 | ||
1239 | trackParamAtCluster = (AliMUONTrackParam*) (track->GetTrackParamAtCluster()->After(trackParamAtCluster)); | |
ea94c18b | 1240 | } |
1241 | ||
ea94c18b | 1242 | } |
1243 | ||
1244 | track = (AliMUONTrack*) fRecTracksPtr->After(track); | |
b0e4c598 | 1245 | } |
ea94c18b | 1246 | |
b0e4c598 | 1247 | } |
ea94c18b | 1248 |