]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | /* | |
17 | $Log$ | |
bbe35c23 | 18 | Revision 1.8 2001/01/08 11:01:02 gosset |
19 | Modifications used for addendum to Dimuon TDR (JP Cussonneau): | |
20 | *. MaxBendingMomentum to make both a segment and a track (default 500) | |
21 | *. MaxChi2 per degree of freedom to make a track (default 100) | |
22 | *. MinBendingMomentum used also to make a track | |
23 | and not only a segment (default 3) | |
24 | *. wider roads for track search in stations 1 to 3 | |
25 | *. extrapolation to actual Z instead of Z(chamber) in FollowTracks | |
26 | *. in track fit: | |
27 | - limits on parameters X and Y (+/-500) | |
28 | - covariance matrices in double precision | |
29 | - normalization of covariance matrices before inversion | |
30 | - suppression of Minuit printouts | |
31 | *. correction against memory leak (delete extrapHit) in FollowTracks | |
32 | *. RMax to 10 degrees with Z(chamber) instead of fixed values; | |
33 | RMin and Rmax cuts suppressed in NewHitForRecFromGEANT, | |
34 | because useless with realistic geometry | |
35 | ||
d0bfce8d | 36 | Revision 1.7 2000/09/19 15:50:46 gosset |
37 | TrackChi2MCS function: covariance matrix better calculated, | |
38 | taking into account missing planes... | |
39 | ||
eb9c9dab | 40 | Revision 1.6 2000/07/20 12:45:27 gosset |
41 | New "EventReconstructor..." structure, | |
42 | hopefully more adapted to tree/streamer. | |
43 | "AliMUONEventReconstructor::RemoveDoubleTracks" | |
44 | to keep only one track among similar ones. | |
45 | ||
8429a5e4 | 46 | Revision 1.5 2000/07/18 16:04:06 gosset |
47 | AliMUONEventReconstructor package: | |
48 | * a few minor modifications and more comments | |
49 | * a few corrections | |
50 | * right sign for Z of raw clusters | |
51 | * right loop over chambers inside station | |
52 | * symmetrized covariance matrix for measurements (TrackChi2MCS) | |
53 | * right sign of charge in extrapolation (ExtrapToZ) | |
54 | * right zEndAbsorber for Branson correction below 3 degrees | |
55 | * use of TVirtualFitter instead of TMinuit for AliMUONTrack::Fit | |
56 | * no parameter for AliMUONTrack::Fit() but more fit parameters in Track object | |
57 | ||
956019b6 | 58 | Revision 1.4 2000/06/30 10:15:48 gosset |
59 | Changes to EventReconstructor...: | |
60 | precision fit with multiple Coulomb scattering; | |
61 | extrapolation to vertex with Branson correction in absorber (JPC) | |
62 | ||
04b5ea16 | 63 | Revision 1.3 2000/06/25 13:23:28 hristov |
64 | stdlib.h needed for non-Linux compilation | |
65 | ||
f6e92cf4 | 66 | Revision 1.2 2000/06/15 07:58:48 morsch |
67 | Code from MUON-dev joined | |
68 | ||
a9e2aefa | 69 | Revision 1.1.2.3 2000/06/12 10:11:34 morsch |
70 | Dummy copy constructor and assignment operator added | |
71 | ||
72 | Revision 1.1.2.2 2000/06/09 12:58:05 gosset | |
73 | Removed comment beginnings in Log sections of .cxx files | |
74 | Suppressed most violations of coding rules | |
75 | ||
76 | Revision 1.1.2.1 2000/06/07 14:44:53 gosset | |
77 | Addition of files for track reconstruction in C++ | |
78 | */ | |
79 | ||
80 | //__________________________________________________________________________ | |
81 | // | |
82 | // Reconstructed track in ALICE dimuon spectrometer | |
83 | //__________________________________________________________________________ | |
84 | ||
85 | #include "AliMUONTrack.h" | |
86 | ||
87 | #include <iostream.h> | |
88 | ||
89 | #include <TClonesArray.h> | |
04b5ea16 | 90 | #include <TMath.h> |
d0bfce8d | 91 | #include <TMatrixD.h> |
8429a5e4 | 92 | #include <TObjArray.h> |
956019b6 | 93 | #include <TVirtualFitter.h> |
a9e2aefa | 94 | |
95 | #include "AliMUONEventReconstructor.h" | |
96 | #include "AliMUONHitForRec.h" | |
97 | #include "AliMUONSegment.h" | |
98 | #include "AliMUONTrackHit.h" | |
99 | ||
f6e92cf4 | 100 | #include <stdlib.h> |
101 | ||
04b5ea16 | 102 | // Functions to be minimized with Minuit |
a9e2aefa | 103 | void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag); |
04b5ea16 | 104 | void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag); |
105 | ||
106 | Double_t MultipleScatteringAngle2(AliMUONTrackHit *TrackHit); | |
a9e2aefa | 107 | |
108 | ClassImp(AliMUONTrack) // Class implementation in ROOT context | |
109 | ||
956019b6 | 110 | TVirtualFitter* AliMUONTrack::fgFitter = NULL; |
111 | ||
a9e2aefa | 112 | //__________________________________________________________________________ |
113 | AliMUONTrack::AliMUONTrack(AliMUONSegment* BegSegment, AliMUONSegment* EndSegment, AliMUONEventReconstructor* EventReconstructor) | |
114 | { | |
115 | // Constructor from two Segment's | |
116 | fEventReconstructor = EventReconstructor; // link back to EventReconstructor | |
8429a5e4 | 117 | // memory allocation for the TObjArray of pointers to reconstructed TrackHit's |
118 | fTrackHitsPtr = new TObjArray(10); | |
a9e2aefa | 119 | fNTrackHits = 0; |
120 | AddSegment(BegSegment); // add hits from BegSegment | |
121 | AddSegment(EndSegment); // add hits from EndSegment | |
122 | fTrackHitsPtr->Sort(); // sort TrackHits according to increasing Z | |
123 | SetTrackParamAtVertex(); // set track parameters at vertex | |
8429a5e4 | 124 | // set fit conditions... |
04b5ea16 | 125 | fFitMCS = 0; |
956019b6 | 126 | fFitNParam = 3; |
127 | fFitStart = 1; | |
8429a5e4 | 128 | fFitFMin = -1.0; |
a9e2aefa | 129 | return; |
130 | } | |
131 | ||
132 | //__________________________________________________________________________ | |
133 | AliMUONTrack::AliMUONTrack(AliMUONSegment* Segment, AliMUONHitForRec* HitForRec, AliMUONEventReconstructor* EventReconstructor) | |
134 | { | |
135 | // Constructor from one Segment and one HitForRec | |
136 | fEventReconstructor = EventReconstructor; // link back to EventReconstructor | |
8429a5e4 | 137 | // memory allocation for the TObjArray of pointers to reconstructed TrackHit's |
138 | fTrackHitsPtr = new TObjArray(10); | |
a9e2aefa | 139 | fNTrackHits = 0; |
140 | AddSegment(Segment); // add hits from Segment | |
141 | AddHitForRec(HitForRec); // add HitForRec | |
142 | fTrackHitsPtr->Sort(); // sort TrackHits according to increasing Z | |
143 | SetTrackParamAtVertex(); // set track parameters at vertex | |
8429a5e4 | 144 | // set fit conditions... |
04b5ea16 | 145 | fFitMCS = 0; |
956019b6 | 146 | fFitNParam = 3; |
147 | fFitStart = 1; | |
8429a5e4 | 148 | fFitFMin = -1.0; |
a9e2aefa | 149 | return; |
150 | } | |
151 | ||
8429a5e4 | 152 | //__________________________________________________________________________ |
153 | AliMUONTrack::~AliMUONTrack() | |
154 | { | |
155 | // Destructor | |
156 | if (fTrackHitsPtr) { | |
157 | delete fTrackHitsPtr; // delete the TObjArray of pointers to TrackHit's | |
158 | fTrackHitsPtr = NULL; | |
159 | } | |
160 | } | |
161 | ||
956019b6 | 162 | //__________________________________________________________________________ |
a9e2aefa | 163 | AliMUONTrack::AliMUONTrack (const AliMUONTrack& MUONTrack) |
164 | { | |
165 | // Dummy copy constructor | |
166 | } | |
167 | ||
956019b6 | 168 | //__________________________________________________________________________ |
a9e2aefa | 169 | AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& MUONTrack) |
170 | { | |
171 | // Dummy assignment operator | |
172 | return *this; | |
173 | } | |
174 | ||
8429a5e4 | 175 | //__________________________________________________________________________ |
176 | void AliMUONTrack::Remove() | |
177 | { | |
178 | // Remove current track from array of tracks, | |
179 | // and corresponding track hits from array of track hits. | |
180 | // Compress the TClonesArray it belongs to. | |
181 | AliMUONTrackHit *nextTrackHit; | |
182 | AliMUONEventReconstructor *eventRec = this->fEventReconstructor; | |
183 | TClonesArray *trackHitsPtr = eventRec->GetRecTrackHitsPtr(); | |
184 | // Loop over all track hits of track | |
185 | AliMUONTrackHit *trackHit = (AliMUONTrackHit*) fTrackHitsPtr->First(); | |
186 | while (trackHit) { | |
187 | nextTrackHit = (AliMUONTrackHit*) fTrackHitsPtr->After(trackHit); | |
188 | // Remove TrackHit from event TClonesArray. | |
189 | // Destructor is called, | |
190 | // hence links between HitForRec's and TrackHit's are updated | |
191 | trackHitsPtr->Remove(trackHit); | |
192 | trackHit = nextTrackHit; | |
193 | } | |
194 | // Remove the track from event TClonesArray | |
195 | // Destructor is called, | |
196 | // hence space for TObjArray of pointers to TrackHit's is freed | |
197 | eventRec->GetRecTracksPtr()->Remove(this); | |
198 | // Number of tracks decreased by 1 | |
199 | eventRec->SetNRecTracks(eventRec->GetNRecTracks() - 1); | |
200 | // Compress event TClonesArray of Track's: | |
201 | // this is essential to retrieve the TClonesArray afterwards | |
202 | eventRec->GetRecTracksPtr()->Compress(); | |
203 | // Compress event TClonesArray of TrackHit's: | |
204 | // this is probably also essential to retrieve the TClonesArray afterwards | |
205 | trackHitsPtr->Compress(); | |
206 | } | |
207 | ||
04b5ea16 | 208 | //__________________________________________________________________________ |
209 | void AliMUONTrack::SetFitMCS(Int_t FitMCS) | |
210 | { | |
956019b6 | 211 | // Set multiple Coulomb scattering option for track fit "fFitMCS" |
04b5ea16 | 212 | // from "FitMCS" argument: 0 without, 1 with |
956019b6 | 213 | if ((FitMCS == 0) || (FitMCS == 1)) fFitMCS = FitMCS; |
04b5ea16 | 214 | // better implementation with enum(with, without) ???? |
956019b6 | 215 | else { |
216 | cout << "ERROR in AliMUONTrack::SetFitMCS(FitMCS)" << endl; | |
217 | cout << "FitMCS = " << FitMCS << " is neither 0 nor 1" << endl; | |
218 | exit(0); | |
219 | } | |
220 | return; | |
221 | } | |
222 | ||
223 | //__________________________________________________________________________ | |
224 | void AliMUONTrack::SetFitNParam(Int_t FitNParam) | |
225 | { | |
226 | // Set number of parameters for track fit "fFitNParam" from "FitNParam": | |
227 | // 3 for momentum, 5 for momentum and position | |
228 | if ((FitNParam == 3) || (FitNParam == 5)) fFitNParam = FitNParam; | |
229 | else { | |
230 | cout << "ERROR in AliMUONTrack::SetFitNParam(FitNParam)" << endl; | |
231 | cout << "FitNParam = " << FitNParam << " is neither 3 nor 5" << endl; | |
232 | exit(0); | |
233 | } | |
234 | return; | |
235 | } | |
236 | ||
237 | //__________________________________________________________________________ | |
238 | void AliMUONTrack::SetFitStart(Int_t FitStart) | |
239 | { | |
240 | // Set multiple Coulomb scattering option for track fit "fFitStart" | |
241 | // from "FitStart" argument: 0 without, 1 with | |
242 | if ((FitStart == 0) || (FitStart == 1)) fFitStart = FitStart; | |
243 | // better implementation with enum(vertex, firstHit) ???? | |
244 | else { | |
245 | cout << "ERROR in AliMUONTrack::SetFitStart(FitStart)" << endl; | |
246 | cout << "FitStart = " << FitStart << " is neither 0 nor 1" << endl; | |
247 | exit(0); | |
248 | } | |
04b5ea16 | 249 | return; |
250 | } | |
251 | ||
956019b6 | 252 | //__________________________________________________________________________ |
a9e2aefa | 253 | AliMUONTrackParam* AliMUONTrack::GetTrackParamAtFirstHit(void) { |
254 | // Get pointer to TrackParamAtFirstHit | |
255 | return ((AliMUONTrackHit*) (fTrackHitsPtr->First()))->GetTrackParam();} | |
a9e2aefa | 256 | |
257 | //__________________________________________________________________________ | |
258 | void AliMUONTrack::RecursiveDump(void) | |
259 | { | |
260 | // Recursive dump of AliMUONTrack, i.e. with dump of TrackHit's and HitForRec's | |
261 | AliMUONTrackHit *trackHit; | |
262 | AliMUONHitForRec *hitForRec; | |
263 | cout << "Recursive dump of Track: " << this << endl; | |
264 | // Track | |
265 | this->Dump(); | |
266 | for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) { | |
267 | trackHit = (AliMUONTrackHit*) ((*fTrackHitsPtr)[trackHitIndex]); | |
268 | // TrackHit | |
269 | cout << "TrackHit: " << trackHit << " (index: " << trackHitIndex << ")" << endl; | |
270 | trackHit->Dump(); | |
271 | hitForRec = trackHit->GetHitForRecPtr(); | |
272 | // HitForRec | |
273 | cout << "HitForRec: " << hitForRec << endl; | |
274 | hitForRec->Dump(); | |
275 | } | |
276 | return; | |
277 | } | |
278 | ||
8429a5e4 | 279 | //__________________________________________________________________________ |
280 | Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* Track) | |
281 | { | |
282 | // Returns the number of hits in common | |
283 | // between the current track ("this") | |
284 | // and the track pointed to by "Track". | |
285 | Int_t hitsInCommon = 0; | |
286 | AliMUONTrackHit *trackHit1, *trackHit2; | |
287 | // Loop over hits of first track | |
288 | trackHit1 = (AliMUONTrackHit*) this->GetTrackHitsPtr()->First(); | |
289 | while (trackHit1) { | |
290 | // Loop over hits of second track | |
291 | trackHit2 = (AliMUONTrackHit*) Track->GetTrackHitsPtr()->First(); | |
292 | while (trackHit2) { | |
293 | // Increment "hitsInCommon" if both TrackHits point to the same HitForRec | |
294 | if ( (trackHit1->GetHitForRecPtr()) == | |
295 | (trackHit2->GetHitForRecPtr()) ) hitsInCommon++; | |
296 | trackHit2 = (AliMUONTrackHit*) Track->GetTrackHitsPtr()->After(trackHit2); | |
297 | } // trackHit2 | |
298 | trackHit1 = (AliMUONTrackHit*) this->GetTrackHitsPtr()->After(trackHit1); | |
299 | } // trackHit1 | |
300 | return hitsInCommon; | |
301 | } | |
302 | ||
a9e2aefa | 303 | //__________________________________________________________________________ |
956019b6 | 304 | void AliMUONTrack::Fit() |
a9e2aefa | 305 | { |
306 | // Fit the current track ("this"), | |
956019b6 | 307 | // with or without multiple Coulomb scattering according to "fFitMCS", |
308 | // with the number of parameters given by "fFitNParam" | |
309 | // (3 if one keeps X and Y fixed in "TrackParam", 5 if one lets them vary), | |
310 | // starting, according to "fFitStart", | |
311 | // with track parameters at vertex or at the first TrackHit. | |
312 | // "fFitMCS", "fFitNParam" and "fFitStart" have to be set before | |
313 | // by calling the corresponding Set methods. | |
a9e2aefa | 314 | Double_t arg[1], benC, errorParam, invBenP, lower, nonBenC, upper, x, y; |
956019b6 | 315 | char parName[50]; |
316 | AliMUONTrackParam *trackParam; | |
317 | // Check if Minuit is initialized... | |
318 | fgFitter = TVirtualFitter::Fitter(this); // add 3 or 5 for the maximum number of parameters ??? | |
319 | fgFitter->Clear(); // necessary ???? probably yes | |
320 | // how to reset the printout number at every fit ???? | |
321 | // is there any risk to leave it like that ???? | |
a9e2aefa | 322 | // how to go faster ???? choice of Minuit parameters like EDM ???? |
04b5ea16 | 323 | // choice of function to be minimized according to fFitMCS |
956019b6 | 324 | if (fFitMCS == 0) fgFitter->SetFCN(TrackChi2); |
325 | else fgFitter->SetFCN(TrackChi2MCS); | |
d0bfce8d | 326 | arg[0] = -1; |
956019b6 | 327 | fgFitter->ExecuteCommand("SET PRINT", arg, 1); // More printing !!!! |
328 | // Parameters according to "fFitStart" | |
329 | // (should be a function to be used at every place where needed ????) | |
330 | if (fFitStart == 0) trackParam = &fTrackParamAtVertex; | |
331 | else trackParam = this->GetTrackParamAtFirstHit(); | |
332 | // set first 3 Minuit parameters | |
04b5ea16 | 333 | // could be tried with no limits for the search (min=max=0) ???? |
956019b6 | 334 | fgFitter->SetParameter(0, "InvBenP", |
335 | trackParam->GetInverseBendingMomentum(), | |
336 | 0.003, -0.4, 0.4); | |
337 | fgFitter->SetParameter(1, "BenS", | |
338 | trackParam->GetBendingSlope(), | |
339 | 0.001, -0.5, 0.5); | |
340 | fgFitter->SetParameter(2, "NonBenS", | |
341 | trackParam->GetNonBendingSlope(), | |
342 | 0.001, -0.5, 0.5); | |
343 | if (fFitNParam == 5) { | |
d0bfce8d | 344 | // set last 2 Minuit parameters |
345 | // mandatory limits in Bending to avoid NaN values of parameters | |
956019b6 | 346 | fgFitter->SetParameter(3, "X", |
347 | trackParam->GetNonBendingCoor(), | |
d0bfce8d | 348 | 0.03, -500.0, 500.0); |
349 | // mandatory limits in non Bending to avoid NaN values of parameters | |
956019b6 | 350 | fgFitter->SetParameter(4, "Y", |
351 | trackParam->GetBendingCoor(), | |
d0bfce8d | 352 | 0.10, -500.0, 500.0); |
a9e2aefa | 353 | } |
354 | // search without gradient calculation in the function | |
956019b6 | 355 | fgFitter->ExecuteCommand("SET NOGRADIENT", arg, 0); |
a9e2aefa | 356 | // minimization |
956019b6 | 357 | fgFitter->ExecuteCommand("MINIMIZE", arg, 0); |
a9e2aefa | 358 | // exit from Minuit |
956019b6 | 359 | fgFitter->ExecuteCommand("EXIT", arg, 0); // necessary ???? |
360 | // get results into "invBenP", "benC", "nonBenC" ("x", "y") | |
361 | fgFitter->GetParameter(0, parName, invBenP, errorParam, lower, upper); | |
362 | fgFitter->GetParameter(1, parName, benC, errorParam, lower, upper); | |
363 | fgFitter->GetParameter(2, parName, nonBenC, errorParam, lower, upper); | |
364 | if (fFitNParam == 5) { | |
365 | fgFitter->GetParameter(3, parName, x, errorParam, lower, upper); | |
366 | fgFitter->GetParameter(4, parName, y, errorParam, lower, upper); | |
a9e2aefa | 367 | } |
368 | // result of the fit into track parameters | |
956019b6 | 369 | trackParam->SetInverseBendingMomentum(invBenP); |
370 | trackParam->SetBendingSlope(benC); | |
371 | trackParam->SetNonBendingSlope(nonBenC); | |
372 | if (fFitNParam == 5) { | |
373 | trackParam->SetNonBendingCoor(x); | |
374 | trackParam->SetBendingCoor(y); | |
a9e2aefa | 375 | } |
8429a5e4 | 376 | // global result of the fit |
377 | Double_t fedm, errdef; | |
378 | Int_t npari, nparx; | |
379 | fgFitter->GetStats(fFitFMin, fedm, errdef, npari, nparx); | |
a9e2aefa | 380 | } |
381 | ||
382 | //__________________________________________________________________________ | |
383 | void AliMUONTrack::AddSegment(AliMUONSegment* Segment) | |
384 | { | |
8429a5e4 | 385 | // Add Segment to the track |
a9e2aefa | 386 | AddHitForRec(Segment->GetHitForRec1()); // 1st hit |
387 | AddHitForRec(Segment->GetHitForRec2()); // 2nd hit | |
388 | } | |
389 | ||
390 | //__________________________________________________________________________ | |
391 | void AliMUONTrack::AddHitForRec(AliMUONHitForRec* HitForRec) | |
392 | { | |
8429a5e4 | 393 | // Add HitForRec to the track: |
394 | // actual TrackHit into TClonesArray of TrackHit's for the event; | |
395 | // pointer to actual TrackHit in TObjArray of pointers to TrackHit's for the track | |
396 | TClonesArray *recTrackHitsPtr = this->fEventReconstructor->GetRecTrackHitsPtr(); | |
397 | Int_t eventTrackHits = this->fEventReconstructor->GetNRecTrackHits(); | |
398 | // event | |
399 | AliMUONTrackHit* trackHit = | |
400 | new ((*recTrackHitsPtr)[eventTrackHits]) AliMUONTrackHit(HitForRec); | |
401 | this->fEventReconstructor->SetNRecTrackHits(eventTrackHits + 1); | |
402 | // track | |
403 | fTrackHitsPtr->Add(trackHit); | |
a9e2aefa | 404 | fNTrackHits++; |
405 | } | |
406 | ||
407 | //__________________________________________________________________________ | |
408 | void AliMUONTrack::SetTrackParamAtHit(Int_t indexHit, AliMUONTrackParam *TrackParam) | |
409 | { | |
410 | // Set track parameters at TrackHit with index "indexHit" | |
411 | // from the track parameters pointed to by "TrackParam". | |
412 | AliMUONTrackHit* trackHit = (AliMUONTrackHit*) ((*fTrackHitsPtr)[indexHit]); | |
413 | trackHit->SetTrackParam(TrackParam); | |
414 | } | |
415 | ||
416 | //__________________________________________________________________________ | |
417 | void AliMUONTrack::SetTrackParamAtVertex() | |
418 | { | |
419 | // Set track parameters at vertex. | |
420 | // TrackHit's are assumed to be only in stations(1..) 4 and 5, | |
421 | // and sorted according to increasing Z.. | |
422 | // Parameters are calculated from information in HitForRec's | |
423 | // of first and last TrackHit's. | |
424 | AliMUONTrackParam *trackParam = | |
425 | &fTrackParamAtVertex; // pointer to track parameters | |
426 | // Pointer to HitForRec of first TrackHit | |
427 | AliMUONHitForRec *firstHit = | |
428 | ((AliMUONTrackHit*) (fTrackHitsPtr->First()))->GetHitForRecPtr(); | |
429 | // Pointer to HitForRec of last TrackHit | |
430 | AliMUONHitForRec *lastHit = | |
431 | ((AliMUONTrackHit*) (fTrackHitsPtr->Last()))->GetHitForRecPtr(); | |
432 | // Z difference between first and last hits | |
433 | Double_t deltaZ = firstHit->GetZ() - lastHit->GetZ(); | |
434 | // bending slope in stations(1..) 4 and 5 | |
435 | Double_t bendingSlope = | |
436 | (firstHit->GetBendingCoor() - lastHit->GetBendingCoor()) / deltaZ; | |
437 | trackParam->SetBendingSlope(bendingSlope); | |
438 | // impact parameter | |
439 | Double_t impactParam = | |
440 | firstHit->GetBendingCoor() - bendingSlope * firstHit->GetZ(); // same if from firstHit and lastHit ???? | |
441 | // signed bending momentum | |
442 | Double_t signedBendingMomentum = | |
443 | fEventReconstructor->GetBendingMomentumFromImpactParam(impactParam); | |
444 | trackParam->SetInverseBendingMomentum(1.0 / signedBendingMomentum); | |
445 | // bending slope at vertex | |
446 | trackParam-> | |
447 | SetBendingSlope(bendingSlope + | |
448 | impactParam / fEventReconstructor->GetSimpleBPosition()); | |
449 | // non bending slope | |
450 | Double_t nonBendingSlope = | |
451 | (firstHit->GetNonBendingCoor() - lastHit->GetNonBendingCoor()) / deltaZ; | |
452 | trackParam->SetNonBendingSlope(nonBendingSlope); | |
453 | // vertex coordinates at (0,0,0) | |
454 | trackParam->SetZ(0.0); | |
455 | trackParam->SetBendingCoor(0.0); | |
456 | trackParam->SetNonBendingCoor(0.0); | |
457 | } | |
458 | ||
459 | //__________________________________________________________________________ | |
460 | void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag) | |
461 | { | |
462 | // Return the "Chi2" to be minimized with Minuit for track fitting, | |
463 | // with "NParam" parameters | |
464 | // and their current values in array pointed to by "Param". | |
465 | // Assumes that the track hits are sorted according to increasing Z. | |
466 | // Track parameters at each TrackHit are updated accordingly. | |
04b5ea16 | 467 | // Multiple Coulomb scattering is not taken into account |
956019b6 | 468 | AliMUONTrack *trackBeingFitted; |
a9e2aefa | 469 | AliMUONTrackHit* hit; |
470 | AliMUONTrackParam param1; | |
471 | Int_t hitNumber; | |
472 | Double_t zHit; | |
473 | Chi2 = 0.0; // initialize Chi2 | |
474 | // copy of track parameters to be fitted | |
956019b6 | 475 | trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit(); |
476 | if (trackBeingFitted->GetFitStart() == 0) | |
477 | param1 = *(trackBeingFitted->GetTrackParamAtVertex()); | |
478 | else param1 = *(trackBeingFitted->GetTrackParamAtFirstHit()); | |
a9e2aefa | 479 | // Minuit parameters to be fitted into this copy |
480 | param1.SetInverseBendingMomentum(Param[0]); | |
481 | param1.SetBendingSlope(Param[1]); | |
482 | param1.SetNonBendingSlope(Param[2]); | |
483 | if (NParam == 5) { | |
484 | param1.SetNonBendingCoor(Param[3]); | |
485 | param1.SetBendingCoor(Param[4]); | |
486 | } | |
487 | // Follow track through all planes of track hits | |
488 | for (hitNumber = 0; hitNumber < trackBeingFitted->GetNTrackHits(); hitNumber++) { | |
489 | hit = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber]; | |
490 | zHit = hit->GetHitForRecPtr()->GetZ(); | |
491 | // do something special if 2 hits with same Z ???? | |
492 | // security against infinite loop ???? | |
493 | (¶m1)->ExtrapToZ(zHit); // extrapolation | |
494 | hit->SetTrackParam(¶m1); | |
495 | // Increment Chi2 | |
496 | // done hit per hit, with hit resolution, | |
497 | // and not with point and angle like in "reco_muon.F" !!!! | |
498 | // Needs to add multiple scattering contribution ???? | |
499 | Double_t dX = | |
500 | hit->GetHitForRecPtr()->GetNonBendingCoor() - (¶m1)->GetNonBendingCoor(); | |
501 | Double_t dY = | |
502 | hit->GetHitForRecPtr()->GetBendingCoor() - (¶m1)->GetBendingCoor(); | |
503 | Chi2 = | |
504 | Chi2 + | |
505 | dX * dX / hit->GetHitForRecPtr()->GetNonBendingReso2() + | |
506 | dY * dY / hit->GetHitForRecPtr()->GetBendingReso2(); | |
507 | } | |
508 | } | |
04b5ea16 | 509 | |
510 | //__________________________________________________________________________ | |
511 | void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag) | |
512 | { | |
513 | // Return the "Chi2" to be minimized with Minuit for track fitting, | |
514 | // with "NParam" parameters | |
515 | // and their current values in array pointed to by "Param". | |
516 | // Assumes that the track hits are sorted according to increasing Z. | |
517 | // Track parameters at each TrackHit are updated accordingly. | |
518 | // Multiple Coulomb scattering is taken into account with covariance matrix. | |
956019b6 | 519 | AliMUONTrack *trackBeingFitted; |
04b5ea16 | 520 | AliMUONTrackParam param1; |
521 | Chi2 = 0.0; // initialize Chi2 | |
522 | // copy of track parameters to be fitted | |
956019b6 | 523 | trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit(); |
524 | if (trackBeingFitted->GetFitStart() == 0) | |
525 | param1 = *(trackBeingFitted->GetTrackParamAtVertex()); | |
526 | else param1 = *(trackBeingFitted->GetTrackParamAtFirstHit()); | |
04b5ea16 | 527 | // Minuit parameters to be fitted into this copy |
528 | param1.SetInverseBendingMomentum(Param[0]); | |
529 | param1.SetBendingSlope(Param[1]); | |
530 | param1.SetNonBendingSlope(Param[2]); | |
531 | if (NParam == 5) { | |
532 | param1.SetNonBendingCoor(Param[3]); | |
533 | param1.SetBendingCoor(Param[4]); | |
534 | } | |
535 | ||
956019b6 | 536 | AliMUONTrackHit *hit; |
537 | Bool_t goodDeterminant; | |
bbe35c23 | 538 | Int_t chCurrent, chPrev = 0, hitNumber, hitNumber1, hitNumber2, hitNumber3; |
eb9c9dab | 539 | Double_t z, z1, z2, z3; |
540 | AliMUONTrackHit *hit1, *hit2, *hit3; | |
541 | Double_t hbc1, hbc2, pbc1, pbc2; | |
542 | Double_t hnbc1, hnbc2, pnbc1, pnbc2; | |
543 | Int_t numberOfHit = trackBeingFitted->GetNTrackHits(); | |
d0bfce8d | 544 | TMatrixD *covBending = new TMatrixD(numberOfHit, numberOfHit); |
545 | TMatrixD *covNonBending = new TMatrixD(numberOfHit, numberOfHit); | |
eb9c9dab | 546 | Double_t *msa2 = new Double_t[numberOfHit]; |
04b5ea16 | 547 | |
548 | // Predicted coordinates and multiple scattering angles are first calculated | |
549 | for (hitNumber = 0; hitNumber < numberOfHit; hitNumber++) { | |
550 | hit = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber]; | |
eb9c9dab | 551 | z = hit->GetHitForRecPtr()->GetZ(); |
04b5ea16 | 552 | // do something special if 2 hits with same Z ???? |
553 | // security against infinite loop ???? | |
eb9c9dab | 554 | (¶m1)->ExtrapToZ(z); // extrapolation |
04b5ea16 | 555 | hit->SetTrackParam(¶m1); |
eb9c9dab | 556 | // square of multiple scattering angle at current hit, with one chamber |
557 | msa2[hitNumber] = MultipleScatteringAngle2(hit); | |
558 | // correction for eventual missing hits or multiple hits in a chamber, | |
559 | // according to the number of chambers | |
560 | // between the current hit and the previous one | |
561 | chCurrent = hit->GetHitForRecPtr()->GetChamberNumber(); | |
562 | if (hitNumber > 0) msa2[hitNumber] = msa2[hitNumber] * (chCurrent - chPrev); | |
563 | chPrev = chCurrent; | |
04b5ea16 | 564 | } |
565 | ||
566 | // Calculates the covariance matrix | |
eb9c9dab | 567 | for (hitNumber1 = 0; hitNumber1 < numberOfHit; hitNumber1++) { |
568 | hit1 = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber1]; | |
569 | z1 = hit1->GetHitForRecPtr()->GetZ(); | |
04b5ea16 | 570 | for (hitNumber2 = hitNumber1; hitNumber2 < numberOfHit; hitNumber2++) { |
eb9c9dab | 571 | hit2 = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber2]; |
572 | z2 = hit2->GetHitForRecPtr()->GetZ(); | |
956019b6 | 573 | // initialization to 0 (diagonal plus upper triangular part) |
574 | (*covBending)(hitNumber2, hitNumber1) = 0.0; | |
575 | // contribution from multiple scattering in bending plane: | |
576 | // loop over upstream hits | |
577 | for (hitNumber3 = 0; hitNumber3 < hitNumber1; hitNumber3++) { | |
eb9c9dab | 578 | hit3 = (AliMUONTrackHit*) |
579 | (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber3]; | |
580 | z3 = hit3->GetHitForRecPtr()->GetZ(); | |
04b5ea16 | 581 | (*covBending)(hitNumber2, hitNumber1) = |
582 | (*covBending)(hitNumber2, hitNumber1) + | |
eb9c9dab | 583 | ((z1 - z3) * (z2 - z3) * msa2[hitNumber3]); |
956019b6 | 584 | } |
585 | // equal contribution from multiple scattering in non bending plane | |
04b5ea16 | 586 | (*covNonBending)(hitNumber2, hitNumber1) = |
587 | (*covBending)(hitNumber2, hitNumber1); | |
956019b6 | 588 | if (hitNumber1 == hitNumber2) { |
589 | // Diagonal elements: add contribution from position measurements | |
590 | // in bending plane | |
591 | (*covBending)(hitNumber2, hitNumber1) = | |
eb9c9dab | 592 | (*covBending)(hitNumber2, hitNumber1) + |
593 | hit1->GetHitForRecPtr()->GetBendingReso2(); | |
956019b6 | 594 | // and in non bending plane |
04b5ea16 | 595 | (*covNonBending)(hitNumber2, hitNumber1) = |
eb9c9dab | 596 | (*covNonBending)(hitNumber2, hitNumber1) + |
597 | hit1->GetHitForRecPtr()->GetNonBendingReso2(); | |
956019b6 | 598 | } |
599 | else { | |
600 | // Non diagonal elements: symmetrization | |
601 | // for bending plane | |
602 | (*covBending)(hitNumber1, hitNumber2) = | |
603 | (*covBending)(hitNumber2, hitNumber1); | |
604 | // and non bending plane | |
605 | (*covNonBending)(hitNumber1, hitNumber2) = | |
606 | (*covNonBending)(hitNumber2, hitNumber1); | |
607 | } | |
608 | } // for (hitNumber2 = hitNumber1;... | |
609 | } // for (hitNumber1 = 0;... | |
d0bfce8d | 610 | // Normalization of covariance matrices |
611 | Double_t normCovBending2 = covBending->E2Norm(); | |
612 | Double_t normCovNonBending2 = covNonBending->E2Norm(); | |
613 | (*covBending) *= 1/normCovBending2; | |
614 | (*covNonBending) *= 1/normCovNonBending2; | |
615 | // if (covBending->Determinant() < 1.e-33) { | |
616 | // printf(" *** covBending *** \n"); | |
617 | // covBending->Print(); | |
618 | // printf(" *** covNonBending *** \n"); | |
619 | // covNonBending->Print(); | |
620 | // cout << " number of hits " << numberOfHit << endl; | |
621 | // cout << "Momentum = " << 1/Param[0] <<endl; | |
622 | // cout << "normCovBending = " << normCovBending2 << endl; | |
623 | // cout << "normCovNonBending = " << normCovNonBending2 << endl; | |
624 | // exit(0); | |
625 | ||
626 | // } | |
04b5ea16 | 627 | // Inverts covariance matrix |
956019b6 | 628 | goodDeterminant = kTRUE; |
629 | // check whether the Invert method returns flag if matrix cannot be inverted, | |
630 | // and do not calculate the Determinant in that case !!!! | |
04b5ea16 | 631 | if (covBending->Determinant() != 0) { |
632 | covBending->Invert(); | |
633 | } else { | |
956019b6 | 634 | goodDeterminant = kFALSE; |
04b5ea16 | 635 | cout << "Warning in ChiMCS Determinant Bending=0: " << endl; |
636 | } | |
956019b6 | 637 | if (covNonBending->Determinant() != 0) { |
04b5ea16 | 638 | covNonBending->Invert(); |
639 | } else { | |
956019b6 | 640 | goodDeterminant = kFALSE; |
04b5ea16 | 641 | cout << "Warning in ChiMCS Determinant non Bending=0: " << endl; |
642 | } | |
956019b6 | 643 | |
644 | // It would be worth trying to calculate the inverse of the covariance matrix | |
645 | // only once per fit, since it cannot change much in principle, | |
646 | // and it would save a lot of computing time !!!! | |
04b5ea16 | 647 | |
648 | // Calculates Chi2 | |
eb9c9dab | 649 | if (goodDeterminant) { |
650 | // with Multiple Scattering if inversion correct | |
d0bfce8d | 651 | // Inverse matrices without normalization |
652 | (*covBending) *= 1/normCovBending2; | |
653 | (*covNonBending) *= 1/normCovNonBending2; | |
eb9c9dab | 654 | for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) { |
655 | hit1 = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber1]; | |
656 | hbc1 = hit1->GetHitForRecPtr()->GetBendingCoor(); | |
657 | pbc1 = hit1->GetTrackParam()->GetBendingCoor(); | |
658 | hnbc1 = hit1->GetHitForRecPtr()->GetNonBendingCoor(); | |
659 | pnbc1 = hit1->GetTrackParam()->GetNonBendingCoor(); | |
660 | for (hitNumber2 = 0; hitNumber2 < numberOfHit; hitNumber2++) { | |
661 | hit2 = (AliMUONTrackHit*) | |
662 | (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber2]; | |
663 | hbc2 = hit2->GetHitForRecPtr()->GetBendingCoor(); | |
664 | pbc2 = hit2->GetTrackParam()->GetBendingCoor(); | |
665 | hnbc2 = hit2->GetHitForRecPtr()->GetNonBendingCoor(); | |
666 | pnbc2 = hit2->GetTrackParam()->GetNonBendingCoor(); | |
04b5ea16 | 667 | Chi2 = Chi2 + |
eb9c9dab | 668 | ((*covBending)(hitNumber2, hitNumber1) * |
669 | (hbc1 - pbc1) * (hbc2 - pbc2)) + | |
04b5ea16 | 670 | ((*covNonBending)(hitNumber2, hitNumber1) * |
eb9c9dab | 671 | (hnbc1 - pnbc1) * (hnbc2 - pnbc2)); |
04b5ea16 | 672 | } |
673 | } | |
eb9c9dab | 674 | } else { |
675 | // without Multiple Scattering if inversion impossible | |
676 | for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) { | |
677 | hit1 = (AliMUONTrackHit*) (*(trackBeingFitted->GetTrackHitsPtr()))[hitNumber1]; | |
678 | hbc1 = hit1->GetHitForRecPtr()->GetBendingCoor(); | |
679 | pbc1 = hit1->GetTrackParam()->GetBendingCoor(); | |
680 | hnbc1 = hit1->GetHitForRecPtr()->GetNonBendingCoor(); | |
681 | pnbc1 = hit1->GetTrackParam()->GetNonBendingCoor(); | |
682 | Chi2 = Chi2 + | |
683 | ((hbc1 - pbc1) * (hbc1 - pbc1) / | |
684 | hit1->GetHitForRecPtr()->GetBendingReso2()) + | |
685 | ((hnbc1 - pnbc1) * (hnbc1 - pnbc1) / | |
686 | hit1->GetHitForRecPtr()->GetNonBendingReso2()); | |
04b5ea16 | 687 | } |
688 | } | |
689 | ||
690 | delete covBending; | |
691 | delete covNonBending; | |
eb9c9dab | 692 | delete [] msa2; |
04b5ea16 | 693 | } |
694 | ||
695 | Double_t MultipleScatteringAngle2(AliMUONTrackHit *TrackHit) | |
696 | { | |
697 | // Returns square of multiple Coulomb scattering angle | |
698 | // at TrackHit pointed to by "TrackHit" | |
699 | Double_t slopeBending, slopeNonBending, radiationLength, inverseBendingMomentum2, inverseTotalMomentum2; | |
700 | Double_t varMultipleScatteringAngle; | |
956019b6 | 701 | AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrack::Fitter()->GetObjectFit(); |
04b5ea16 | 702 | AliMUONTrackParam *param = TrackHit->GetTrackParam(); |
956019b6 | 703 | // Better implementation in AliMUONTrack class ???? |
04b5ea16 | 704 | slopeBending = param->GetBendingSlope(); |
705 | slopeNonBending = param->GetNonBendingSlope(); | |
706 | // thickness in radiation length for the current track, | |
707 | // taking local angle into account | |
708 | radiationLength = | |
709 | trackBeingFitted->GetEventReconstructor()->GetChamberThicknessInX0() * | |
710 | TMath::Sqrt(1.0 + | |
711 | slopeBending * slopeBending + slopeNonBending * slopeNonBending); | |
712 | inverseBendingMomentum2 = | |
713 | param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum(); | |
714 | inverseTotalMomentum2 = | |
956019b6 | 715 | inverseBendingMomentum2 * (1.0 + slopeBending * slopeBending) / |
04b5ea16 | 716 | (1.0 + slopeBending *slopeBending + slopeNonBending * slopeNonBending); |
717 | varMultipleScatteringAngle = 0.0136 * (1.0 + 0.038 * TMath::Log(radiationLength)); | |
956019b6 | 718 | // The velocity is assumed to be 1 !!!! |
04b5ea16 | 719 | varMultipleScatteringAngle = inverseTotalMomentum2 * radiationLength * |
720 | varMultipleScatteringAngle * varMultipleScatteringAngle; | |
721 | return varMultipleScatteringAngle; | |
722 | } |