]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/src/Tracking/MansoTracker.cxx
07160e57743f0265ec25e6d4dc03229cdf36fa1a
[u/mrichter/AliRoot.git] / HLT / MUON / src / Tracking / MansoTracker.cxx
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Author: Artur Szostak
4 // Email:  artur@alice.phy.uct.ac.za | artursz@iafrica.com
5 //
6 ////////////////////////////////////////////////////////////////////////////////
7
8 #include "Tracking/MansoTracker.hpp"
9 #include <math.h>
10 #include "Tracking/Calculations.hpp"
11 #include "Utils.hpp"
12 #include "Error.hpp"
13 #include "RegionOfInterest.hpp"
14
15
16 #if defined(DEBUG) || (defined(USE_ALILOG) && ! defined(LOG_NO_DEBUG))
17 #include <ostream>
18 #include "Debug/print.hpp"
19 namespace
20 {
21
22 std::ostream& operator << (std::ostream& os, AliHLTMUONCoreMansoTracker::StatesSM4 state)
23 {
24         switch (state)
25         {
26         case AliHLTMUONCoreMansoTracker::kSM4Idle:          os << "kSM4Idle"; break;
27         case AliHLTMUONCoreMansoTracker::kWaitChamber8:     os << "kWaitChamber8"; break;
28         case AliHLTMUONCoreMansoTracker::kWaitMoreChamber8: os << "kWaitMoreChamber8"; break;
29         case AliHLTMUONCoreMansoTracker::kWaitChamber7:     os << "kWaitChamber7"; break;
30         case AliHLTMUONCoreMansoTracker::kWaitMoreChamber7: os << "kWaitMoreChamber7"; break;
31         default:                             os << "FAULT!!"; 
32         }
33         return os;
34 }
35
36 std::ostream& operator << (std::ostream& os, AliHLTMUONCoreMansoTracker::StatesSM5 state)
37 {
38         switch (state)
39         {
40         case AliHLTMUONCoreMansoTracker::kSM5Idle:           os << "kSM5Idle"; break;
41         case AliHLTMUONCoreMansoTracker::kWaitChamber10:     os << "kWaitChamber10"; break;
42         case AliHLTMUONCoreMansoTracker::kWaitMoreChamber10: os << "kWaitMoreChamber10"; break;
43         case AliHLTMUONCoreMansoTracker::kWaitChamber9:      os << "kWaitChamber9"; break;
44         case AliHLTMUONCoreMansoTracker::kWaitMoreChamber9:  os << "kWaitMoreChamber9"; break;
45         case AliHLTMUONCoreMansoTracker::kSM5Done:           os << "kSM5Done"; break;
46         default:                              os << "FAULT!!"; 
47         }
48         return os;
49 }
50
51 } // end of namespace
52 #endif // DEBUG
53
54
55 // Deviate from the Manso implementation by allowing a and b
56 // parameters per chamber and not just per station.
57 // The default values are derived from the work done in
58 //    "A first algorithm for dimuon High Level Trigger"
59 //    Ref ID:  ALICE-INT-2002-04 version 1.0
60 Float AliHLTMUONCoreMansoTracker::fgA7  = 0.016f;
61 Float AliHLTMUONCoreMansoTracker::fgB7  = 2.0f;
62 Float AliHLTMUONCoreMansoTracker::fgA8  = 0.016f;
63 Float AliHLTMUONCoreMansoTracker::fgB8  = 2.0f;
64 Float AliHLTMUONCoreMansoTracker::fgA9  = 0.020f;
65 Float AliHLTMUONCoreMansoTracker::fgB9  = 3.0f;
66 Float AliHLTMUONCoreMansoTracker::fgA10 = 0.020f;
67 Float AliHLTMUONCoreMansoTracker::fgB10 = 3.0f;
68 Float AliHLTMUONCoreMansoTracker::fgZ7  = 1274.5f;
69 Float AliHLTMUONCoreMansoTracker::fgZ8  = 1305.5f;
70 Float AliHLTMUONCoreMansoTracker::fgZ9  = 1408.6f;
71 Float AliHLTMUONCoreMansoTracker::fgZ10 = 1439.6f;
72 Float AliHLTMUONCoreMansoTracker::fgZ11 = 1603.5f;
73 Float AliHLTMUONCoreMansoTracker::fgZ13 = 1703.5f;
74
75
76 void AliHLTMUONCoreMansoTracker::RegionOfInterest::Create(AliHLTMUONCorePoint p, Float a, Float b)
77 {
78         fCentre = p;
79         // Compute the radius Rp
80         Float Rp = (Float) sqrt( p.fX * p.fX + p.fY * p.fY );
81
82         // The radius Rs for the region of interest is computed from the
83         // specification given in the document:
84         //   "A first algorithm for dimuon High Level Trigger"
85         //   Ref ID:  ALICE-INT-2002-04 version 1.0
86         //   equation:
87         //     Rs = a * Rp + b
88         //   given on page 3 section 4.
89         fRs = a * Rp + b;
90 }
91
92
93 bool AliHLTMUONCoreMansoTracker::RegionOfInterest::Contains(AliHLTMUONCorePoint p) const
94 {
95         // Compute the distance between the centre of the region of interest and
96         // the point p. This distance must be less than the radius of the region
97         // of interest for p to be contained in the region of interest.
98         register Float lx = fCentre.fX - p.fX;
99         register Float ly = fCentre.fY - p.fY;
100         register Float r = (Float) sqrt( lx * lx + ly * ly );
101         DebugMsg(4, "\tRegionOfInterest::Contains : p = " << p
102                 << " , centre = " << fCentre << " , r = " << r << " , Rs = " << fRs
103         );
104         return r <= fRs;
105 }
106
107
108 void AliHLTMUONCoreMansoTracker::RegionOfInterest::GetBoundaryBox(Float& left, Float& right, Float& bottom, Float& top)
109 {
110         left = fCentre.fX - fRs;
111         right = fCentre.fX + fRs;
112         bottom = fCentre.fY - fRs;
113         top = fCentre.fY + fRs;
114 }
115
116
117 AliHLTMUONCoreMansoTracker::Vertex::Vertex(Float x, Float y, Float z)
118 {
119         fX = x;
120         fY = y;
121         fZ = z;
122 }
123
124
125 AliHLTMUONCoreMansoTracker::Vertex::Vertex(AliHLTMUONCorePoint xy, Float z)
126 {
127         fX = xy.fX;
128         fY = xy.fY;
129         fZ = z;
130 }
131
132
133 AliHLTMUONCoreMansoTracker::Line::Line(
134         Float Ax, Float Ay, Float Az,
135         Float Bx, Float By, Float Bz
136     )
137 {
138         fMx = Ax - Bx;
139         fMy = Ay - By;
140         fMz = Az - Bz;
141         fCx = Bx;
142         fCy = By;
143         fCz = Bz;
144 }
145
146
147 AliHLTMUONCoreMansoTracker::Line::Line(Vertex A, Vertex B)
148 {
149         fMx = A.fX - B.fX;
150         fMy = A.fY - B.fY;
151         fMz = A.fZ - B.fZ;
152         fCx = B.fX;
153         fCy = B.fY;
154         fCz = B.fZ;
155 }
156
157
158 AliHLTMUONCorePoint AliHLTMUONCoreMansoTracker::Line::FindIntersectWithXYPlain(Float z) const
159 {
160         Assert( fMz != 0.0 );    // Should not have a ray perpendicular to the beam axis.
161         Float t = (z - fCz) / fMz;
162         Float Lx = fMx*t + fCx;
163         Float Ly = fMy*t + fCy;
164
165         return AliHLTMUONCorePoint(Lx, Ly);
166 }
167
168
169 AliHLTMUONCoreMansoTracker::AliHLTMUONCoreMansoTracker() : AliHLTMUONCoreTracker()
170 {
171         fSm4state = kSM4Idle;
172         fSm5state = kSM5Idle;
173         fRequestsCompleted = 0;
174 }
175
176
177 void AliHLTMUONCoreMansoTracker::FindTrack(const AliHLTMUONCoreTriggerRecord& trigger)
178 {
179         DebugMsg(4, "SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
180         DebugMsg(1, "Processing trigger with pt = " << trigger.fPt);
181         fV1 = Vertex( trigger.fStation1impact, fgZ11 );
182         Vertex v2 = Vertex( trigger.fStation2impact, fgZ13 );
183
184         // Form the vector line between the above two impact points and
185         // find the crossing point of the line with chamber 10 (i.e. station 5).
186         fMc1.fLine = Line(fV1, v2);
187         AliHLTMUONCorePoint p10 = fMc1.fLine.FindIntersectWithXYPlain( fgZ10 );
188
189         // Build a region of interest for tracking station 5 (chamber 10).
190         // Remember the parameters a and b are station specific.
191         fMc1.fChamber = kChamber10;
192         fMc1.fRoi.Create(p10, fgA10, fgB10);
193         
194         // Make SM5 state transition before the call to RequestClusters since
195         // that method could call one of our methods again, so we need to be
196         // in a consistant internal state.
197         fSm5state = kWaitChamber10;
198
199         Float left, right, bottom, top;
200         fMc1.fRoi.GetBoundaryBox(left, right, bottom, top);
201         RequestClusters(left, right, bottom, top, kChamber10, &fMc1);
202 }
203
204
205 void AliHLTMUONCoreMansoTracker::ReturnClusters(void* tag, const AliHLTMUONCoreClusterPoint* clusters, UInt count)
206 {
207         Assert( count > 0 );
208         Assert( clusters != NULL );
209         
210         TagData* data = (TagData*)tag;
211         DebugMsg(4, "Got AliHLTMUONCoreMansoTracker::ReturnClusters(tag = " << tag
212                 << ", chamber = " << data->fChamber
213                 << ", clusters = " << clusters <<  ", count = " << count << ")"
214         );
215         DebugMsg(4, "SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
216
217         switch (data->fChamber)
218         {
219         case kChamber7:  ReceiveClustersChamber7(clusters, count, data); break;
220         case kChamber8:  ReceiveClustersChamber8(clusters, count, data); break;
221         case kChamber9:  ReceiveClustersChamber9(clusters, count); break;
222         case kChamber10: ReceiveClustersChamber10(clusters, count); break;
223         default:
224                 // Error
225                 DebugMsg(1, "ERROR: Got tag with an invalid value: " << data->fChamber);
226         }
227 }
228
229
230 void AliHLTMUONCoreMansoTracker::EndOfClusters(void* tag)
231 {
232         TagData* data = (TagData*)tag;
233         DebugMsg(4, "Got AliHLTMUONCoreMansoTracker::EndOfClusters(chamber = " << data->fChamber << ")");
234         DebugMsg(4, "SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
235
236         switch (data->fChamber)
237         {
238         case kChamber7:  EndOfClustersChamber7(); break;
239         case kChamber8:  EndOfClustersChamber8(); break;
240         case kChamber9:  EndOfClustersChamber9(); break;
241         case kChamber10: EndOfClustersChamber10(); break;
242         default:
243                 // Error
244                 DebugMsg(1, "ERROR: Got tag with an invalid value: " << data->fChamber);
245         }
246 }
247
248
249 void AliHLTMUONCoreMansoTracker::FillTrackData(AliHLTMUONCoreTrack& track)
250 {
251         DebugMsg(4, "FillTrack: st5 = " << fSt5rec->fClusterPoint << ", st4 = " << fFoundPoint->fClusterPoint);
252         
253         Float x1 = fFoundPoint->fClusterPoint.fX;
254         Float y1 = fFoundPoint->fClusterPoint.fY;
255         Float y2 = fSt5rec->fClusterPoint.fY;
256         Float momentum;
257         Float pt = AliHLTMUONCoreCalculateSignedPt(x1, y1, y2, fSt4z, fSt5z, momentum);
258         DebugMsg(1, "Calculated Pt = " << pt);
259         DebugMsg(1, "\tusing x1 = " << x1 << " , y1 = " << y1 << " , y2 = " << y2
260                 << " , z1 = " << fSt4z << " , z2 = " << fSt5z
261         );
262
263         if (pt < 0)
264                 track.fSign = kSignMinus;
265         else if (pt > 0)
266                 track.fSign = kSignPlus;
267         else
268                 track.fSign = kUnknownSign;
269
270         track.fP = momentum;
271         track.fPt = (Float) fabs(pt);
272         for (UInt i = 0; i < 6; i++)
273         {
274                 track.fPoint[i] = AliHLTMUONCorePoint(0.0, 0.0);
275                 track.fRegion[i] = kINVALID_ROI;
276         }
277
278         Float left, right, bottom, top;
279         
280         // Have to create the ROI numbers from the internal region of interest structures.
281         fSt5rec->fTag.fRoi.GetBoundaryBox(left, right, bottom, top);
282         AliHLTMUONCoreRegionOfInterest region4(left, right, bottom, top, fSt4chamber);
283         fMc1.fRoi.GetBoundaryBox(left, right, bottom, top);
284         AliHLTMUONCoreRegionOfInterest region5(left, right, bottom, top, fMc1.fChamber);
285         
286         // Depending on the chamber we received cluster points from, fill the appropriate
287         // point and ROI number. This is done for station 4 then 5.
288         if (fSt4chamber == kChamber8)
289         {
290                 track.fPoint[6] = AliHLTMUONCorePoint(0.0, 0.0);
291                 track.fRegion[6] = kINVALID_ROI;
292                 track.fPoint[7] = fFoundPoint->fClusterPoint;
293                 track.fRegion[7] = region4;
294         }
295         else
296         {
297                 track.fPoint[6] = fFoundPoint->fClusterPoint;
298                 track.fRegion[6] = region4;
299                 track.fPoint[7] = AliHLTMUONCorePoint(0.0, 0.0);
300                 track.fRegion[7] = kINVALID_ROI;
301         }
302         if (fMc1.fChamber == kChamber10)
303         {
304                 track.fPoint[8] = AliHLTMUONCorePoint(0.0, 0.0);
305                 track.fRegion[8] = kINVALID_ROI;
306                 track.fPoint[9] = fSt5rec->fClusterPoint;
307                 track.fRegion[9] = region5;
308         }
309         else
310         {
311                 track.fPoint[8] = fSt5rec->fClusterPoint;
312                 track.fRegion[8] = region5;
313                 track.fPoint[9] = AliHLTMUONCorePoint(0.0, 0.0);
314                 track.fRegion[9] = kINVALID_ROI;
315         }
316 }
317
318
319 void AliHLTMUONCoreMansoTracker::Reset()
320 {
321         DebugMsg(4, "SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
322         fSt5data.Clear();
323         fSt4points.Clear();
324         fSm4state = kSM4Idle;
325         fSm5state = kSM5Idle;
326         fRequestsCompleted = 0;
327 }
328
329
330 // Note: In the following ReceiveClustersXXX and EndOfClustersXXX methods we make
331 // the state machine transitions before calls to RequestClusters, FoundTrack, 
332 // NoTrackFound or EndOfClusterRequests. This is important since the callback
333 // object will make recursive calls to the tracker's methods so we need to maintain
334 // a consistant internal state.
335 // The same would go for updating internal variables.
336 // In general one should only call the callback methods at the end of any of the
337 // following routines.
338
339 void AliHLTMUONCoreMansoTracker::ReceiveClustersChamber7(
340                 const AliHLTMUONCoreClusterPoint* clusters, UInt count, const TagData* data
341         )
342 {
343         switch (fSm4state)
344         {
345         case kWaitChamber7:
346                 fSm4state = kWaitMoreChamber7;
347         
348         case kWaitMoreChamber7:
349                 for (UInt j = 0; j < count; j++)
350                 {
351                         AliHLTMUONCoreClusterPoint cluster = clusters[j];
352                         // Check that the cluster actually is in our region of interest on station 4.
353                         if ( data->fRoi.Contains(cluster) )
354                         {
355                                 DebugMsg(4, "Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 7.");
356                                 Station4Data* newdata = fSt4points.New();
357                                 newdata->fClusterPoint = cluster;
358                                 newdata->fSt5tag = data;
359                         }
360                 }
361                 break;
362         
363         default:
364                 DebugMsg(1, "ERROR: Unexpected state for SM4 in AliHLTMUONCoreMansoTracker::ReceiveClustersChamber7!");
365         }
366 }
367
368
369 void AliHLTMUONCoreMansoTracker::ReceiveClustersChamber8(
370                 const AliHLTMUONCoreClusterPoint* clusters, UInt count, const TagData* data
371         )
372 {
373         switch (fSm4state)
374         {
375         case kWaitChamber8:
376                 fSm4state = kWaitMoreChamber8;
377                 fSt4z = fgZ8;
378                 fSt4chamber = kChamber8;
379         
380         case kWaitMoreChamber8:
381                 for (UInt j = 0; j < count; j++)
382                 {
383                         AliHLTMUONCoreClusterPoint cluster = clusters[j];
384                         // Check that the cluster actually is in our region of interest on station 4.
385                         if ( data->fRoi.Contains(cluster) )
386                         {
387                                 DebugMsg(4, "Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 8.");
388                                 Station4Data* newdata = fSt4points.New();
389                                 newdata->fClusterPoint = cluster;
390                                 newdata->fSt5tag = data;
391                         }
392                 }
393                 break;
394                 
395         default:
396                 DebugMsg(1, "ERROR: Unexpected state for SM4 in AliHLTMUONCoreMansoTracker::ReceiveClustersChamber8!");
397         }
398 }
399
400
401 void AliHLTMUONCoreMansoTracker::ReceiveClustersChamber9(const AliHLTMUONCoreClusterPoint* clusters, UInt count)
402 {
403         switch (fSm5state)
404         {
405         case kWaitChamber9:
406                 fSm5state = kWaitMoreChamber9;
407                 fSm4state = kWaitChamber8;  // Start SM4.
408         
409         case kWaitMoreChamber9:
410                 for (UInt j = 0; j < count; j++)
411                 {
412                         AliHLTMUONCoreClusterPoint cluster = clusters[j];
413                         // Check that the cluster actually is in our region of interest on station 5.
414                         if ( fMc1.fRoi.Contains(cluster) )
415                         {
416                                 DebugMsg(4, "Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 9.");
417                                 Station5Data* data = fSt5data.New();
418                                 data->fClusterPoint = cluster;
419                                 ProjectToStation4(data, fgZ9);  // This adds a new request for station 4.
420                         }
421                 }
422                 break;
423
424         default:
425                 DebugMsg(1, "ERROR: Unexpected state for SM5 in AliHLTMUONCoreMansoTracker::ReceiveClustersChamber9!");
426         }
427 }
428
429
430 void AliHLTMUONCoreMansoTracker::ReceiveClustersChamber10(const AliHLTMUONCoreClusterPoint* clusters, UInt count)
431 {
432         switch (fSm5state)
433         {
434         case kWaitChamber10:
435                 fSm5state = kWaitMoreChamber10;
436                 fSt5z = fgZ10;
437                 fSm4state = kWaitChamber8;  // Start SM4.
438         
439         case kWaitMoreChamber10:
440                 for (UInt j = 0; j < count; j++)
441                 {
442                         AliHLTMUONCoreClusterPoint cluster = clusters[j];
443                         // Check that the cluster actually is in our region of interest on station 5.
444                         if ( fMc1.fRoi.Contains(cluster) )
445                         {
446                                 DebugMsg(4, "Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 10.");
447                                 Station5Data* data = fSt5data.New();
448                                 data->fClusterPoint = cluster;
449                                 ProjectToStation4(data, fgZ10);  // This adds a new request for station 4.
450                         }
451                 }
452                 break;
453
454         default:
455                 DebugMsg(1, "ERROR: Unexpected state for SM5 in AliHLTMUONCoreMansoTracker::ReceiveClustersChamber10!");
456         }
457 }
458
459
460 void AliHLTMUONCoreMansoTracker::EndOfClustersChamber7()
461 {
462         fRequestsCompleted++;  // Increment the number of requests completed for station 4.
463         DebugMsg(4, "fRequestsCompleted = " << fRequestsCompleted );
464
465         switch (fSm4state)
466         {
467         case kWaitChamber7:
468                 // If all data from station 5 is received and no data found on
469                 // chambers 7 or 8 then we can not find a track.
470                 if (fSm5state == kSM5Done) NoTrackFound();
471                 break;
472         
473         case kWaitMoreChamber7:
474                 if (fRequestsCompleted == fSt5data.Count() && fSm5state == kSM5Done)
475                         ProcessClusters();
476                 break;
477         
478         default:
479                 DebugMsg(1, "ERROR: Unexpected state for SM4 in AliHLTMUONCoreMansoTracker::EndOfClustersChamber7!");
480         }
481 }
482
483
484 void AliHLTMUONCoreMansoTracker::EndOfClustersChamber8()
485 {
486         fRequestsCompleted++;  // Increment the number of requests completed for station 4.
487         DebugMsg(4, "fRequestsCompleted = " << fRequestsCompleted );
488
489         switch (fSm4state)
490         {
491         case kWaitChamber7:
492                 // Ignore. The requests for chamber 8 are already re-requested below.
493                 break;
494                 
495         case kWaitChamber8:
496                 {
497                 fSm4state = kWaitChamber7;
498                 fSt4z = fgZ7;
499                 fSt4chamber = kChamber7;
500         
501                 // We need to resend the requests for chamber 8, but change the request
502                 // to get data for chamber 7 instead:
503                 UInt reqlistsize = fSt5data.Count();
504                 DebugMsg(4, "Re-requesting clusters from chamber 7... reqlistsize = " << reqlistsize);
505
506                 Station5List::Iterator rec = fSt5data.First();
507                 for (UInt i = 0; i < reqlistsize; i++, rec++)
508                 {
509                         // Need to create a new st5 data block for the request.
510                         Station5Data* data = fSt5data.New();
511                         data->fClusterPoint = rec->fClusterPoint;
512                         data->fTag.fLine = rec->fTag.fLine;
513
514                         // Rebuild a region of interest for chamber 7.
515                         // Remember the parameters a and b are station specific.
516                         AliHLTMUONCorePoint p7 = data->fTag.fLine.FindIntersectWithXYPlain( fgZ7 );
517                         data->fTag.fChamber = kChamber7;
518                         data->fTag.fRoi.Create(p7, fgA7, fgB7);
519                         
520                         Float left, right, bottom, top;
521                         data->fTag.fRoi.GetBoundaryBox(left, right, bottom, top);
522                         // Make request for chamber 7 data.
523                         RequestClusters(left, right, bottom, top, kChamber7, &data->fTag);
524                 }
525                 }
526                 break;
527         
528         case kWaitMoreChamber8:
529                 if (fRequestsCompleted == fSt5data.Count() && fSm5state == kSM5Done)
530                         ProcessClusters();
531                 break;
532         
533         default:
534                 DebugMsg(1, "ERROR: Unexpected state for SM4 in AliHLTMUONCoreMansoTracker::EndOfClustersChamber8!");
535         }
536 }
537
538
539 void AliHLTMUONCoreMansoTracker::EndOfClustersChamber9()
540 {
541         switch (fSm5state)
542         {
543         case kWaitChamber9:
544                 fSm5state = kSM5Done;
545                 EndOfClusterRequests();
546                 NoTrackFound();
547                 break;
548                 
549         case kWaitMoreChamber9:
550                 fSm5state = kSM5Done;
551                 EndOfClusterRequests();
552                 if (fRequestsCompleted == fSt5data.Count())
553                         ProcessClusters();
554                 break;
555
556         default:
557                 DebugMsg(1, "ERROR: Unexpected state for SM5 in AliHLTMUONCoreMansoTracker::EndOfClustersChamber9!");
558         }
559 }
560
561
562 void AliHLTMUONCoreMansoTracker::EndOfClustersChamber10()
563 {
564         switch (fSm5state)
565         {
566         case kWaitChamber10:
567                 {
568                 fSm5state = kWaitChamber9;
569                 fSt5z = fgZ9;
570                 
571                 // No clusters found on chamber 10 so we need to make a request for
572                 // clusters from chamber 9:
573                 AliHLTMUONCorePoint p9 = fMc1.fLine.FindIntersectWithXYPlain( fgZ9 );
574
575                 // Build a region of interest for tracking station 5 (chamber 9).
576                 // Remember the parameters a and b are station specific.
577                 fMc1.fChamber = kChamber9;
578                 fMc1.fRoi.Create(p9, fgA9, fgB9);
579
580                 Float left, right, bottom, top;
581                 fMc1.fRoi.GetBoundaryBox(left, right, bottom, top);
582                 RequestClusters(left, right, bottom, top, kChamber9, &fMc1);
583                 }
584                 break;
585
586         case kWaitMoreChamber10:
587                 fSm5state = kSM5Done;
588                 EndOfClusterRequests();
589                 if (fRequestsCompleted == fSt5data.Count())
590                         ProcessClusters();
591                 break;
592
593         default:
594                 DebugMsg(1, "ERROR: Unexpected state for SM5 in AliHLTMUONCoreMansoTracker::EndOfClustersChamber10!");
595         }
596 }
597
598
599 void AliHLTMUONCoreMansoTracker::ProjectToStation4(Station5Data* data, register Float station5z)
600 {
601         // Perform chamber specific operations:
602         // Since certain states of SM4 means that it is fetching for Chamber8
603         // and other states are for fetching from Chamber7. We need to make
604         // requests for the correct chamber.
605         Assert( fSm4state == kWaitChamber8 
606                 || fSm4state == kWaitMoreChamber8
607                 || fSm4state == kWaitChamber7
608                 || fSm4state == kWaitMoreChamber7
609         );
610         TagData* tag = &data->fTag;
611         if (fSm4state == kWaitChamber8 || fSm4state == kWaitMoreChamber8)
612         {
613                 // Form the vector line between trigger station 1 and tracking station 5,
614                 // and find the intersection point of the line with station 4 (chamber8).
615                 Line line51( Vertex(data->fClusterPoint, station5z), fV1 );
616                 AliHLTMUONCorePoint intercept = line51.FindIntersectWithXYPlain( fgZ8 );
617                 tag->fLine = line51;
618                 
619                 // Build a region of interest for tracking station 4.
620                 tag->fChamber = kChamber8;
621                 tag->fRoi.Create(intercept, fgA8, fgB8);
622         }
623         else
624         {
625                 // Form the vector line between trigger station 1 and tracking station 5,
626                 // and find the intersection point of the line with station 4 (chamber7).
627                 Line line51( Vertex(data->fClusterPoint, station5z), fV1 );
628                 AliHLTMUONCorePoint intercept = line51.FindIntersectWithXYPlain( fgZ7 );
629                 tag->fLine = line51;
630                 
631                 // Build a region of interest for tracking station 4.
632                 tag->fChamber = kChamber7;
633                 tag->fRoi.Create(intercept, fgA7, fgB7);
634         }
635
636         // Make the request for clusters from station 4.
637         Float left, right, bottom, top;
638         tag->fRoi.GetBoundaryBox(left, right, bottom, top);
639         RequestClusters(left, right, bottom, top, tag->fChamber, tag);
640 }
641
642
643 void AliHLTMUONCoreMansoTracker::ProcessClusters()
644 {
645         DebugMsg(2, "ProcessClusters...");
646         
647         // Check if the cluster point list on station 4 is empty.
648         // If it is then we have not found any tracks.
649         fFoundPoint = fSt4points.First();
650         if (fFoundPoint == fSt4points.End())
651         {
652                 NoTrackFound();
653                 return;
654         }
655         
656         fSt5rec = fSt5data.First();
657         if (fSt5rec != fSt5data.End())
658         {
659                 // Only look at station 5 data records that are for the found chamber number.
660                 // Note: either we only have chamber 8 data or we have chamber 7 data followed
661                 // by chamber 8 data.
662                 // Thus if we hit records that we are not interested in already then the list
663                 // contains no interesting data and we can signal no track found.
664                 if (fSt5rec->fTag.fChamber != fSt4chamber)
665                 {
666                         NoTrackFound();
667                         return;
668                 }
669                  
670                 // For all combinations of cluster point pairs from station 4 and 5
671                 // signal a found track:
672                 do
673                 {
674                         DebugMsg(4, "\tfSt5rec->fTag.chamber = " << fSt5rec->fTag.fChamber
675                                 << " , fSt4chamber = " << fSt4chamber
676                         );
677
678                         for (fFoundPoint = fSt4points.First(); fFoundPoint != fSt4points.End(); fFoundPoint++)
679                         {
680                                 if (fFoundPoint->fSt5tag == &fSt5rec->fTag)
681                                         FoundTrack();
682                         }
683
684                         fSt5rec++;  // Get next station 5 cluster point.
685                 } while (fSt5rec != fSt5data.End() && fSt5rec->fTag.fChamber == fSt4chamber);
686         }
687         else
688                 NoTrackFound();
689 }
690