]>
Commit | Line | Data |
---|---|---|
0e676e3f | 1 | // Author: Artur Szostak |
2 | // Email: artur@alice.phy.uct.ac.za | artursz@iafrica.com | |
3 | ||
4 | #include "AliHLTMUONTracker.h" | |
5 | #include "Tracking/MansoTracker.hpp" | |
6 | #include "AliMUONDataInterface.h" | |
7 | #include "AliRunLoader.h" | |
8 | #include "AliLog.h" | |
9 | #include "AliESD.h" | |
10 | #include "AliESDMuonTrack.h" | |
11 | ||
12 | ClassImp(AliHLTMUONTracker) | |
13 | ||
14 | ||
77650318 | 15 | AliHLTMUONTracker::AliHLTMUONTracker(AliRunLoader* runloader) : |
16 | AliTracker(), fdHLT(NULL), fTriggers(NULL), fClusters(NULL), fTracks(NULL) | |
0e676e3f | 17 | { |
69d7cf2e | 18 | // Creates the the AliHLTMUONMicrodHLT object and its associated data source and sink |
19 | // objects. The AliHLTMUONMicrodHLT object is then initialised by hooking to these objects. | |
0e676e3f | 20 | |
21 | AliDebug(2, Form("Called for object 0x%X and with runloader = 0x%X", (ULong_t)this, (ULong_t)runloader)); | |
22 | ||
23 | // Create the dHLT objects. | |
69d7cf2e | 24 | fdHLT = new AliHLTMUONMicrodHLT(); |
25 | fTriggers = new AliHLTMUONTriggerSource(); | |
26 | fClusters = new AliHLTMUONClusterSource(); | |
27 | fTracks = new AliHLTMUONTrackSink(); | |
0e676e3f | 28 | |
29 | // Hook up all the objects. | |
30 | fdHLT->SetTriggerSource(fTriggers); | |
31 | fdHLT->SetClusterSource(fClusters); | |
32 | fdHLT->SetTrackSink(fTracks); | |
33 | } | |
34 | ||
35 | ||
36 | AliHLTMUONTracker::~AliHLTMUONTracker() | |
37 | { | |
38 | // Deletes all dHLT objects created in the constructor. | |
39 | ||
40 | AliDebug(2, Form("Called for object 0x%X", (ULong_t)this)); | |
41 | delete fTracks; | |
42 | delete fClusters; | |
43 | delete fTriggers; | |
44 | delete fdHLT; | |
45 | } | |
46 | ||
47 | ||
48 | Int_t AliHLTMUONTracker::LoadClusters(TTree* data) | |
49 | { | |
50 | // Fills the trigger and cluster data source from the current runloader. | |
51 | // The runloader must be open and initialised properly. | |
52 | ||
53 | AliDebug(1, Form("Called for object 0x%X and with data tree = 0x%X", (ULong_t)this, (ULong_t)data)); | |
54 | ||
55 | // Initialise the MUON data interface to use current runloader. | |
56 | AliMUONDataInterface di; | |
57 | di.UseCurrentRunLoader(); | |
58 | AliDebug(2, Form("Loading for event %d", di.CurrentEvent())); | |
59 | ||
60 | // Load the trigger records. | |
3a682eae | 61 | fTriggers->DataToUse(AliHLTMUONTriggerSource::kFromLocalTriggers); |
0e676e3f | 62 | fTriggers->FillFrom(&di, di.CurrentEvent()); |
63 | ||
64 | #ifndef LOG_NO_DEBUG | |
65 | TString str = "====================== Loaded Triggers ========================\nTrig#\tSign\tPt\t\tX1\t\tY1\t\tX2\t\tY2\n"; | |
66 | for (fTriggers->GetFirstEvent(); fTriggers->MoreEvents(); fTriggers->GetNextEvent()) | |
67 | for (fTriggers->GetFirstBlock(); fTriggers->MoreBlocks(); fTriggers->GetNextBlock()) | |
68 | for (fTriggers->GetFirstTrigger(); fTriggers->MoreTriggers(); fTriggers->GetNextTrigger()) | |
69 | { | |
69d7cf2e | 70 | const AliHLTMUONTriggerRecord* trig = fTriggers->GetTrigger(); |
0e676e3f | 71 | str += trig->TriggerNumber(); |
72 | str += "\t"; | |
73 | str += trig->ParticleSign(); | |
74 | str += "\t"; | |
75 | str += trig->Pt(); | |
76 | str += "\t"; | |
26538635 | 77 | str += trig->Station1Point().X(); |
0e676e3f | 78 | str += "\t"; |
26538635 | 79 | str += trig->Station1Point().Y(); |
0e676e3f | 80 | str += "\t"; |
26538635 | 81 | str += trig->Station2Point().X(); |
0e676e3f | 82 | str += "\t"; |
26538635 | 83 | str += trig->Station2Point().Y(); |
0e676e3f | 84 | str += "\n"; |
85 | } | |
86 | AliDebug(5, str); | |
87 | #endif // LOG_NO_DEBUG | |
88 | ||
89 | // Load cluster points (reconstructed hits) | |
3a682eae | 90 | fClusters->DataToUse(AliHLTMUONClusterSource::kFromRawClusters); |
0e676e3f | 91 | fClusters->FillFrom(&di, di.CurrentEvent()); |
92 | ||
93 | #ifndef LOG_NO_DEBUG | |
94 | str = "====================== Loaded Clusters ========================\nChamber\tX\t\tY\n"; | |
95 | for (fClusters->GetFirstEvent(); fClusters->MoreEvents(); fClusters->GetNextEvent()) | |
96 | for (fClusters->GetFirstBlock(); fClusters->MoreBlocks(); fClusters->GetNextBlock()) | |
97 | for (fClusters->GetFirstCluster(); fClusters->MoreClusters(); fClusters->GetNextCluster()) | |
98 | { | |
99 | Float_t x, y; | |
100 | fClusters->FetchCluster(x, y); | |
101 | str += fClusters->Chamber(); | |
102 | str += "\t"; | |
103 | str += x; | |
104 | str += "\t"; | |
105 | str += y; | |
106 | str += "\n"; | |
107 | } | |
108 | AliDebug(5, str); | |
109 | #endif // LOG_NO_DEBUG | |
110 | ||
111 | return 0; | |
112 | } | |
113 | ||
114 | ||
115 | void AliHLTMUONTracker::UnloadClusters() | |
116 | { | |
117 | // Frees the triggers and clusters loaded in LoadClusters(). | |
118 | ||
119 | AliDebug(1, Form("Called for object 0x%X", (ULong_t)this)); | |
120 | ||
121 | // Release internal arrays. | |
122 | fTriggers->Clear(); | |
123 | fClusters->Clear(); | |
124 | ||
125 | return; | |
126 | } | |
127 | ||
128 | ||
69d7cf2e | 129 | const AliHLTMUONTriggerRecord* |
130 | AliHLTMUONTracker::FindTriggerRecord(const AliHLTMUONTrack* track) const | |
0e676e3f | 131 | { |
132 | // Finds the corresponding trigger record object for the given track. | |
133 | // This is doen by matching up the trigger record number with the trigger | |
134 | // record ID number in the track. | |
135 | ||
136 | fTriggers->GetEvent( fTracks->CurrentEvent() ); | |
137 | for (fTriggers->GetFirstBlock(); fTriggers->MoreBlocks(); fTriggers->GetNextBlock()) | |
138 | for (fTriggers->GetFirstTrigger(); fTriggers->MoreTriggers(); fTriggers->GetNextTrigger()) | |
139 | { | |
69d7cf2e | 140 | const AliHLTMUONTriggerRecord* trigrec = fTriggers->GetTrigger(); |
0e676e3f | 141 | if ( trigrec->TriggerNumber() == track->TriggerID() ) |
142 | return trigrec; | |
143 | } | |
144 | return NULL; | |
145 | } | |
146 | ||
147 | ||
148 | void AliHLTMUONTracker::LeastSquaresFit(const Double_t x[4], const Double_t y[4], Double_t& m, Double_t& c) const | |
149 | { | |
150 | // Least squares fit for a 4 point line: y = m*x + c | |
151 | ||
152 | Double_t n = 4.; // Number of data points. | |
153 | ||
154 | // Compute the sums. | |
155 | Double_t sumx, sumy, sumxx, sumxy; | |
156 | sumx = sumy = sumxx = sumxy = 0.; | |
157 | for (Int_t i = 0; i < 4; i++) | |
158 | { | |
159 | sumx += x[i]; | |
160 | sumy += y[i]; | |
161 | sumxx += x[i] * x[i]; | |
162 | sumxy += x[i] * y[i]; | |
163 | } | |
164 | // Now compute the denominator then m and c parameters. | |
165 | Double_t denom = n*sumxx - sumx*sumx; | |
166 | m = (n*sumxy - sumx*sumy) / denom; | |
167 | c = (sumy*sumxx - sumx*sumxy) / denom; | |
168 | } | |
169 | ||
170 | ||
69d7cf2e | 171 | Double_t AliHLTMUONTracker::ComputeChi2(const AliHLTMUONTrack* track) const |
0e676e3f | 172 | { |
173 | // Computes the Chi^2 for the line fit of the found track fragment. | |
174 | ||
69d7cf2e | 175 | const AliHLTMUONTriggerRecord* trigrec = FindTriggerRecord(track); |
0e676e3f | 176 | if (trigrec == NULL) return -1.; |
177 | AliDebug(10, Form("Found trigger #%d, particle sign = %d, pt = %f", | |
178 | trigrec->TriggerNumber(), | |
179 | trigrec->ParticleSign(), | |
180 | trigrec->Pt() | |
181 | ) | |
182 | ); | |
183 | ||
184 | // Initialise X, Y and Z coordinate arrays. | |
185 | Double_t st4x, st4y, st4z, st5x, st5y, st5z; | |
26538635 | 186 | if (track->Hit(6).X() == 0. && track->Hit(6).Y() == 0.) |
0e676e3f | 187 | { |
26538635 | 188 | st4x = track->Hit(7).X(); |
189 | st4y = track->Hit(7).Y(); | |
69d7cf2e | 190 | st4z = AliHLTMUONCoreMansoTracker::GetZ8(); |
0e676e3f | 191 | } |
192 | else | |
193 | { | |
26538635 | 194 | st4x = track->Hit(6).X(); |
195 | st4y = track->Hit(6).Y(); | |
69d7cf2e | 196 | st4z = AliHLTMUONCoreMansoTracker::GetZ7(); |
0e676e3f | 197 | } |
26538635 | 198 | if (track->Hit(8).X() == 0. && track->Hit(8).Y() == 0.) |
0e676e3f | 199 | { |
26538635 | 200 | st5x = track->Hit(9).X(); |
201 | st5y = track->Hit(9).Y(); | |
69d7cf2e | 202 | st5z = AliHLTMUONCoreMansoTracker::GetZ10(); |
0e676e3f | 203 | } |
204 | else | |
205 | { | |
26538635 | 206 | st5x = track->Hit(8).X(); |
207 | st5y = track->Hit(8).Y(); | |
69d7cf2e | 208 | st5z = AliHLTMUONCoreMansoTracker::GetZ9(); |
0e676e3f | 209 | } |
210 | ||
211 | Double_t x[4] = {st4x, st5x, | |
26538635 | 212 | trigrec->Station1Point().X(), trigrec->Station2Point().X() |
0e676e3f | 213 | }; |
214 | Double_t y[4] = {st4y, st5y, | |
26538635 | 215 | trigrec->Station1Point().Y(), trigrec->Station2Point().Y() |
0e676e3f | 216 | }; |
217 | Double_t z[4] = {st4z, st5z, | |
69d7cf2e | 218 | AliHLTMUONCoreMansoTracker::GetZ11(), |
219 | AliHLTMUONCoreMansoTracker::GetZ13() | |
0e676e3f | 220 | }; |
221 | ||
222 | // Fit a line to the x, y, z data points. | |
223 | Double_t mx, cx; // for x = mx*z + cx | |
224 | Double_t my, cy; // for y = my*z + cy | |
225 | LeastSquaresFit(z, x, mx, cx); | |
226 | AliDebug(11, Form("Fitted line to xz plane: m = %f c = %f", mx, cx)); | |
227 | LeastSquaresFit(z, y, my, cy); | |
228 | AliDebug(11, Form("Fitted line to yz plane: m = %f c = %f", my, cy)); | |
229 | ||
230 | // Now compute the residual, square it and add it to the total chi2. | |
231 | Double_t chi2 = 0.; | |
232 | for (Int_t i = 0; i < 4; i++) | |
233 | { | |
234 | Double_t rx = x[i] - (mx*z[i] + cx); | |
235 | Double_t ry = y[i] - (my*z[i] + cy); | |
236 | AliDebug(15, Form("Real x = %f, fitted x = %f for z = %f", x[i], (mx*z[i] + cx), z[i])); | |
237 | AliDebug(15, Form("Real y = %f, fitted y = %f for z = %f", y[i], (my*z[i] + cy), z[i])); | |
238 | chi2 += rx*rx + ry*ry; | |
239 | AliDebug(15, Form("Running total for Chi2 = %f", chi2)); | |
240 | } | |
241 | ||
242 | return chi2; | |
243 | } | |
244 | ||
245 | ||
246 | Int_t AliHLTMUONTracker::Clusters2Tracks(AliESD* event) | |
247 | { | |
69d7cf2e | 248 | // Runs the dHLT tracking algorithm via the AliHLTMUONMicrodHLT fdHLT object. The found tracks are |
249 | // filled by AliHLTMUONMicrodHLT in fTracks, which then need to be unpacked into the AliRoot ESD. | |
0e676e3f | 250 | |
251 | AliDebug(1, Form("Called for object 0x%X and ESD object = 0x%X", (ULong_t)this, (ULong_t)event)); | |
252 | ||
253 | // Run the dHLT tracking algorithm. | |
254 | fdHLT->Run(); | |
255 | AliDebug(1, "Finished running dHLT."); | |
256 | ||
257 | // Unpack the output and fill the ESD. | |
258 | #ifndef LOG_NO_DEBUG | |
259 | TString str = "====================== Found Tracks ========================\nID\tSign\tP\t\tPt\t\tChamber\tX\t\tY\n"; | |
260 | #endif // LOG_NO_DEBUG | |
261 | for (fTracks->GetFirstEvent(); fTracks->MoreEvents(); fTracks->GetNextEvent()) | |
262 | for (fTracks->GetFirstBlock(); fTracks->MoreBlocks(); fTracks->GetNextBlock()) | |
263 | for (fTracks->GetFirstTrack(); fTracks->MoreTracks(); fTracks->GetNextTrack()) | |
264 | { | |
69d7cf2e | 265 | const AliHLTMUONTrack* track = fTracks->GetTrack(); |
0e676e3f | 266 | |
267 | #ifndef LOG_NO_DEBUG | |
268 | // Build some debug logging information. | |
269 | str += track->TriggerID(); | |
270 | str += "\t"; | |
271 | str += track->ParticleSign(); | |
272 | str += "\t"; | |
273 | str += track->P(); | |
274 | str += "\t"; | |
275 | str += track->Pt(); | |
276 | str += "\t7\t"; | |
26538635 | 277 | str += track->Hit(6).X(); |
0e676e3f | 278 | str += "\t"; |
26538635 | 279 | str += track->Hit(6).Y(); |
0e676e3f | 280 | str += "\n\t\t\t\t\t\t8\t"; |
26538635 | 281 | str += track->Hit(7).X(); |
0e676e3f | 282 | str += "\t"; |
26538635 | 283 | str += track->Hit(7).Y(); |
0e676e3f | 284 | str += "\n\t\t\t\t\t\t9\t"; |
26538635 | 285 | str += track->Hit(8).X(); |
0e676e3f | 286 | str += "\t"; |
26538635 | 287 | str += track->Hit(8).Y(); |
0e676e3f | 288 | str += "\n\t\t\t\t\t\t10\t"; |
26538635 | 289 | str += track->Hit(9).X(); |
0e676e3f | 290 | str += "\t"; |
26538635 | 291 | str += track->Hit(9).Y(); |
0e676e3f | 292 | str += "\n"; |
293 | #endif // LOG_NO_DEBUG | |
294 | ||
69d7cf2e | 295 | Double_t z = AliHLTMUONCoreMansoTracker::GetZ7(); |
26538635 | 296 | Double_t x = track->Hit(6).X(); |
297 | if (track->Hit(6).X() == 0. && track->Hit(6).Y() == 0.) | |
0e676e3f | 298 | { |
69d7cf2e | 299 | z = AliHLTMUONCoreMansoTracker::GetZ8(); |
26538635 | 300 | x = track->Hit(7).X(); |
0e676e3f | 301 | }; |
302 | ||
303 | Double_t p = track->P(); | |
304 | Double_t pt = track->Pt(); | |
305 | ||
306 | // Using the approximation: px / pz = x / z , and pz^2 = p^2 - pt^2 | |
307 | Double_t pz2 = TMath::Abs(p*p - pt*pt); | |
308 | Double_t px2 = -1.; | |
309 | if (z != 0.) | |
310 | px2 = pz2 * x*x / (z*z); | |
311 | Double_t pyz = -1.; | |
312 | if (p*p - px2 >= 0.) | |
313 | pyz = TMath::Sqrt(p*p - px2); | |
314 | Double_t px = -1.; | |
315 | if (px2 >= 0.) | |
316 | px = TMath::Sqrt(px2); | |
317 | Double_t py = -1.; | |
318 | if (pt*pt - px2 >= 0.) | |
319 | py = TMath::Sqrt(pt*pt - px2); // pt^2 = px^2 + py^2 | |
320 | Double_t pz = -1.; | |
321 | if (pz2 >= 0.) | |
322 | pz = TMath::Sqrt(pz2); | |
323 | ||
324 | Double_t invmom = -1.0; | |
325 | if (pyz != 0.) | |
326 | invmom = 1. / pyz * track->ParticleSign(); | |
327 | Double_t thetax = TMath::ATan2(px, pz); | |
328 | Double_t thetay = TMath::ATan2(py, pz); | |
329 | ||
330 | Double_t chi2 = ComputeChi2(track); | |
331 | ||
332 | // Create MUON track, fill it and add it to the ESD. | |
333 | AliESDMuonTrack mt; | |
334 | mt.SetInverseBendingMomentum(invmom); | |
335 | mt.SetThetaX(thetax); | |
336 | mt.SetThetaY(thetay); | |
337 | ||
338 | // Our algorithm assumes the particle originates from the origin. | |
339 | mt.SetZ(0.0); | |
340 | mt.SetBendingCoor(0.0); | |
341 | mt.SetNonBendingCoor(0.0); | |
342 | ||
343 | mt.SetChi2(chi2); | |
344 | mt.SetNHit(2); // Always 2, thats the way Manso's algorithm works. | |
345 | mt.SetMatchTrigger( chi2 != -1. ? 1 : 0 ); | |
346 | mt.SetChi2MatchTrigger(chi2); | |
347 | ||
348 | AliDebug(2, Form( | |
349 | "Adding AliESDMuonTrack with inverse bending momentum" | |
350 | " = %f, theta X = %f, theta Y = %f, chi2 = %f", | |
351 | invmom, thetax, thetay, chi2) | |
352 | ); | |
353 | ||
354 | event->AddMuonTrack(&mt); | |
355 | } | |
356 | ||
357 | #ifndef LOG_NO_DEBUG | |
358 | AliDebug(4, str); | |
359 | #endif // LOG_NO_DEBUG | |
360 | ||
361 | return 0; | |
362 | } | |
363 |