]>
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 | ||
06ca6d7b | 18 | /// \class AliMUONTrackReconstructorK |
19 | ///////////////////////////////////// | |
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 | /// | |
8cc77df0 | 29 | //////////////////////////////////// |
30 | ||
31 | #include <stdlib.h> | |
32 | #include <Riostream.h> | |
33 | #include <TDirectory.h> | |
34 | #include <TFile.h> | |
35 | #include <TMatrixD.h> | |
36 | ||
37 | #include "AliMUONVTrackReconstructor.h" | |
38 | #include "AliMUONTrackReconstructorK.h" | |
39 | #include "AliMUONData.h" | |
40 | #include "AliMUONConstants.h" | |
41 | #include "AliMUONHitForRec.h" | |
208f139e | 42 | #include "AliMUONObjectPair.h" |
8cc77df0 | 43 | #include "AliMUONRawCluster.h" |
8cc77df0 | 44 | #include "AliMUONTrackK.h" |
45 | #include "AliLog.h" | |
46 | ||
47 | ClassImp(AliMUONTrackReconstructorK) // Class implementation in ROOT context | |
48 | ||
49 | //__________________________________________________________________________ | |
50 | AliMUONTrackReconstructorK::AliMUONTrackReconstructorK(AliMUONData* data, const Option_t* TrackMethod) | |
51 | : AliMUONVTrackReconstructor(data), | |
52 | fTrackMethod(2), //tracking method (2-Kalman 3-Combination-Kalman/Clustering) | |
53 | fMuons(0) | |
54 | { | |
55 | /// Constructor for class AliMUONTrackReconstructorK | |
56 | ||
57 | if (strstr(TrackMethod,"Kalman")) { | |
58 | cout << " *** Tracking with the Kalman filter *** " << endl; | |
59 | fTrackMethod = 2; | |
60 | } else if (strstr(TrackMethod,"Combi")) { | |
61 | cout << " *** Combined cluster / track finder ***" << endl; | |
62 | fTrackMethod = 3; | |
63 | } else AliFatal(Form("Tracking method %s not available",TrackMethod)); | |
64 | ||
65 | // Memory allocation for the TClonesArray of reconstructed tracks | |
66 | fRecTracksPtr = new TClonesArray("AliMUONTrackK", 10); | |
67 | } | |
68 | ||
69 | //__________________________________________________________________________ | |
70 | AliMUONTrackReconstructorK::~AliMUONTrackReconstructorK(void) | |
71 | { | |
72 | /// Destructor for class AliMUONTrackReconstructorK | |
73 | delete fRecTracksPtr; | |
74 | } | |
75 | ||
76 | //__________________________________________________________________________ | |
77 | void AliMUONTrackReconstructorK::AddHitsForRecFromRawClusters() | |
78 | { | |
79 | /// To add to the list of hits for reconstruction all the raw clusters | |
e6b25a6e | 80 | TTree *treeR; |
8cc77df0 | 81 | AliMUONHitForRec *hitForRec; |
82 | AliMUONRawCluster *clus; | |
208f139e | 83 | Int_t iclus, nclus; |
8cc77df0 | 84 | TClonesArray *rawclusters; |
85 | AliDebug(1,"Enter AddHitsForRecFromRawClusters"); | |
86 | ||
e6b25a6e | 87 | treeR = fMUONData->TreeR(); |
88 | if (!treeR) { | |
89 | AliError("TreeR must be loaded"); | |
90 | exit(0); | |
91 | } | |
92 | ||
8cc77df0 | 93 | if (fTrackMethod != 3) { //AZ |
e6b25a6e | 94 | fMUONData->SetTreeAddress("RC"); //AZ |
8cc77df0 | 95 | fMUONData->GetRawClusters(); // only one entry |
96 | } | |
97 | ||
98 | // Loop over tracking chambers | |
99 | for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) { | |
8cc77df0 | 100 | rawclusters =fMUONData->RawClusters(ch); |
101 | nclus = (Int_t) (rawclusters->GetEntries()); | |
102 | // Loop over (cathode correlated) raw clusters | |
103 | for (iclus = 0; iclus < nclus; iclus++) { | |
104 | clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(iclus); | |
105 | // new AliMUONHitForRec from raw cluster | |
106 | // and increment number of AliMUONHitForRec's (total and in chamber) | |
107 | hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(clus); | |
108 | fNHitsForRec++; | |
8cc77df0 | 109 | // more information into HitForRec |
110 | hitForRec->SetBendingReso2(clus->GetErrY() * clus->GetErrY()); | |
111 | hitForRec->SetNonBendingReso2(clus->GetErrX() * clus->GetErrX()); | |
112 | // original raw cluster | |
113 | hitForRec->SetChamberNumber(ch); | |
114 | hitForRec->SetHitNumber(iclus); | |
115 | // Z coordinate of the raw cluster (cm) | |
116 | hitForRec->SetZ(clus->GetZ(0)); | |
8cc77df0 | 117 | StdoutToAliDebug(3, |
118 | cout << "Chamber " << ch << | |
119 | " raw cluster " << iclus << " : " << endl; | |
120 | clus->Print("full"); | |
121 | cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl; | |
122 | hitForRec->Print("full"); | |
123 | ); | |
124 | } // end of cluster loop | |
125 | } // end of chamber loop | |
126 | SortHitsForRecWithIncreasingChamber(); | |
127 | ||
128 | AliDebug(1,"End of AddHitsForRecFromRawClusters"); | |
129 | if (AliLog::GetGlobalDebugLevel() > 0) { | |
130 | AliDebug(1, Form("NHitsForRec: %d",fNHitsForRec)); | |
131 | for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) { | |
132 | AliDebug(1, Form("Chamber(0...): %d",ch)); | |
133 | AliDebug(1, Form("NHitsForRec: %d", fNHitsForRecPerChamber[ch])); | |
134 | AliDebug(1, Form("Index(first HitForRec): %d", fIndexOfFirstHitForRecPerChamber[ch])); | |
135 | for (Int_t hit = fIndexOfFirstHitForRecPerChamber[ch]; | |
136 | hit < fIndexOfFirstHitForRecPerChamber[ch] + fNHitsForRecPerChamber[ch]; | |
137 | hit++) { | |
138 | AliDebug(1, Form("HitForRec index(0...): %d",hit)); | |
139 | ((*fHitsForRecPtr)[hit])->Dump(); | |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | return; | |
145 | } | |
146 | ||
8cc77df0 | 147 | //__________________________________________________________________________ |
148 | void AliMUONTrackReconstructorK::MakeTracks(void) | |
149 | { | |
150 | /// To make the tracks from the list of segments and points in all stations | |
151 | AliDebug(1,"Enter MakeTracks"); | |
152 | // The order may be important for the following Reset's | |
153 | //AZ ResetTracks(); | |
154 | MakeTrackCandidates(); | |
155 | if (fRecTracksPtr->GetEntriesFast() == 0) return; | |
156 | // Follow tracks in stations(1..) 3, 2 and 1 | |
157 | FollowTracks(); | |
158 | // Remove double tracks | |
159 | RemoveDoubleTracks(); | |
208f139e | 160 | // Propagate tracks to the vertex through absorber |
161 | ExtrapTracksToVertex(); | |
8cc77df0 | 162 | // Fill AliMUONTrack data members |
163 | FillMUONTrack(); | |
164 | } | |
165 | ||
166 | //__________________________________________________________________________ | |
167 | void AliMUONTrackReconstructorK::MakeTrackCandidates(void) | |
168 | { | |
208f139e | 169 | /// To make initial tracks for Kalman filter from segments in stations(1..) 4 and 5 |
8cc77df0 | 170 | Int_t istat, iseg; |
208f139e | 171 | TClonesArray *segments; |
172 | AliMUONObjectPair *segment; | |
8cc77df0 | 173 | AliMUONTrackK *trackK; |
174 | ||
175 | AliDebug(1,"Enter MakeTrackCandidatesK"); | |
176 | ||
177 | AliMUONTrackK a(this, fHitsForRecPtr); | |
178 | // Loop over stations(1...) 5 and 4 | |
179 | for (istat=4; istat>=3; istat--) { | |
208f139e | 180 | // Make segments in the station |
181 | segments = MakeSegmentsInStation(istat); | |
8cc77df0 | 182 | // Loop over segments in the station |
208f139e | 183 | for (iseg=0; iseg<segments->GetEntriesFast(); iseg++) { |
184 | // Transform segments to tracks | |
185 | segment = (AliMUONObjectPair*) ((*segments)[iseg]); | |
8cc77df0 | 186 | trackK = new ((*fRecTracksPtr)[fNRecTracks++]) AliMUONTrackK(segment); |
187 | } // for (iseg=0;...) | |
188 | } // for (istat=4;...) | |
189 | return; | |
190 | } | |
191 | ||
192 | //__________________________________________________________________________ | |
193 | void AliMUONTrackReconstructorK::FollowTracks(void) | |
194 | { | |
195 | /// Follow tracks using Kalman filter | |
196 | Bool_t ok; | |
197 | Int_t icand, ichamBeg = 0, ichamEnd, chamBits; | |
8cc77df0 | 198 | AliMUONTrackK *trackK; |
199 | AliMUONHitForRec *hit; | |
200 | AliMUONRawCluster *clus; | |
201 | TClonesArray *rawclusters; | |
202 | clus = 0; rawclusters = 0; | |
203 | ||
208f139e | 204 | Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ()); |
205 | Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL()); | |
206 | Double_t zDipole1 = simpleBPosition + 0.5 * simpleBLength; | |
207 | Double_t zDipole2 = zDipole1 - simpleBLength; | |
8cc77df0 | 208 | |
209 | // Print hits | |
210 | trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[0]); | |
211 | ||
212 | if (trackK->DebugLevel() > 0) { | |
213 | for (Int_t i1=0; i1<fNHitsForRec; i1++) { | |
214 | hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[i1]); | |
215 | printf(" Hit # %d %10.4f %10.4f %10.4f", | |
216 | hit->GetChamberNumber(), hit->GetBendingCoor(), | |
217 | hit->GetNonBendingCoor(), hit->GetZ()); | |
218 | ||
219 | // from raw clusters | |
220 | rawclusters = fMUONData->RawClusters(hit->GetChamberNumber()); | |
221 | clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit-> | |
222 | GetHitNumber()); | |
223 | printf(" %d", clus->GetTrack(1)); | |
224 | if (clus->GetTrack(2) != -1) printf(" %d \n", clus->GetTrack(2)); | |
225 | else printf("\n"); | |
226 | ||
227 | } | |
228 | } // if (trackK->DebugLevel() > 0) | |
229 | ||
230 | icand = -1; | |
231 | Int_t nSeeds; | |
232 | nSeeds = fNRecTracks; // starting number of seeds | |
233 | // Loop over track candidates | |
234 | while (icand < fNRecTracks-1) { | |
235 | icand ++; | |
236 | if (trackK->DebugLevel()>0) cout << " *** Kalman track candidate No. " << icand << endl; | |
237 | trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]); | |
238 | if (trackK->GetRecover() < 0) continue; // failed track | |
239 | ||
240 | // Discard candidate which will produce the double track | |
241 | /* | |
242 | if (icand > 0) { | |
243 | ok = CheckCandidate(icand,nSeeds); | |
244 | if (!ok) { | |
245 | trackK->SetRecover(-1); // mark candidate to be removed | |
246 | continue; | |
247 | } | |
248 | } | |
249 | */ | |
250 | ||
251 | ok = kTRUE; | |
252 | if (trackK->GetRecover() == 0) | |
253 | hit = (AliMUONHitForRec*) trackK->GetTrackHits()->Last(); // last hit | |
254 | else | |
255 | hit = trackK->GetHitLastOk(); // hit where track stopped | |
256 | ||
257 | if (hit) ichamBeg = hit->GetChamberNumber(); | |
258 | ichamEnd = 0; | |
259 | // Check propagation direction | |
260 | if (!hit) { ichamBeg = ichamEnd; AliFatal(" ??? "); } | |
261 | else if (trackK->GetTrackDir() < 0) { | |
262 | ichamEnd = 9; // forward propagation | |
263 | ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2); | |
264 | if (ok) { | |
265 | ichamBeg = ichamEnd; | |
266 | ichamEnd = 6; // backward propagation | |
267 | // Change weight matrix and zero fChi2 for backpropagation | |
268 | trackK->StartBack(); | |
269 | trackK->SetTrackDir(1); | |
270 | ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2); | |
271 | ichamBeg = ichamEnd; | |
272 | ichamEnd = 0; | |
273 | } | |
274 | } else { | |
275 | if (trackK->GetBPFlag()) { | |
276 | // backpropagation | |
277 | ichamEnd = 6; // backward propagation | |
278 | // Change weight matrix and zero fChi2 for backpropagation | |
279 | trackK->StartBack(); | |
280 | ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2); | |
281 | ichamBeg = ichamEnd; | |
282 | ichamEnd = 0; | |
283 | } | |
284 | } | |
285 | ||
286 | if (ok) { | |
287 | trackK->SetTrackDir(1); | |
288 | trackK->SetBPFlag(kFALSE); | |
289 | ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2); | |
290 | } | |
291 | if (!ok) { trackK->SetRecover(-1); continue; } // mark candidate to be removed | |
292 | ||
293 | // Apply smoother | |
294 | if (trackK->GetRecover() >= 0) { | |
295 | ok = trackK->Smooth(); | |
296 | if (!ok) trackK->SetRecover(-1); // mark candidate to be removed | |
297 | } | |
298 | ||
299 | // Majority 3 of 4 in first 2 stations | |
300 | if (!ok) continue; | |
301 | chamBits = 0; | |
302 | Double_t chi2max = 0; | |
303 | for (Int_t i=0; i<trackK->GetNTrackHits(); i++) { | |
304 | hit = (AliMUONHitForRec*) (*trackK->GetTrackHits())[i]; | |
305 | chamBits |= BIT(hit->GetChamberNumber()); | |
306 | if (trackK->GetChi2PerPoint(i) > chi2max) chi2max = trackK->GetChi2PerPoint(i); | |
307 | } | |
308 | if (!((chamBits&3)==3 || (chamBits>>2&3)==3) && chi2max > 25) { | |
309 | //trackK->Recover(); | |
310 | trackK->SetRecover(-1); //mark candidate to be removed | |
311 | continue; | |
312 | } | |
313 | if (ok) trackK->SetTrackQuality(0); // compute "track quality" | |
314 | } // while | |
315 | ||
316 | for (Int_t i=0; i<fNRecTracks; i++) { | |
317 | trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[i]); | |
318 | if (trackK->GetRecover() < 0) fRecTracksPtr->RemoveAt(i); | |
319 | } | |
320 | ||
321 | // Compress TClonesArray | |
322 | fRecTracksPtr->Compress(); | |
323 | fNRecTracks = fRecTracksPtr->GetEntriesFast(); | |
324 | return; | |
325 | } | |
326 | ||
327 | //__________________________________________________________________________ | |
328 | Bool_t AliMUONTrackReconstructorK::CheckCandidate(Int_t icand, Int_t nSeeds) const | |
329 | { | |
330 | /// Discards track candidate if it will produce the double track (having | |
331 | /// the same seed segment hits as hits of a good track found before) | |
332 | AliMUONTrackK *track1, *track2; | |
333 | AliMUONHitForRec *hit1, *hit2, *hit; | |
208f139e | 334 | AliMUONObjectPair *segment1, *segment2; |
8cc77df0 | 335 | |
336 | track1 = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]); | |
337 | hit1 = (AliMUONHitForRec*) (*track1->GetTrackHits())[0]; // 1'st hit | |
338 | hit2 = (AliMUONHitForRec*) (*track1->GetTrackHits())[1]; // 2'nd hit | |
339 | ||
340 | for (Int_t i=0; i<icand; i++) { | |
341 | track2 = (AliMUONTrackK*) ((*fRecTracksPtr)[i]); | |
342 | //if (track2->GetRecover() < 0) continue; | |
343 | if (track2->GetRecover() < 0 && icand >= nSeeds) continue; | |
208f139e | 344 | segment1 = track1->GetStartSegment(); |
345 | segment2 = track2->GetStartSegment(); | |
346 | if (segment1->First() == segment2->First() && | |
347 | segment1->Second() == segment2->Second()) { | |
8cc77df0 | 348 | return kFALSE; |
349 | } else { | |
350 | Int_t nSame = 0; | |
351 | for (Int_t j=0; j<track2->GetNTrackHits(); j++) { | |
352 | hit = (AliMUONHitForRec*) (*track2->GetTrackHits())[j]; | |
353 | if (hit == hit1 || hit == hit2) { | |
354 | nSame++; | |
355 | if (nSame == 2) return kFALSE; | |
356 | } | |
357 | } // for (Int_t j=0; | |
358 | } | |
359 | } // for (Int_t i=0; | |
360 | return kTRUE; | |
361 | } | |
362 | ||
363 | //__________________________________________________________________________ | |
364 | void AliMUONTrackReconstructorK::RemoveDoubleTracks(void) | |
365 | { | |
366 | /// Removes double tracks (sharing more than half of their hits). | |
367 | /// Keeps the track with higher quality | |
368 | AliMUONTrackK *track1, *track2, *trackToKill; | |
369 | ||
370 | // Sort tracks according to their quality | |
371 | fRecTracksPtr->Sort(); | |
372 | ||
373 | // Loop over first track of the pair | |
374 | track1 = (AliMUONTrackK*) fRecTracksPtr->First(); | |
375 | Int_t debug = track1->DebugLevel(); | |
376 | while (track1) { | |
377 | // Loop over second track of the pair | |
378 | track2 = (AliMUONTrackK*) fRecTracksPtr->After(track1); | |
379 | while (track2) { | |
380 | // Check whether or not to keep track2 | |
381 | if (!track2->KeepTrack(track1)) { | |
382 | if (debug >= 0) cout << " Killed track: " << 1/(*track2->GetTrackParameters())(4,0) << | |
383 | " " << track2->GetTrackQuality() << endl; | |
384 | trackToKill = track2; | |
385 | track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2); | |
386 | trackToKill->Kill(); | |
387 | fRecTracksPtr->Compress(); | |
388 | } else track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2); | |
389 | } // track2 | |
390 | track1 = (AliMUONTrackK*) fRecTracksPtr->After(track1); | |
391 | } // track1 | |
392 | ||
393 | fNRecTracks = fRecTracksPtr->GetEntriesFast(); | |
394 | if (debug >= 0) cout << " Number of Kalman tracks: " << fNRecTracks << endl; | |
395 | } | |
396 | ||
397 | //__________________________________________________________________________ | |
208f139e | 398 | void AliMUONTrackReconstructorK::ExtrapTracksToVertex(void) |
8cc77df0 | 399 | { |
400 | /// Propagates track to the vertex thru absorber | |
401 | /// (using Branson correction for now) | |
402 | Double_t zVertex; | |
403 | zVertex = 0; | |
404 | for (Int_t i=0; i<fNRecTracks; i++) { | |
405 | //((AliMUONTrackK*)(*fRecTracksPtr)[i])->Branson(); | |
406 | ((AliMUONTrackK*)(*fRecTracksPtr)[i])->SetTrackQuality(1); // compute Chi2 | |
407 | //((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToZ(zVertex); // w/out absorber | |
408 | ((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToVertex(1); // with absorber | |
409 | } | |
410 | } | |
411 | ||
412 | //__________________________________________________________________________ | |
413 | void AliMUONTrackReconstructorK::FillMUONTrack() | |
414 | { | |
415 | // Set track parameters at hits for Kalman track. Fill fTrackParamAtHit of AliMUONTrack's | |
416 | AliMUONTrackK *track; | |
417 | track = (AliMUONTrackK*) fRecTracksPtr->First(); | |
418 | while (track) { | |
419 | track->FillMUONTrack(); | |
420 | track = (AliMUONTrackK*) fRecTracksPtr->After(track); | |
421 | } | |
422 | return; | |
423 | } | |
424 | ||
425 | //__________________________________________________________________________ | |
426 | void AliMUONTrackReconstructorK::EventDump(void) | |
427 | { | |
428 | /// Dump reconstructed event (track parameters at vertex and at first hit), | |
429 | /// and the particle parameters | |
430 | AliDebug(1,"****** enter EventDump ******"); | |
431 | AliDebug(1, Form("Number of Reconstructed tracks : %d", fNRecTracks)); | |
432 | ||
433 | AliWarning("AliMUONTrackReconstructorK::EventDump: not implemented"); | |
434 | ||
435 | // informations about generated particles NO !!!!!!!! | |
436 | ||
437 | // for (Int_t iPart = 0; iPart < np; iPart++) { | |
438 | // p = gAlice->Particle(iPart); | |
439 | // printf(" particle %d: type= %d px= %f py= %f pz= %f pdg= %d\n", | |
440 | // iPart, p->GetPdgCode(), p->Px(), p->Py(), p->Pz(), p->GetPdgCode()); | |
441 | // } | |
442 | return; | |
443 | } | |
444 | ||
445 |