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