]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrackReconstructor.cxx
Adding CreateIterator(void) and GetNeighbours() pure virtual methods,
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackReconstructor.cxx
CommitLineData
a9e2aefa 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
cc87ebcd 16/* $Id$ */
17
7945aae7 18/// \class AliMUONTrackReconstructor
19/// MUON track reconstructor using the original method
20///
21/// This class contains as data:
22/// - the parameters for the track reconstruction
23///
24/// It contains as methods, among others:
25/// - MakeTracks to build the tracks
26///
a9e2aefa 27
29f1b13a 28#include "AliMUONTrackReconstructor.h"
5e671e06 29#include "AliMUONData.h"
29fc2c86 30#include "AliMUONConstants.h"
a9e2aefa 31#include "AliMUONRawCluster.h"
2457f726 32#include "AliMUONHitForRec.h"
208f139e 33#include "AliMUONObjectPair.h"
a9e2aefa 34#include "AliMUONTrack.h"
37827b29 35#include "AliMUONTrackParam.h"
36#include "AliMUONTrackExtrap.h"
af743f54 37
8c343c7c 38#include "AliLog.h"
af743f54 39
208f139e 40#include <TMinuit.h>
af743f54 41#include <Riostream.h>
42#include <TMatrixD.h>
a9e2aefa 43
de2cd600 44// Functions to be minimized with Minuit
45void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
46void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
47
de2cd600 48Double_t MultipleScatteringAngle2(AliMUONTrackParam *param);
49
7945aae7 50/// \cond CLASSIMP
29f1b13a 51ClassImp(AliMUONTrackReconstructor) // Class implementation in ROOT context
7945aae7 52/// \endcond
a9e2aefa 53
2457f726 54//************* Defaults parameters for reconstruction
208f139e 55const Double_t AliMUONTrackReconstructor::fgkMaxNormChi2 = 100.0;
56const Bool_t AliMUONTrackReconstructor::fgkTrackAllTracks = kFALSE;
2457f726 57
3bc8b580 58//__________________________________________________________________________
cc9e7528 59AliMUONTrackReconstructor::AliMUONTrackReconstructor(AliMUONData* data)
208f139e 60 : AliMUONVTrackReconstructor(data)
a9e2aefa 61{
2457f726 62 /// Constructor for class AliMUONTrackReconstructor
de2cd600 63
a9e2aefa 64 // Memory allocation for the TClonesArray of reconstructed tracks
a9e2aefa 65 fRecTracksPtr = new TClonesArray("AliMUONTrack", 10);
a9e2aefa 66}
9cbdf048 67
a9e2aefa 68 //__________________________________________________________________________
29f1b13a 69AliMUONTrackReconstructor::~AliMUONTrackReconstructor(void)
a9e2aefa 70{
2457f726 71 /// Destructor for class AliMUONTrackReconstructor
de2cd600 72 delete fRecTracksPtr;
a9e2aefa 73}
a9e2aefa 74
75 //__________________________________________________________________________
2457f726 76void AliMUONTrackReconstructor::AddHitsForRecFromRawClusters()
a9e2aefa 77{
2457f726 78 /// To add to the list of hits for reconstruction all the raw clusters
e6b25a6e 79 TTree *treeR;
a9e2aefa 80 AliMUONHitForRec *hitForRec;
81 AliMUONRawCluster *clus;
208f139e 82 Int_t iclus, nclus;
a9e2aefa 83 TClonesArray *rawclusters;
b840996b 84 AliDebug(1,"Enter AddHitsForRecFromRawClusters");
2457f726 85
e6b25a6e 86 treeR = fMUONData->TreeR();
87 if (!treeR) {
88 AliError("TreeR must be loaded");
2457f726 89 exit(0);
f69d51b5 90 }
e6b25a6e 91
e6b25a6e 92 fMUONData->SetTreeAddress("RC");
2457f726 93 fMUONData->GetRawClusters(); // only one entry
94
a9e2aefa 95 // Loop over tracking chambers
190f97ea 96 for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
52c9bc11 97 rawclusters =fMUONData->RawClusters(ch);
a9e2aefa 98 nclus = (Int_t) (rawclusters->GetEntries());
99 // Loop over (cathode correlated) raw clusters
100 for (iclus = 0; iclus < nclus; iclus++) {
101 clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(iclus);
102 // new AliMUONHitForRec from raw cluster
103 // and increment number of AliMUONHitForRec's (total and in chamber)
104 hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(clus);
105 fNHitsForRec++;
a9e2aefa 106 // more information into HitForRec
fff097e0 107 hitForRec->SetBendingReso2(clus->GetErrY() * clus->GetErrY());
108 hitForRec->SetNonBendingReso2(clus->GetErrX() * clus->GetErrX());
a9e2aefa 109 // original raw cluster
110 hitForRec->SetChamberNumber(ch);
111 hitForRec->SetHitNumber(iclus);
ba5b68db 112 // Z coordinate of the raw cluster (cm)
ba12c242 113 hitForRec->SetZ(clus->GetZ(0));
80e33fc5 114 StdoutToAliDebug(3,
115 cout << "Chamber " << ch <<
116 " raw cluster " << iclus << " : " << endl;
117 clus->Print("full");
118 cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
119 hitForRec->Print("full");
120 );
a9e2aefa 121 } // end of cluster loop
122 } // end of chamber loop
cc87ebcd 123 SortHitsForRecWithIncreasingChamber();
2457f726 124
125 AliDebug(1,"End of AddHitsForRecFromRawClusters");
126 if (AliLog::GetGlobalDebugLevel() > 0) {
127 AliDebug(1, Form("NHitsForRec: %d",fNHitsForRec));
128 for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
129 AliDebug(1, Form("Chamber(0...): %d",ch));
130 AliDebug(1, Form("NHitsForRec: %d", fNHitsForRecPerChamber[ch]));
131 AliDebug(1, Form("Index(first HitForRec): %d", fIndexOfFirstHitForRecPerChamber[ch]));
132 for (Int_t hit = fIndexOfFirstHitForRecPerChamber[ch];
133 hit < fIndexOfFirstHitForRecPerChamber[ch] + fNHitsForRecPerChamber[ch];
134 hit++) {
135 AliDebug(1, Form("HitForRec index(0...): %d",hit));
136 ((*fHitsForRecPtr)[hit])->Dump();
137 }
138 }
139 }
140
a9e2aefa 141 return;
142}
143
a9e2aefa 144 //__________________________________________________________________________
29f1b13a 145void AliMUONTrackReconstructor::MakeTracks(void)
a9e2aefa 146{
2457f726 147 /// To make the tracks from the list of segments and points in all stations
b840996b 148 AliDebug(1,"Enter MakeTracks");
2457f726 149 // Look for candidates from at least 3 aligned points in stations(1..) 4 and 5
150 MakeTrackCandidates();
151 // Follow tracks in stations(1..) 3, 2 and 1
152 FollowTracks();
153 // Remove double tracks
154 RemoveDoubleTracks();
208f139e 155 // Propagate tracks to the vertex through absorber
156 ExtrapTracksToVertex();
157 // Fill out the AliMUONTrack's
158 FillMUONTrack();
276c44b7 159}
160
de2cd600 161 //__________________________________________________________________________
162void AliMUONTrackReconstructor::MakeTrackCandidates(void)
163{
208f139e 164 /// To make track candidates:
165 /// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
166 /// Good candidates are made of at least three hitForRec's.
167 /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
168 TClonesArray *segments;
169 AliMUONObjectPair *segment;
170 AliMUONHitForRec *hitForRec1, *hitForRec2;
171 AliMUONTrack *track;
172 AliMUONTrackParam *trackParamAtFirstHit;
173 Int_t iCandidate = 0;
174
de2cd600 175 AliDebug(1,"Enter MakeTrackCandidates");
de2cd600 176
208f139e 177 // Loop over stations(1..) 5 and 4 and make track candidates
178 for (Int_t istat=4; istat>=3; istat--) {
179 // Make segments in the station
180 segments = MakeSegmentsInStation(istat);
181 // Loop over segments
182 for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) {
183 AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
184 // Transform segments to tracks and put them at the end of fRecTracksPtr
185 segment = (AliMUONObjectPair*) ((*segments)[iseg]);
186 hitForRec1 = (AliMUONHitForRec*) segment->First();
187 hitForRec2 = (AliMUONHitForRec*) segment->Second();
188 track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(hitForRec1, hitForRec2);
a9e2aefa 189 fNRecTracks++;
208f139e 190 // Add MCS effects in parameter covariances
191 trackParamAtFirstHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
192 AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(trackParamAtFirstHit,AliMUONConstants::ChamberThicknessInX0(),1.);
193 // Printout for debuging
194 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
195 cout<<endl<<"Track parameter covariances at first hit with multiple Coulomb scattering effects:"<<endl;
196 trackParamAtFirstHit->GetCovariances()->Print();
197 }
198 // Look for compatible hitForRec(s) in the other station
199 FollowTrackInStation(track,7-istat);
a9e2aefa 200 }
208f139e 201 // delete the array of segments
202 delete segments;
203 }
204 fRecTracksPtr->Compress(); // this is essential before checking tracks
205
206 // Keep all different tracks or only the best ones as required
207 if (fgkTrackAllTracks) RemoveIdenticalTracks();
208 else RemoveDoubleTracks();
209
210 AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
211
a9e2aefa 212}
213
214 //__________________________________________________________________________
208f139e 215void AliMUONTrackReconstructor::RemoveIdenticalTracks(void)
a9e2aefa 216{
208f139e 217 /// To remove identical tracks:
218 /// Tracks are considered identical if they have all their hits in common.
219 /// One keeps the track with the larger number of hits if need be
220 AliMUONTrack *track1, *track2, *trackToRemove;
221 Int_t hitsInCommon, nHits1, nHits2;
222 Bool_t removedTrack1;
223 // Loop over first track of the pair
224 track1 = (AliMUONTrack*) fRecTracksPtr->First();
225 while (track1) {
226 removedTrack1 = kFALSE;
227 nHits1 = track1->GetNTrackHits();
228 // Loop over second track of the pair
229 track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
230 while (track2) {
231 nHits2 = track2->GetNTrackHits();
232 // number of hits in common between two tracks
233 hitsInCommon = track1->HitsInCommon(track2);
234 // check for identical tracks
235 if ((hitsInCommon == nHits1) || (hitsInCommon == nHits2)) {
236 // decide which track to remove
237 if (nHits2 > nHits1) {
238 // remove track1 and continue the first loop with the track next to track1
239 trackToRemove = track1;
240 track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
241 fRecTracksPtr->Remove(trackToRemove);
242 fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
243 fNRecTracks--;
244 removedTrack1 = kTRUE;
245 break;
246 } else {
247 // remove track2 and continue the second loop with the track next to track2
248 trackToRemove = track2;
249 track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
250 fRecTracksPtr->Remove(trackToRemove);
251 fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
252 fNRecTracks--;
253 }
254 } else track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
255 } // track2
256 if (removedTrack1) continue;
257 track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
258 } // track1
259 return;
a9e2aefa 260}
261
262 //__________________________________________________________________________
208f139e 263void AliMUONTrackReconstructor::RemoveDoubleTracks(void)
a9e2aefa 264{
208f139e 265 /// To remove double tracks:
266 /// Tracks are considered identical if more than half of the hits of the track
267 /// which has the smaller number of hits are in common with the other track.
268 /// Among two identical tracks, one keeps the track with the larger number of hits
269 /// or, if these numbers are equal, the track with the minimum chi2.
270 AliMUONTrack *track1, *track2, *trackToRemove;
271 Int_t hitsInCommon, nHits1, nHits2;
272 Bool_t removedTrack1;
273 // Loop over first track of the pair
274 track1 = (AliMUONTrack*) fRecTracksPtr->First();
275 while (track1) {
276 removedTrack1 = kFALSE;
277 nHits1 = track1->GetNTrackHits();
278 // Loop over second track of the pair
279 track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
280 while (track2) {
281 nHits2 = track2->GetNTrackHits();
282 // number of hits in common between two tracks
283 hitsInCommon = track1->HitsInCommon(track2);
284 // check for identical tracks
285 if (((nHits1 < nHits2) && (2 * hitsInCommon > nHits1)) || (2 * hitsInCommon > nHits2)) {
286 // decide which track to remove
287 if ((nHits1 > nHits2) || ((nHits1 == nHits2) && (track1->GetFitFMin() <= track2->GetFitFMin()))) {
288 // remove track2 and continue the second loop with the track next to track2
289 trackToRemove = track2;
290 track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
291 fRecTracksPtr->Remove(trackToRemove);
292 fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
293 fNRecTracks--;
294 } else {
295 // else remove track1 and continue the first loop with the track next to track1
296 trackToRemove = track1;
297 track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
298 fRecTracksPtr->Remove(trackToRemove);
299 fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
300 fNRecTracks--;
301 removedTrack1 = kTRUE;
302 break;
303 }
304 } else track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
305 } // track2
306 if (removedTrack1) continue;
307 track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
308 } // track1
309 return;
a9e2aefa 310}
311
312 //__________________________________________________________________________
29f1b13a 313void AliMUONTrackReconstructor::FollowTracks(void)
a9e2aefa 314{
2457f726 315 /// Follow tracks in stations(1..) 3, 2 and 1
208f139e 316 AliDebug(1,"Enter FollowTracks");
317
04b5ea16 318 AliMUONTrack *track, *nextTrack;
208f139e 319 AliMUONTrackParam *trackParamAtFirstHit;
320 Double_t numberOfDegFree, chi2Norm;
af743f54 321 Int_t currentNRecTracks;
208f139e 322
323 for (Int_t station = 2; station >= 0; station--) {
324 // Save the actual number of reconstructed track in case of
325 // tracks are added or suppressed during the tracking procedure
326 // !! Do not compress fRecTracksPtr until the end of the loop over tracks !!
af743f54 327 currentNRecTracks = fNRecTracks;
328 for (Int_t iRecTrack = 0; iRecTrack <currentNRecTracks; iRecTrack++) {
208f139e 329 AliDebug(1,Form("FollowTracks: track candidate(1..) %d", iRecTrack+1));
330 track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
331 // Fit the track:
332 // Do not take into account the multiple scattering to speed up the fit
333 // Calculate the track parameter covariance matrix
334 // If "station" is station(1..) 3 then use the vertex to better constrain the fit
335 if (station==2) {
336 SetVertexForFit(track);
337 track->SetFitWithVertex(kTRUE);
338 } else track->SetFitWithVertex(kFALSE);
339 Fit(track,kFALSE, kTRUE);
340 // Remove the track if the normalized chi2 is too high
341 numberOfDegFree = (2. * track->GetNTrackHits() - 5.);
342 if (numberOfDegFree > 0) chi2Norm = track->GetFitFMin() / numberOfDegFree;
343 else chi2Norm = 1.e10;
344 if (chi2Norm > fgkMaxNormChi2) {
345 fRecTracksPtr->Remove(track);
346 fNRecTracks--;
347 continue;
348 }
349 // Add MCS effects in parameter covariances
350 trackParamAtFirstHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
351 AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(trackParamAtFirstHit,AliMUONConstants::ChamberThicknessInX0(),1.);
352 // Printout for debuging
353 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
354 cout<<endl<<"Track parameter covariances at first hit with multiple Coulomb scattering effects:"<<endl;
355 trackParamAtFirstHit->GetCovariances()->Print();
356 }
357 // Look for compatible hitForRec in station(0..) "station"
358 FollowTrackInStation(track,station);
359 }
360 // Compress fRecTracksPtr for the next step
361 fRecTracksPtr->Compress();
362 // Keep only the best tracks if required
363 if (!fgkTrackAllTracks) RemoveDoubleTracks();
364 }
365
366 // Last fit of track candidates with all station
367 // Take into account the multiple scattering and remove bad tracks
368 Int_t trackIndex = -1;
04b5ea16 369 track = (AliMUONTrack*) fRecTracksPtr->First();
04b5ea16 370 while (track) {
04b5ea16 371 trackIndex++;
372 nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track); // prepare next track
208f139e 373 track->SetFitWithVertex(kFALSE); // just to be sure
374 Fit(track,kTRUE, kFALSE);
375 // Printout for debuging
376 if (AliLog::GetGlobalDebugLevel() >= 3) {
377 cout << "FollowTracks: track candidate(0..) " << trackIndex << " after final fit" << endl;
a9e2aefa 378 track->RecursiveDump();
208f139e 379 }
380 // Remove the track if the normalized chi2 is too high
381 numberOfDegFree = (2.0 * track->GetNTrackHits() - 5);
382 if (numberOfDegFree > 0) chi2Norm = track->GetFitFMin() / numberOfDegFree;
383 else chi2Norm = 1.e10;
384 if (chi2Norm > fgkMaxNormChi2) {
385 fRecTracksPtr->Remove(track);
386 fNRecTracks--;
a9e2aefa 387 }
208f139e 388 track = nextTrack;
389 }
390 fRecTracksPtr->Compress();
391
392}
1a38e749 393
208f139e 394 //__________________________________________________________________________
395void AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack* trackCandidate, Int_t nextStation)
396{
397 /// Follow trackCandidate in station(0..) nextStation and search for compatible HitForRec(s)
398 /// Keep all possibilities or only the best one(s) according to the flag fgkTrackAllTracks:
399 /// kTRUE: duplicate "trackCandidate" if there are several possibilities and add the new tracks at the end of
400 /// fRecTracksPtr to avoid conficts with other track candidates at this current stage of the tracking procedure.
401 /// Remove the obsolete "trackCandidate" at the end.
402 /// kFALSE: add only the best hit(s) to the "trackCandidate". Try to add a couple of hits in priority.
403 AliDebug(1,Form("Enter FollowTrackInStation(1..) %d", nextStation+1));
404
405 Int_t ch1 = 2*nextStation;
406 Int_t ch2 = 2*nextStation+1;
407 Double_t zCh2 = AliMUONConstants::DefaultChamberZ(ch2);
408 Double_t chi2WithOneHitForRec = 1.e10;
409 Double_t chi2WithTwoHitForRec = 1.e10;
410 Double_t maxChi2WithOneHitForRec = 2.*fgkMaxNormChi2; // 2 because 2 quantities in chi2
411 Double_t maxChi2WithTwoHitForRec = 4.*fgkMaxNormChi2; // 4 because 4 quantities in chi2
412 Double_t bestChi2WithOneHitForRec = maxChi2WithOneHitForRec;
413 Double_t bestChi2WithTwoHitForRec = maxChi2WithTwoHitForRec;
414 AliMUONTrack *newTrack = 0x0;
415 AliMUONHitForRec *hitForRecCh1, *hitForRecCh2;
416 AliMUONHitForRec *bestHitForRec1 = 0x0, *bestHitForRec2 = 0x0;
847cbaef 417 Bool_t *hitForRecCh1Used = new Bool_t[fNHitsForRecPerChamber[ch1]];
418 for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) hitForRecCh1Used[hit1] = kFALSE;
208f139e 419 //
420 //Extrapolate trackCandidate to chamber "ch2" to save computing time in the next steps
421 AliMUONTrackParam *extrapTrackParamPtr = trackCandidate->GetExtrapTrackParam();
422 *extrapTrackParamPtr = *((AliMUONTrackParam*)(trackCandidate->GetTrackParamAtHit()->First()));
423 AliMUONTrackExtrap::ExtrapToZCov(extrapTrackParamPtr, zCh2);
424 AliMUONTrackParam extrapTrackParamSave(*extrapTrackParamPtr);
425 //
426 // Printout for debuging
427 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
428 TMatrixD* paramCovForDebug = extrapTrackParamPtr->GetCovariances();
429 cout<<endl<<"Track parameter covariances at first hit extrapolated to z = "<<zCh2<<":"<<endl;
430 paramCovForDebug->Print();
431 }
432 //
433 // look for candidates in chamber 2
434 // Printout for debuging
435 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
436 cout << "FollowTrackInStation: look for hits in chamber(1..): " << ch2+1 << endl;
437 }
438 for (Int_t hit2 = 0; hit2 < fNHitsForRecPerChamber[ch2]; hit2++) {
439 hitForRecCh2 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch2]+hit2);
440 // extrapolate track parameters and covariances only once for this hit
441 AliMUONTrackExtrap::ExtrapToZCov(extrapTrackParamPtr, hitForRecCh2->GetZ());
442 chi2WithOneHitForRec = trackCandidate->TryOneHitForRec(hitForRecCh2);
443 // if good chi2 then try to attach a hitForRec in the other chamber too
444 if (chi2WithOneHitForRec < maxChi2WithOneHitForRec) {
445 // Printout for debuging
446 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
447 cout << "FollowTrackInStation: look for second hits in chamber(1..): " << ch1+1 << endl;
a9e2aefa 448 }
208f139e 449 Bool_t foundSecondHit = kFALSE;
450 for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) {
451 hitForRecCh1 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch1]+hit1);
452 chi2WithTwoHitForRec = trackCandidate->TryTwoHitForRec(hitForRecCh2, hitForRecCh1); // order hits like that to save computing time
453 // if good chi2 then create a new track by adding the 2 hitForRec to the "trackCandidate"
454 if (chi2WithTwoHitForRec < maxChi2WithTwoHitForRec) {
455 foundSecondHit = kTRUE;
456 if (fgkTrackAllTracks) {
457 // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
458 newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
459 fNRecTracks++;
af743f54 460 AliMUONTrackParam trackParam1(extrapTrackParamSave);
461 AliMUONTrackExtrap::ExtrapToZ(&trackParam1, hitForRecCh1->GetZ());
462 newTrack->AddTrackParamAtHit(&trackParam1,hitForRecCh1);
463 AliMUONTrackParam trackParam2(extrapTrackParamSave);
464 AliMUONTrackExtrap::ExtrapToZ(&trackParam2, hitForRecCh2->GetZ());
465 newTrack->AddTrackParamAtHit(&trackParam2,hitForRecCh2);
208f139e 466 // Sort TrackParamAtHit according to increasing Z
467 newTrack->GetTrackParamAtHit()->Sort();
468 // Update the chi2 of the new track
469 if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithTwoHitForRec);
470 else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithTwoHitForRec);
847cbaef 471 // Tag hitForRecCh1 as used
472 hitForRecCh1Used[hit1] = kTRUE;
208f139e 473 // Printout for debuging
474 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
475 cout << "FollowTrackInStation: added two hits in station(1..): " << nextStation+1
476 << " (Chi2 = " << chi2WithTwoHitForRec << ")" << endl;
477 if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
a9e2aefa 478 }
208f139e 479 } else if (chi2WithTwoHitForRec < bestChi2WithTwoHitForRec) {
480 // keep track of the best couple of hits
481 bestChi2WithTwoHitForRec = chi2WithTwoHitForRec;
482 bestHitForRec1 = hitForRecCh1;
483 bestHitForRec2 = hitForRecCh2;
484 }
a9e2aefa 485 }
d0bfce8d 486 }
208f139e 487 // if no hitForRecCh1 found then consider to add hitForRecCh2 only
488 if (!foundSecondHit) {
489 if (fgkTrackAllTracks) {
490 // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
491 newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
492 fNRecTracks++;
af743f54 493 AliMUONTrackParam trackParam1(extrapTrackParamSave);
494 AliMUONTrackExtrap::ExtrapToZ(&trackParam1, hitForRecCh2->GetZ());
495 newTrack->AddTrackParamAtHit(&trackParam1,hitForRecCh2);
208f139e 496 // Sort TrackParamAtHit according to increasing Z
497 newTrack->GetTrackParamAtHit()->Sort();
498 // Update the chi2 of the new track
499 if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithOneHitForRec);
500 else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithOneHitForRec);
501 // Printout for debuging
502 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
503 cout << "FollowTrackInStation: added one hit in chamber(1..): " << ch2+1
504 << " (Chi2 = " << chi2WithOneHitForRec << ")" << endl;
505 if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
506 }
507 } if (!bestHitForRec2 && chi2WithOneHitForRec < bestChi2WithOneHitForRec) {
508 // keep track of the best single hitForRec except if a couple
509 // of hits has already been found (i.e. bestHitForRec2!=0x0)
510 bestChi2WithOneHitForRec = chi2WithOneHitForRec;
511 bestHitForRec1 = hitForRecCh2;
512 }
d0bfce8d 513 }
208f139e 514 }
515 // reset the extrapolated track parameter for next step
516 trackCandidate->SetExtrapTrackParam(&extrapTrackParamSave);
517 }
518 //
519 // look for candidates in chamber 1 not already attached to a track
520 // if we want to keep all possible tracks or if no good couple of hitForRec has been found
521 if (fgkTrackAllTracks || !bestHitForRec2) {
522 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
523 cout << "FollowTrackInStation: look for single hits in chamber(1..): " << ch1+1 << endl;
524 }
525 for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) {
526 hitForRecCh1 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch1]+hit1);
847cbaef 527 if (hitForRecCh1Used[hit1]) continue; // Skip hitForRec already used
208f139e 528 chi2WithOneHitForRec = trackCandidate->TryOneHitForRec(hitForRecCh1);
529 // if good chi2 then create a new track by adding the good hitForRec in "ch1" to the "trackCandidate"
530 // We do not try to attach a hitForRec in the other chamber too since it has already been done above
531 if (chi2WithOneHitForRec < maxChi2WithOneHitForRec) {
532 if (fgkTrackAllTracks) {
533 // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
534 newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
535 fNRecTracks++;
af743f54 536 AliMUONTrackParam trackParam1(extrapTrackParamSave);
537 AliMUONTrackExtrap::ExtrapToZ(&trackParam1, hitForRecCh1->GetZ());
538 newTrack->AddTrackParamAtHit(&trackParam1,hitForRecCh1);
208f139e 539 // Sort TrackParamAtHit according to increasing Z
540 newTrack->GetTrackParamAtHit()->Sort();
541 // Update the chi2 of the new track
542 if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithOneHitForRec);
543 else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithOneHitForRec);
544 // Printout for debuging
545 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
546 cout << "FollowTrackInStation: added one hit in chamber(1..): " << ch1+1
547 << " (Chi2 = " << chi2WithOneHitForRec << ")" << endl;
548 if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
549 }
550 } if (!bestHitForRec2 && chi2WithOneHitForRec < bestChi2WithOneHitForRec) {
551 // keep track of the best single hitForRec except if a couple
552 // of hits has already been found (i.e. bestHitForRec1!=0x0)
553 bestChi2WithOneHitForRec = chi2WithOneHitForRec;
554 bestHitForRec1 = hitForRecCh1;
555 }
d0bfce8d 556 }
208f139e 557 }
558 }
559 //
560 // fill out the best track if required else clean up the fRecTracksPtr array
561 if (!fgkTrackAllTracks && bestHitForRec1) {
af743f54 562 AliMUONTrackParam trackParam1(extrapTrackParamSave);
563 AliMUONTrackExtrap::ExtrapToZ(&trackParam1, bestHitForRec1->GetZ());
564 trackCandidate->AddTrackParamAtHit(&trackParam1,bestHitForRec1);
208f139e 565 if (bestHitForRec2) {
af743f54 566 AliMUONTrackParam trackParam2(extrapTrackParamSave);
567 AliMUONTrackExtrap::ExtrapToZ(&trackParam2, bestHitForRec2->GetZ());
568 trackCandidate->AddTrackParamAtHit(&trackParam2,bestHitForRec2);
208f139e 569 // Sort TrackParamAtHit according to increasing Z
570 trackCandidate->GetTrackParamAtHit()->Sort();
571 // Update the chi2 of the new track
572 if (trackCandidate->GetFitFMin()<0) trackCandidate->SetFitFMin(bestChi2WithTwoHitForRec);
573 else trackCandidate->SetFitFMin(trackCandidate->GetFitFMin() + bestChi2WithTwoHitForRec);
574 // Printout for debuging
575 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
576 cout << "FollowTrackInStation: added the two best hits in station(1..): " << nextStation+1
577 << " (Chi2 = " << bestChi2WithTwoHitForRec << ")" << endl;
578 if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
a9e2aefa 579 }
208f139e 580 } else {
581 // Sort TrackParamAtHit according to increasing Z
582 trackCandidate->GetTrackParamAtHit()->Sort();
583 // Update the chi2 of the new track
584 if (trackCandidate->GetFitFMin()<0) trackCandidate->SetFitFMin(bestChi2WithOneHitForRec);
585 else trackCandidate->SetFitFMin(trackCandidate->GetFitFMin() + bestChi2WithOneHitForRec);
586 // Printout for debuging
587 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
588 cout << "FollowTrackInStation: added the best hit in station(1..): " << nextStation+1
589 << " (Chi2 = " << bestChi2WithOneHitForRec << ")" << endl;
590 if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
04b5ea16 591 }
208f139e 592 }
593 } else {
594 fRecTracksPtr->Remove(trackCandidate); // obsolete track
595 fNRecTracks--;
596 }
597
04b5ea16 598}
599
de2cd600 600 //__________________________________________________________________________
208f139e 601void AliMUONTrackReconstructor::SetVertexForFit(AliMUONTrack* trackCandidate)
de2cd600 602{
208f139e 603 /// Add the vertex as a measured hit to constrain the fit of the "trackCandidate"
604 /// Compute the vertex resolution from natural vertex dispersion and
605 /// multiple scattering effets according to trackCandidate path in absorber
606 /// It is necessary to account for multiple scattering effects here instead of during the fit of
607 /// the "trackCandidate" to do not influence the result by changing track resolution at vertex
608 AliDebug(1,"Enter SetVertexForFit");
de2cd600 609
208f139e 610 Double_t nonBendingReso2 = fNonBendingVertexDispersion * fNonBendingVertexDispersion;
611 Double_t bendingReso2 = fBendingVertexDispersion * fBendingVertexDispersion;
612 // add multiple scattering effets
613 AliMUONTrackParam paramAtVertex(*((AliMUONTrackParam*)(trackCandidate->GetTrackParamAtHit()->First())));
614 paramAtVertex.DeleteCovariances(); // to be sure to account only for multiple scattering
615 AliMUONTrackExtrap::ExtrapToVertexUncorrected(&paramAtVertex,0.);
616 TMatrixD* paramCov = paramAtVertex.GetCovariances();
617 nonBendingReso2 += (*paramCov)(0,0);
618 bendingReso2 += (*paramCov)(2,2);
619 // Set the vertex
620 AliMUONHitForRec vertex; // Coordinates set to (0.,0.,0.) by default
621 vertex.SetNonBendingReso2(nonBendingReso2);
622 vertex.SetBendingReso2(bendingReso2);
623 trackCandidate->SetVertex(&vertex);
624}
625
626 //__________________________________________________________________________
627void AliMUONTrackReconstructor::Fit(AliMUONTrack *track, Bool_t includeMCS, Bool_t calcCov)
628{
629 /// Fit the track "track" with or without multiple Coulomb scattering according to "includeMCS".
de2cd600 630
208f139e 631 Double_t benC, errorParam, invBenP, nonBenC, x, y;
de2cd600 632 AliMUONTrackParam *trackParam;
208f139e 633 Double_t arg[1], fedm, errdef, fitFMin;
634 Int_t npari, nparx;
635 Int_t status, covStatus;
636
637 // Clear MINUIT parameters
638 gMinuit->mncler();
639 // Give the fitted track to MINUIT
640 gMinuit->SetObjectFit(track);
641 if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
642 // Define print level
643 arg[0] = 1;
644 gMinuit->mnexcm("SET PRI", arg, 1, status);
645 // Print covariance matrix
646 gMinuit->mnexcm("SHO COV", arg, 0, status);
647 } else {
648 arg[0] = -1;
649 gMinuit->mnexcm("SET PRI", arg, 1, status);
650 }
de2cd600 651 // No warnings
208f139e 652 gMinuit->mnexcm("SET NOW", arg, 0, status);
653 // Define strategy
654 //arg[0] = 2;
655 //gMinuit->mnexcm("SET STR", arg, 1, status);
656
657 // Switch between available FCN according to "includeMCS"
658 if (includeMCS) gMinuit->SetFCN(TrackChi2MCS);
659 else gMinuit->SetFCN(TrackChi2);
660
661 // Set fitted parameters (!! The order is very important for the covariance matrix !!)
662 trackParam = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
de2cd600 663 // could be tried with no limits for the search (min=max=0) ????
208f139e 664 // mandatory limits in non Bending to avoid NaN values of parameters
665 gMinuit->mnparm(0, "X", trackParam->GetNonBendingCoor(), 0.03, -500.0, 500.0, status);
666 gMinuit->mnparm(1, "NonBenS", trackParam->GetNonBendingSlope(), 0.001, -0.5, 0.5, status);
667 // mandatory limits in Bending to avoid NaN values of parameters
668 gMinuit->mnparm(2, "Y", trackParam->GetBendingCoor(), 0.10, -500.0, 500.0, status);
669 gMinuit->mnparm(3, "BenS", trackParam->GetBendingSlope(), 0.001, -0.5, 0.5, status);
670 gMinuit->mnparm(4, "InvBenP", trackParam->GetInverseBendingMomentum(), 0.003, -0.4, 0.4, status);
671
de2cd600 672 // minimization
208f139e 673 gMinuit->mnexcm("MIGRAD", arg, 0, status);
674
675 // Calculate the covariance matrix more accurately if required
676 if (calcCov) gMinuit->mnexcm("HESSE", arg, 0, status);
677
de2cd600 678 // get results into "invBenP", "benC", "nonBenC" ("x", "y")
208f139e 679 gMinuit->GetParameter(0, x, errorParam);
680 trackParam->SetNonBendingCoor(x);
681 gMinuit->GetParameter(1, nonBenC, errorParam);
de2cd600 682 trackParam->SetNonBendingSlope(nonBenC);
208f139e 683 gMinuit->GetParameter(2, y, errorParam);
684 trackParam->SetBendingCoor(y);
685 gMinuit->GetParameter(3, benC, errorParam);
686 trackParam->SetBendingSlope(benC);
687 gMinuit->GetParameter(4, invBenP, errorParam);
688 trackParam->SetInverseBendingMomentum(invBenP);
689
de2cd600 690 // global result of the fit
208f139e 691 gMinuit->mnstat(fitFMin, fedm, errdef, npari, nparx, covStatus);
692 track->SetFitFMin(fitFMin);
693
694 // Get the covariance matrix if required
695 if (calcCov) {
696 // Covariance matrix according to HESSE status
697 // If problem then keep only the diagonal terms (variances)
698 Double_t matrix[5][5];
699 gMinuit->mnemat(&matrix[0][0],5);
700 if (covStatus == 3) trackParam->SetCovariances(matrix);
701 else trackParam->SetVariances(matrix);
702 } else *(trackParam->GetCovariances()) = 0;
703
de2cd600 704}
705
706 //__________________________________________________________________________
208f139e 707void TrackChi2(Int_t & /*NParam*/, Double_t * /*Gradient*/, Double_t &Chi2, Double_t *Param, Int_t /*Flag*/)
de2cd600 708{
2457f726 709 /// Return the "Chi2" to be minimized with Minuit for track fitting,
710 /// with "NParam" parameters
711 /// and their current values in array pointed to by "Param".
712 /// Assumes that the track hits are sorted according to increasing Z.
713 /// Track parameters at each TrackHit are updated accordingly.
714 /// Multiple Coulomb scattering is not taken into account
208f139e 715
716 AliMUONTrack *trackBeingFitted = (AliMUONTrack*) gMinuit->GetObjectFit();
717// AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrackReconstructor::Fitter()->GetObjectFit();
de2cd600 718 AliMUONTrackParam param1;
2457f726 719 AliMUONTrackParam* trackParamAtHit;
720 AliMUONHitForRec* hitForRec;
de2cd600 721 Chi2 = 0.0; // initialize Chi2
208f139e 722 Double_t dX, dY;
723
de2cd600 724 // copy of track parameters to be fitted
208f139e 725 param1 = *((AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First()));
726 param1.SetNonBendingCoor(Param[0]);
727 param1.SetNonBendingSlope(Param[1]);
728 param1.SetBendingCoor(Param[2]);
729 param1.SetBendingSlope(Param[3]);
730 param1.SetInverseBendingMomentum(Param[4]);
731
732 // Take the vertex into account in the fit if required
733 if (trackBeingFitted->GetFitWithVertex()) {
734 AliMUONTrackParam paramAtVertex(param1);
735 AliMUONTrackExtrap::ExtrapToZ(&paramAtVertex, 0.);
736 AliMUONHitForRec *vertex = trackBeingFitted->GetVertex();
737 if (!vertex) {
738 cout<<"Error in TrackChi2: Want to use the vertex in tracking but it has not been created!!"<<endl;
739 exit(-1);
740 }
741 dX = vertex->GetNonBendingCoor() - paramAtVertex.GetNonBendingCoor();
742 dY = vertex->GetBendingCoor() - paramAtVertex.GetBendingCoor();
743 Chi2 += dX * dX / vertex->GetNonBendingReso2() + dY * dY / vertex->GetBendingReso2();
de2cd600 744 }
208f139e 745
de2cd600 746 // Follow track through all planes of track hits
2457f726 747 trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First());
748 while (trackParamAtHit) {
749 hitForRec = trackParamAtHit->GetHitForRecPtr();
750 // extrapolation to the plane of the hitForRec attached to the current trackParamAtHit
37827b29 751 AliMUONTrackExtrap::ExtrapToZ(&param1, hitForRec->GetZ());
de2cd600 752 // update track parameters of the current hit
2457f726 753 trackParamAtHit->SetTrackParam(param1);
de2cd600 754 // Increment Chi2
755 // done hit per hit, with hit resolution,
756 // and not with point and angle like in "reco_muon.F" !!!!
208f139e 757 dX = hitForRec->GetNonBendingCoor() - param1.GetNonBendingCoor();
758 dY = hitForRec->GetBendingCoor() - param1.GetBendingCoor();
2457f726 759 Chi2 = Chi2 + dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
760 trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->After(trackParamAtHit));
de2cd600 761 }
762}
763
764 //__________________________________________________________________________
208f139e 765void TrackChi2MCS(Int_t & /*NParam*/, Double_t * /*Gradient*/, Double_t &Chi2, Double_t *Param, Int_t /*Flag*/)
de2cd600 766{
2457f726 767 /// Return the "Chi2" to be minimized with Minuit for track fitting,
768 /// with "NParam" parameters
769 /// and their current values in array pointed to by "Param".
770 /// Assumes that the track hits are sorted according to increasing Z.
771 /// Track parameters at each TrackHit are updated accordingly.
772 /// Multiple Coulomb scattering is taken into account with covariance matrix.
208f139e 773
774 AliMUONTrack *trackBeingFitted = (AliMUONTrack*) gMinuit->GetObjectFit();
775// AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrackReconstructor::Fitter()->GetObjectFit();
de2cd600 776 AliMUONTrackParam param1;
2457f726 777 AliMUONTrackParam* trackParamAtHit;
778 AliMUONHitForRec* hitForRec;
de2cd600 779 Chi2 = 0.0; // initialize Chi2
de2cd600 780 Int_t chCurrent, chPrev = 0, hitNumber, hitNumber1, hitNumber2, hitNumber3;
781 Double_t z1, z2, z3;
2457f726 782 AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2, *trackParamAtHit3;
783 AliMUONHitForRec *hitForRec1, *hitForRec2;
de2cd600 784 Double_t hbc1, hbc2, pbc1, pbc2;
785 Double_t hnbc1, hnbc2, pnbc1, pnbc2;
786 Int_t numberOfHit = trackBeingFitted->GetNTrackHits();
787 TMatrixD *covBending = new TMatrixD(numberOfHit, numberOfHit);
788 TMatrixD *covNonBending = new TMatrixD(numberOfHit, numberOfHit);
789 Double_t *msa2 = new Double_t[numberOfHit];
208f139e 790
791 // copy of track parameters to be fitted
792 param1 = *((AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First()));
793 param1.SetNonBendingCoor(Param[0]);
794 param1.SetNonBendingSlope(Param[1]);
795 param1.SetBendingCoor(Param[2]);
796 param1.SetBendingSlope(Param[3]);
797 param1.SetInverseBendingMomentum(Param[4]);
798
799 // Take the vertex into account in the fit if required
800 if (trackBeingFitted->GetFitWithVertex()) {
801 AliMUONTrackParam paramAtVertex(param1);
802 AliMUONTrackExtrap::ExtrapToZ(&paramAtVertex, 0.);
803 AliMUONHitForRec *vertex = trackBeingFitted->GetVertex();
804 if (!vertex) {
805 cout<<"Error in TrackChi2MCS: Want to use the vertex in tracking but it has not been created!!"<<endl;
806 exit(-1);
807 }
808 Double_t dX = vertex->GetNonBendingCoor() - paramAtVertex.GetNonBendingCoor();
809 Double_t dY = vertex->GetBendingCoor() - paramAtVertex.GetBendingCoor();
810 Chi2 += dX * dX / vertex->GetNonBendingReso2() + dY * dY / vertex->GetBendingReso2();
811 }
812
813 // Predicted coordinates and multiple scattering angles are first calculated
de2cd600 814 for (hitNumber = 0; hitNumber < numberOfHit; hitNumber++) {
2457f726 815 trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber));
816 hitForRec = trackParamAtHit->GetHitForRecPtr();
817 // extrapolation to the plane of the hitForRec attached to the current trackParamAtHit
37827b29 818 AliMUONTrackExtrap::ExtrapToZ(&param1, hitForRec->GetZ());
de2cd600 819 // update track parameters of the current hit
2457f726 820 trackParamAtHit->SetTrackParam(param1);
de2cd600 821 // square of multiple scattering angle at current hit, with one chamber
822 msa2[hitNumber] = MultipleScatteringAngle2(&param1);
823 // correction for eventual missing hits or multiple hits in a chamber,
824 // according to the number of chambers
825 // between the current hit and the previous one
2457f726 826 chCurrent = hitForRec->GetChamberNumber();
de2cd600 827 if (hitNumber > 0) msa2[hitNumber] = msa2[hitNumber] * (chCurrent - chPrev);
828 chPrev = chCurrent;
829 }
830
831 // Calculates the covariance matrix
832 for (hitNumber1 = 0; hitNumber1 < numberOfHit; hitNumber1++) {
2457f726 833 trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
834 hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
835 z1 = hitForRec1->GetZ();
de2cd600 836 for (hitNumber2 = hitNumber1; hitNumber2 < numberOfHit; hitNumber2++) {
2457f726 837 trackParamAtHit2 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber2));
838 z2 = trackParamAtHit2->GetHitForRecPtr()->GetZ();
de2cd600 839 // initialization to 0 (diagonal plus upper triangular part)
840 (*covBending)(hitNumber2, hitNumber1) = 0.0;
841 // contribution from multiple scattering in bending plane:
842 // loop over upstream hits
843 for (hitNumber3 = 0; hitNumber3 < hitNumber1; hitNumber3++) {
2457f726 844 trackParamAtHit3 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber3));
845 z3 = trackParamAtHit3->GetHitForRecPtr()->GetZ();
de2cd600 846 (*covBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1) + ((z1 - z3) * (z2 - z3) * msa2[hitNumber3]);
847 }
848 // equal contribution from multiple scattering in non bending plane
849 (*covNonBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1);
850 if (hitNumber1 == hitNumber2) {
851 // Diagonal elements: add contribution from position measurements
852 // in bending plane
2457f726 853 (*covBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1) + hitForRec1->GetBendingReso2();
de2cd600 854 // and in non bending plane
2457f726 855 (*covNonBending)(hitNumber2, hitNumber1) = (*covNonBending)(hitNumber2, hitNumber1) + hitForRec1->GetNonBendingReso2();
de2cd600 856 } else {
857 // Non diagonal elements: symmetrization
858 // for bending plane
859 (*covBending)(hitNumber1, hitNumber2) = (*covBending)(hitNumber2, hitNumber1);
860 // and non bending plane
861 (*covNonBending)(hitNumber1, hitNumber2) = (*covNonBending)(hitNumber2, hitNumber1);
862 }
863 } // for (hitNumber2 = hitNumber1;...
864 } // for (hitNumber1 = 0;...
865
866 // Inversion of covariance matrices
de2cd600 867 Int_t ifailBending;
208f139e 868 gMinuit->mnvert(&((*covBending)(0,0)), numberOfHit, numberOfHit, numberOfHit, ifailBending);
de2cd600 869 Int_t ifailNonBending;
208f139e 870 gMinuit->mnvert(&((*covNonBending)(0,0)), numberOfHit, numberOfHit, numberOfHit, ifailNonBending);
de2cd600 871
872 // It would be worth trying to calculate the inverse of the covariance matrix
873 // only once per fit, since it cannot change much in principle,
874 // and it would save a lot of computing time !!!!
875
876 // Calculates Chi2
877 if ((ifailBending == 0) && (ifailNonBending == 0)) {
878 // with Multiple Scattering if inversion correct
879 for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) {
2457f726 880 trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
881 hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
882 hbc1 = hitForRec1->GetBendingCoor();
883 pbc1 = trackParamAtHit1->GetBendingCoor();
884 hnbc1 = hitForRec1->GetNonBendingCoor();
885 pnbc1 = trackParamAtHit1->GetNonBendingCoor();
de2cd600 886 for (hitNumber2 = 0; hitNumber2 < numberOfHit; hitNumber2++) {
2457f726 887 trackParamAtHit2 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber2));
888 hitForRec2 = trackParamAtHit2->GetHitForRecPtr();
889 hbc2 = hitForRec2->GetBendingCoor();
890 pbc2 = trackParamAtHit2->GetBendingCoor();
891 hnbc2 = hitForRec2->GetNonBendingCoor();
892 pnbc2 = trackParamAtHit2->GetNonBendingCoor();
de2cd600 893 Chi2 += ((*covBending)(hitNumber2, hitNumber1) * (hbc1 - pbc1) * (hbc2 - pbc2)) +
894 ((*covNonBending)(hitNumber2, hitNumber1) * (hnbc1 - pnbc1) * (hnbc2 - pnbc2));
895 }
896 }
897 } else {
898 // without Multiple Scattering if inversion impossible
899 for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) {
2457f726 900 trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
901 hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
902 hbc1 = hitForRec1->GetBendingCoor();
903 pbc1 = trackParamAtHit1->GetBendingCoor();
904 hnbc1 = hitForRec1->GetNonBendingCoor();
905 pnbc1 = trackParamAtHit1->GetNonBendingCoor();
906 Chi2 += ((hbc1 - pbc1) * (hbc1 - pbc1) / hitForRec1->GetBendingReso2()) +
907 ((hnbc1 - pnbc1) * (hnbc1 - pnbc1) / hitForRec1->GetNonBendingReso2());
de2cd600 908 }
909 }
910
911 delete covBending;
912 delete covNonBending;
913 delete [] msa2;
914}
915
208f139e 916 //__________________________________________________________________________
de2cd600 917Double_t MultipleScatteringAngle2(AliMUONTrackParam *param)
918{
2457f726 919 /// Returns square of multiple Coulomb scattering angle
920 /// from TrackParamAtHit pointed to by "param"
de2cd600 921 Double_t slopeBending, slopeNonBending, radiationLength, inverseBendingMomentum2, inverseTotalMomentum2;
922 Double_t varMultipleScatteringAngle;
de2cd600 923 slopeBending = param->GetBendingSlope();
924 slopeNonBending = param->GetNonBendingSlope();
925 // thickness in radiation length for the current track,
926 // taking local angle into account
208f139e 927 radiationLength = AliMUONConstants::ChamberThicknessInX0() *
de2cd600 928 TMath::Sqrt(1.0 + slopeBending*slopeBending + slopeNonBending*slopeNonBending);
929 inverseBendingMomentum2 = param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum();
930 inverseTotalMomentum2 = inverseBendingMomentum2 * (1.0 + slopeBending * slopeBending) /
931 (1.0 + slopeBending *slopeBending + slopeNonBending * slopeNonBending);
932 varMultipleScatteringAngle = 0.0136 * (1.0 + 0.038 * TMath::Log(radiationLength));
933 // The velocity is assumed to be 1 !!!!
934 varMultipleScatteringAngle = inverseTotalMomentum2 * radiationLength * varMultipleScatteringAngle * varMultipleScatteringAngle;
935 return varMultipleScatteringAngle;
936}
937
208f139e 938 //__________________________________________________________________________
939void AliMUONTrackReconstructor::ExtrapTracksToVertex()
de2cd600 940{
208f139e 941 /// propagate tracks to the vertex through the absorber (Branson)
942 AliMUONTrack *track;
943 AliMUONTrackParam trackParamVertex;
944 AliMUONHitForRec *vertex;
945 Double_t vX, vY, vZ;
946
947 for (Int_t iRecTrack = 0; iRecTrack <fNRecTracks; iRecTrack++) {
948 track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
949 trackParamVertex = *((AliMUONTrackParam*)(track->GetTrackParamAtHit()->First()));
950 vertex = track->GetVertex();
951 if (vertex) { // if track as a vertex defined, use it
952 vX = vertex->GetNonBendingCoor();
953 vY = vertex->GetBendingCoor();
954 vZ = vertex->GetZ();
955 } else { // else vertex = (0.,0.,0.)
956 vX = 0.;
957 vY = 0.;
958 vZ = 0.;
de2cd600 959 }
208f139e 960 AliMUONTrackExtrap::ExtrapToVertex(&trackParamVertex, vX, vY, vZ);
961 track->SetTrackParamAtVertex(&trackParamVertex);
962
963 if (AliLog::GetGlobalDebugLevel() > 0) {
964 cout << "FollowTracks: track candidate(0..): " << iRecTrack
965 << " after extrapolation to vertex" << endl;
966 track->RecursiveDump();
de2cd600 967 }
208f139e 968 }
969
d837040f 970}
971
b8dc484b 972 //__________________________________________________________________________
208f139e 973void AliMUONTrackReconstructor::FillMUONTrack()
b8dc484b 974{
208f139e 975 /// Fill fHitForRecAtHit of AliMUONTrack's
b8dc484b 976 AliMUONTrack *track;
de2cd600 977 AliMUONTrackParam *trackParamAtHit;
b8dc484b 978 track = (AliMUONTrack*) fRecTracksPtr->First();
979 while (track) {
de2cd600 980 trackParamAtHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
981 while (trackParamAtHit) {
982 track->AddHitForRecAtHit(trackParamAtHit->GetHitForRecPtr());
983 trackParamAtHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->After(trackParamAtHit));
984 }
b8dc484b 985 track = (AliMUONTrack*) fRecTracksPtr->After(track);
de2cd600 986 }
b8dc484b 987 return;
988}
989
8429a5e4 990 //__________________________________________________________________________
29f1b13a 991void AliMUONTrackReconstructor::EventDump(void)
04b5ea16 992{
2457f726 993 /// Dump reconstructed event (track parameters at vertex and at first hit),
994 /// and the particle parameters
04b5ea16 995 AliMUONTrack *track;
996 AliMUONTrackParam *trackParam, *trackParam1;
04b5ea16 997 Double_t bendingSlope, nonBendingSlope, pYZ;
998 Double_t pX, pY, pZ, x, y, z, c;
5e671e06 999 Int_t trackIndex, nTrackHits;
04b5ea16 1000
b840996b 1001 AliDebug(1,"****** enter EventDump ******");
1002 AliDebug(1, Form("Number of Reconstructed tracks : %d", fNRecTracks));
1003
04b5ea16 1004 fRecTracksPtr->Compress(); // for simple loop without "Next" since no hole
1005 // Loop over reconstructed tracks
1006 for (trackIndex = 0; trackIndex < fNRecTracks; trackIndex++) {
b840996b 1007 AliDebug(1, Form("track number: %d", trackIndex));
04b5ea16 1008 // function for each track for modularity ????
1009 track = (AliMUONTrack*) ((*fRecTracksPtr)[trackIndex]);
1010 nTrackHits = track->GetNTrackHits();
b840996b 1011 AliDebug(1, Form("Number of track hits: %d ", nTrackHits));
04b5ea16 1012 // track parameters at Vertex
1013 trackParam = track->GetTrackParamAtVertex();
1014 x = trackParam->GetNonBendingCoor();
1015 y = trackParam->GetBendingCoor();
1016 z = trackParam->GetZ();
1017 bendingSlope = trackParam->GetBendingSlope();
1018 nonBendingSlope = trackParam->GetNonBendingSlope();
1019 pYZ = 1/TMath::Abs(trackParam->GetInverseBendingMomentum());
1020 pZ = pYZ/TMath::Sqrt(1+bendingSlope*bendingSlope);
1021 pX = pZ * nonBendingSlope;
1022 pY = pZ * bendingSlope;
1023 c = TMath::Sign(1.0, trackParam->GetInverseBendingMomentum());
b840996b 1024 AliDebug(1, Form("Track parameters at Vertex z= %f: X= %f Y= %f pX= %f pY= %f pZ= %f c= %f\n",
1025 z, x, y, pX, pY, pZ, c));
04b5ea16 1026
1027 // track parameters at first hit
de2cd600 1028 trackParam1 = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
04b5ea16 1029 x = trackParam1->GetNonBendingCoor();
1030 y = trackParam1->GetBendingCoor();
1031 z = trackParam1->GetZ();
1032 bendingSlope = trackParam1->GetBendingSlope();
1033 nonBendingSlope = trackParam1->GetNonBendingSlope();
1034 pYZ = 1/TMath::Abs(trackParam1->GetInverseBendingMomentum());
1035 pZ = pYZ/TMath::Sqrt(1.0 + bendingSlope * bendingSlope);
1036 pX = pZ * nonBendingSlope;
1037 pY = pZ * bendingSlope;
1038 c = TMath::Sign(1.0, trackParam1->GetInverseBendingMomentum());
b840996b 1039 AliDebug(1, Form("track parameters at z= %f: X= %f Y= %f pX= %f pY= %f pZ= %f c= %f\n",
1040 z, x, y, pX, pY, pZ, c));
04b5ea16 1041 }
8f373020 1042 // informations about generated particles NO !!!!!!!!
04b5ea16 1043
88cb7938 1044// for (Int_t iPart = 0; iPart < np; iPart++) {
1045// p = gAlice->Particle(iPart);
1046// printf(" particle %d: type= %d px= %f py= %f pz= %f pdg= %d\n",
1047// iPart, p->GetPdgCode(), p->Px(), p->Py(), p->Pz(), p->GetPdgCode());
1048// }
a9e2aefa 1049 return;
1050}
1051
276c44b7 1052