]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONMansoTrackerFSM.cxx
Forgot to get rid of #define DEBUG
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONMansoTrackerFSM.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        * 
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          * 
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19 /**
20  *  @file   AliHLTMUONMansoTrackerFSM.cxx
21  *  @author Artur Szostak <artursz@iafrica.com>
22  *  @date   
23  *  @brief  Implementation of AliHLTMUONMansoTrackerFSM class.
24  */
25
26 #include "AliHLTMUONMansoTrackerFSM.h"
27 #include "AliHLTMUONCalculations.h"
28 #include "AliHLTMUONConstants.h"
29 #include "AliHLTMUONUtils.h"
30 #include <cmath>
31
32
33 #ifdef DEBUG
34 #include <ostream>
35 namespace
36 {
37
38 std::ostream& operator << (std::ostream& os, AliHLTMUONMansoTrackerFSM::StatesSM4 state)
39 {
40         switch (state)
41         {
42         case AliHLTMUONMansoTrackerFSM::kSM4Idle:          os << "kSM4Idle"; break;
43         case AliHLTMUONMansoTrackerFSM::kWaitChamber8:     os << "kWaitChamber8"; break;
44         case AliHLTMUONMansoTrackerFSM::kWaitMoreChamber8: os << "kWaitMoreChamber8"; break;
45         case AliHLTMUONMansoTrackerFSM::kWaitChamber7:     os << "kWaitChamber7"; break;
46         case AliHLTMUONMansoTrackerFSM::kWaitMoreChamber7: os << "kWaitMoreChamber7"; break;
47         default:                                           os << "FAULT!!"; 
48         }
49         return os;
50 }
51
52 std::ostream& operator << (std::ostream& os, AliHLTMUONMansoTrackerFSM::StatesSM5 state)
53 {
54         switch (state)
55         {
56         case AliHLTMUONMansoTrackerFSM::kSM5Idle:           os << "kSM5Idle"; break;
57         case AliHLTMUONMansoTrackerFSM::kWaitChamber10:     os << "kWaitChamber10"; break;
58         case AliHLTMUONMansoTrackerFSM::kWaitMoreChamber10: os << "kWaitMoreChamber10"; break;
59         case AliHLTMUONMansoTrackerFSM::kWaitChamber9:      os << "kWaitChamber9"; break;
60         case AliHLTMUONMansoTrackerFSM::kWaitMoreChamber9:  os << "kWaitMoreChamber9"; break;
61         case AliHLTMUONMansoTrackerFSM::kSM5Done:           os << "kSM5Done"; break;
62         default:                                            os << "FAULT!!"; 
63         }
64         return os;
65 }
66
67 } // end of namespace
68 #endif // DEBUG
69
70
71 // Deviate from the Manso implementation by allowing a and b
72 // parameters per chamber and not just per station.
73 // The default values are derived from the work done in
74 //    "A first algorithm for dimuon High Level Trigger"
75 //    Ref ID:  ALICE-INT-2002-04 version 1.0
76 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgA7  = 0.016f;
77 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgB7  = 2.0f;
78 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgA8  = 0.016f;
79 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgB8  = 2.0f;
80 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgA9  = 0.020f;
81 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgB9  = 3.0f;
82 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgA10 = 0.020f;
83 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgB10 = 3.0f;
84 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ7  = -1274.5f;
85 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ8  = -1305.5f;
86 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ9  = -1408.6f;
87 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ10 = -1439.6f;
88 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ11 = -1603.5f;
89 AliHLTFloat32_t AliHLTMUONMansoTrackerFSM::fgZ13 = -1703.5f;
90
91
92 void AliHLTMUONMansoTrackerFSM::AliRegionOfInterest::Create(
93                 AliHLTMUONRecHitStruct p, AliHLTFloat32_t a, AliHLTFloat32_t b
94         )
95 {
96 // Creates a region of interest specific to the Manso algorithm from a point and
97 // two Manso specific parameters.
98
99         fCentre = p;
100         // Compute the radius Rp
101         AliHLTFloat32_t rp = (AliHLTFloat32_t) sqrt( p.fX * p.fX + p.fY * p.fY );
102
103         // The radius Rs for the region of interest is computed from the
104         // specification given in the document:
105         //   "A first algorithm for dimuon High Level Trigger"
106         //   Ref ID:  ALICE-INT-2002-04 version 1.0
107         //   equation:
108         //     Rs = a * Rp + b
109         //   given on page 3 section 4.
110         fRs = a * rp + b;
111 }
112
113
114 bool AliHLTMUONMansoTrackerFSM::AliRegionOfInterest::Contains(AliHLTMUONRecHitStruct p) const
115 {
116         // Compute the distance between the centre of the region of interest and
117         // the point p. This distance must be less than the radius of the region
118         // of interest for p to be contained in the region of interest.
119         register AliHLTFloat32_t lx = fCentre.fX - p.fX;
120         register AliHLTFloat32_t ly = fCentre.fY - p.fY;
121         register AliHLTFloat32_t r = (AliHLTFloat32_t) sqrt( lx * lx + ly * ly );
122         DebugTrace("\tAliRegionOfInterest::Contains : p = " << p
123                 << " , centre = " << fCentre << " , r = " << r << " , Rs = " << fRs
124         );
125         return r <= fRs;
126 }
127
128
129 void AliHLTMUONMansoTrackerFSM::AliRegionOfInterest::GetBoundaryBox(
130                 AliHLTFloat32_t& left, AliHLTFloat32_t& right,
131                 AliHLTFloat32_t& bottom, AliHLTFloat32_t& top
132         ) const
133 {
134 // Works out the smallest boundary box that will contain the region of interest.
135
136         left = fCentre.fX - fRs;
137         right = fCentre.fX + fRs;
138         bottom = fCentre.fY - fRs;
139         top = fCentre.fY + fRs;
140 }
141
142
143 AliHLTMUONMansoTrackerFSM::AliVertex::AliVertex(
144                 AliHLTFloat32_t x, AliHLTFloat32_t y, AliHLTFloat32_t z
145         )
146         : fX(x), fY(y), fZ(z)
147 {
148 // Constructor for vertex.
149 }
150
151
152 AliHLTMUONMansoTrackerFSM::AliVertex::AliVertex(AliHLTMUONRecHitStruct xy, AliHLTFloat32_t z)
153         : fX(xy.fX), fY(xy.fY), fZ(z)
154 {
155 // Construct vertex from a point on the XY plane and z coordinate.
156 }
157
158
159 AliHLTMUONMansoTrackerFSM::AliLine::AliLine(
160                 AliHLTFloat32_t ax, AliHLTFloat32_t ay, AliHLTFloat32_t az,
161                 AliHLTFloat32_t bx, AliHLTFloat32_t by, AliHLTFloat32_t bz
162         ) :
163         fMx(ax - bx),
164         fMy(ay - by),
165         fMz(az - bz),
166         fCx(bx),
167         fCy(by),
168         fCz(bz)
169 {
170 // Construct a line defined by L = M*t + C = (A-B)*t + B
171 // where M and C are 3D vectors and t is a free parameter.
172 // A = (ax, ay, az) and B = (bx, by, bz)
173 }
174
175
176 AliHLTMUONMansoTrackerFSM::AliLine::AliLine(AliVertex a, AliVertex b) :
177         fMx(a.X() - b.X()),
178         fMy(a.Y() - b.Y()),
179         fMz(a.Z() - b.Z()),
180         fCx(b.X()),
181         fCy(b.Y()),
182         fCz(b.Z())
183 {
184 // Contruct a line to go through two vertices a and b.
185 }
186
187
188 AliHLTMUONRecHitStruct AliHLTMUONMansoTrackerFSM::AliLine::FindIntersectWithXYPlain(
189                 AliHLTFloat32_t z
190         ) const
191 {
192 // Find the point of intersection of the line and the XY plane at z.
193
194         assert( fMz != 0.0 );  // Should not have a ray perpendicular to the beam axis.
195         AliHLTFloat32_t t = (z - fCz) / fMz;
196         AliHLTMUONRecHitStruct p;
197         p.fX = fMx*t + fCx;
198         p.fY = fMy*t + fCy;
199         p.fZ = z;
200         return p;
201 }
202
203
204 AliHLTMUONMansoTrackerFSM::AliHLTMUONMansoTrackerFSM() :
205         fCallback(NULL),
206         fSm4state(kSM4Idle),
207         fSm5state(kSM5Idle),
208         fRequestsCompleted(0),
209         fSt4chamber(kChamber1),
210         fV1(),
211         fMc1(),
212         fSt5data(),
213         fSt4points(),
214         fSt5rec(),
215         fFoundPoint(),
216         fTriggerId(-1),
217         fTrackId(0)
218 {
219 // Default constructor
220 }
221
222
223 void AliHLTMUONMansoTrackerFSM::FindTrack(const AliHLTMUONTriggerRecordStruct& trigger)
224 {
225 // Tries to find the track from the trigger seed.
226
227         DebugTrace("SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
228         DebugTrace("Processing trigger with ID = " << trigger.fId);
229         
230         fTriggerId = trigger.fId;
231         
232         AliHLTMUONParticleSign sign;
233         bool hitset[4];
234         AliHLTMUONUtils::UnpackTriggerRecordFlags(trigger.fFlags, sign, hitset);        
235         DebugTrace("hitset = {" << hitset[0] << ", " << hitset[1] << ", "
236                 << hitset[2] << ", " << hitset[3] << "}"
237         ); 
238         
239         // Find first valid hit in the trigger record from chambers 11 and 12.
240         int firstHit = -1;
241         for (int i = 0; i < 2; i++)
242         {
243                 if (hitset[i])
244                 {
245                         firstHit = i;
246                         break;
247                 }
248         }
249         // Find the second valid hit in the trigger record from chambers 13 and 14.
250         int secondHit = -1;
251         for (int i = 2; i < 4; i++)
252         {
253                 if (hitset[i])
254                 {
255                         secondHit = i;
256                         break;
257                 }
258         }
259         if (firstHit == -1 or secondHit == -1)
260         {
261                 NoTrackFound();
262                 return;
263         }
264         
265         fV1 = AliVertex(
266                         trigger.fHit[firstHit].fX,
267                         trigger.fHit[firstHit].fY,
268                         trigger.fHit[firstHit].fZ
269                 );
270         AliVertex v2 = AliVertex(
271                         trigger.fHit[secondHit].fX,
272                         trigger.fHit[secondHit].fY,
273                         trigger.fHit[secondHit].fZ
274                 );
275         
276         DebugTrace("Using fV1 = {x = " << fV1.X() << ", y = " << fV1.Y() << ", "
277                 << fV1.Z() << "}, with firstHit = " << firstHit
278         );
279         DebugTrace("Using v2 = {x = " << v2.X() << ", y = " << v2.Y() << ", "
280                 << v2.Z() << "}, with secondHit = " << secondHit
281         );
282
283         // Form the vector line between the above two impact points and
284         // find the crossing point of the line with chamber 10 (i.e. station 5).
285         fMc1.fLine = AliLine(fV1, v2);
286         AliHLTMUONRecHitStruct p10 = fMc1.fLine.FindIntersectWithXYPlain( fgZ10 );
287
288         // Build a region of interest for tracking station 5 (chamber 10).
289         // Remember the parameters a and b are station specific.
290         fMc1.fChamber = kChamber10;
291         fMc1.fRoi.Create(p10, fgA10, fgB10);
292         
293         // Make SM5 state transition before the call to RequestClusters since
294         // that method could call one of our methods again, so we need to be
295         // in a consistant internal state.
296         fSm5state = kWaitChamber10;
297
298         AliHLTFloat32_t left, right, bottom, top;
299         fMc1.fRoi.GetBoundaryBox(left, right, bottom, top);
300         RequestClusters(left, right, bottom, top, kChamber10, &fMc1);
301 }
302
303
304 void AliHLTMUONMansoTrackerFSM::ReturnClusters(
305                 void* tag, const AliHLTMUONRecHitStruct* clusters,
306                 AliHLTUInt32_t count
307         )
308 {
309 // Implementation of AliHLTMUONMansoTrackerFSM::ReturnClusters.
310
311         assert( count > 0 );
312         assert( clusters != NULL );
313         
314         AliTagData* data = (AliTagData*)tag;
315         DebugTrace("Got AliHLTMUONMansoTrackerFSM::ReturnClusters(tag = " << tag
316                 << ", chamber = " << data->fChamber
317                 << ", clusters = " << clusters <<  ", count = " << count << ")"
318         );
319         DebugTrace("SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
320
321         switch (data->fChamber)
322         {
323         case kChamber7:  ReceiveClustersChamber7(clusters, count, data); break;
324         case kChamber8:  ReceiveClustersChamber8(clusters, count, data); break;
325         case kChamber9:  ReceiveClustersChamber9(clusters, count); break;
326         case kChamber10: ReceiveClustersChamber10(clusters, count); break;
327         default:
328                 // Error
329                 DebugTrace("ERROR: Got tag with an invalid value: " << data->fChamber);
330         }
331 }
332
333
334 void AliHLTMUONMansoTrackerFSM::EndOfClusters(void* tag)
335 {
336 // Implementation of AliHLTMUONMansoTrackerFSM::EndOfClusters.
337
338         AliTagData* data = (AliTagData*)tag;
339         DebugTrace("Got AliHLTMUONMansoTrackerFSM::EndOfClusters(chamber = " << data->fChamber << ")");
340         DebugTrace("SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
341
342         switch (data->fChamber)
343         {
344         case kChamber7:  EndOfClustersChamber7(); break;
345         case kChamber8:  EndOfClustersChamber8(); break;
346         case kChamber9:  EndOfClustersChamber9(); break;
347         case kChamber10: EndOfClustersChamber10(); break;
348         default:
349                 // Error
350                 DebugTrace("ERROR: Got tag with an invalid value: " << data->fChamber);
351         }
352 }
353
354
355 bool AliHLTMUONMansoTrackerFSM::FillTrackData(AliHLTMUONMansoTrackStruct& track)
356 {
357 // Implementation of AliHLTMUONMansoTrackerFSM::FillTrackData
358
359         DebugTrace("FillTrack: st5 = " << fSt5rec->fClusterPoint << ", st4 = " << fFoundPoint->fClusterPoint);
360         
361         track.fId = fTrackId;
362         // Increment track Id and keep it positive.
363         //TODO: handle the wrapparound better.
364         if (fTrackId < 0x7FFFFFFF)
365                 fTrackId++;
366         else
367                 fTrackId = 0;
368         
369         track.fTrigRec = fTriggerId;
370         
371         AliHLTFloat32_t x1 = fFoundPoint->fClusterPoint.fX;
372         AliHLTFloat32_t y1 = fFoundPoint->fClusterPoint.fY;
373         AliHLTFloat32_t z1 = fFoundPoint->fClusterPoint.fZ;
374         AliHLTFloat32_t y2 = fSt5rec->fClusterPoint.fY;
375         AliHLTFloat32_t z2 = fSt5rec->fClusterPoint.fZ;
376         
377         bool calculated = AliHLTMUONCalculations::ComputeMomentum(x1, y1, y2, z1, z2);
378         
379         track.fPx = AliHLTMUONCalculations::Px();
380         track.fPy = AliHLTMUONCalculations::Py();
381         track.fPz = AliHLTMUONCalculations::Pz();
382         DebugTrace("Calculated Px = " << track.fPx << ", Py = " << track.fPy
383                 << ", Pz = " << track.fPx
384         );
385         DebugTrace("\tusing x1 = " << x1 << " , y1 = " << y1 << " , y2 = " << y2
386                 << " , z1 = " << z1 << " , z2 = " << z2
387         );
388         
389         track.fChi2 = 0;
390         
391         bool hitset[4];
392         // Depending on which chamber we found reconstructed hits, fill the hit
393         // in the appropriate location. This is done for station 4 then 5.
394         if (fSt4chamber == kChamber8)
395         {
396                 track.fHit[0] = AliHLTMUONConstants::NilRecHitStruct();
397                 hitset[0] = false;
398                 track.fHit[1] = fFoundPoint->fClusterPoint;
399                 hitset[1] = true;
400         }
401         else
402         {
403                 track.fHit[0] = fFoundPoint->fClusterPoint;
404                 hitset[0] = true;
405                 track.fHit[1] = AliHLTMUONConstants::NilRecHitStruct();
406                 hitset[1] = false;
407         }
408         if (fMc1.fChamber == kChamber10)
409         {
410                 track.fHit[2] = AliHLTMUONConstants::NilRecHitStruct();
411                 hitset[2] = false;
412                 track.fHit[3] = fSt5rec->fClusterPoint;
413                 hitset[3] = true;
414         }
415         else
416         {
417                 track.fHit[2] = fSt5rec->fClusterPoint;
418                 hitset[2] = true;
419                 track.fHit[3] = AliHLTMUONConstants::NilRecHitStruct();
420                 hitset[3] = false;
421         }
422         
423         track.fFlags = AliHLTMUONUtils::PackMansoTrackFlags(
424                         AliHLTMUONCalculations::Sign(), hitset
425                 );
426         return calculated;
427 }
428
429
430 void AliHLTMUONMansoTrackerFSM::Reset()
431 {
432 // Implementation of AliHLTMUONMansoTrackerFSM::Reset
433
434         DebugTrace("SM5 state = " << fSm5state << " , SM4 state = " << fSm4state);
435         fSt5data.Clear();
436         fSt4points.Clear();
437         fSm4state = kSM4Idle;
438         fSm5state = kSM5Idle;
439         fRequestsCompleted = 0;
440         fTriggerId = -1;
441 }
442
443
444 // Note: In the following ReceiveClustersXXX and EndOfClustersXXX methods we make
445 // the state machine transitions before calls to RequestClusters, FoundTrack, 
446 // NoTrackFound or EndOfClusterRequests. This is important since the callback
447 // object will make recursive calls to the tracker's methods so we need to maintain
448 // a consistant internal state.
449 // The same would go for updating internal variables.
450 // In general one should only call the callback methods at the end of any of the
451 // following routines.
452
453 void AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber7(
454                 const AliHLTMUONRecHitStruct* clusters, AliHLTUInt32_t count,
455                 const AliTagData* data
456         )
457 {
458 // State change method for Station 4 state machine.
459
460         switch (fSm4state)
461         {
462         case kWaitChamber7:
463                 fSm4state = kWaitMoreChamber7;
464         
465         case kWaitMoreChamber7:
466                 for (AliHLTUInt32_t j = 0; j < count; j++)
467                 {
468                         AliHLTMUONRecHitStruct cluster = clusters[j];
469                         // Check that the cluster actually is in our region of interest on station 4.
470                         if ( data->fRoi.Contains(cluster) )
471                         {
472                                 DebugTrace("Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 7.");
473                                 AliStation4Data* newdata = fSt4points.Add();
474                                 newdata->fClusterPoint = cluster;
475                                 newdata->fSt5tag = data;
476                         }
477                 }
478                 break;
479         
480         default:
481                 DebugTrace("ERROR: Unexpected state for SM4 in AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber7!");
482         }
483 }
484
485
486 void AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber8(
487                 const AliHLTMUONRecHitStruct* clusters, AliHLTUInt32_t count,
488                 const AliTagData* data
489         )
490 {
491 // State change method for Station 4 state machine.
492
493         switch (fSm4state)
494         {
495         case kWaitChamber8:
496                 fSm4state = kWaitMoreChamber8;
497                 fSt4chamber = kChamber8;
498         
499         case kWaitMoreChamber8:
500                 for (AliHLTUInt32_t j = 0; j < count; j++)
501                 {
502                         AliHLTMUONRecHitStruct cluster = clusters[j];
503                         // Check that the cluster actually is in our region of interest on station 4.
504                         if ( data->fRoi.Contains(cluster) )
505                         {
506                                 DebugTrace("Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 8.");
507                                 AliStation4Data* newdata = fSt4points.Add();
508                                 newdata->fClusterPoint = cluster;
509                                 newdata->fSt5tag = data;
510                         }
511                 }
512                 break;
513                 
514         default:
515                 DebugTrace("ERROR: Unexpected state for SM4 in AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber8!");
516         }
517 }
518
519
520 void AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber9(
521                 const AliHLTMUONRecHitStruct* clusters, AliHLTUInt32_t count
522         )
523 {
524 // State change method for Station 5 state machine.
525
526         switch (fSm5state)
527         {
528         case kWaitChamber9:
529                 fSm5state = kWaitMoreChamber9;
530                 fSm4state = kWaitChamber8;  // Start SM4.
531         
532         case kWaitMoreChamber9:
533                 for (AliHLTUInt32_t j = 0; j < count; j++)
534                 {
535                         AliHLTMUONRecHitStruct cluster = clusters[j];
536                         // Check that the cluster actually is in our region of interest on station 5.
537                         if ( fMc1.fRoi.Contains(cluster) )
538                         {
539                                 DebugTrace("Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 9.");
540                                 AliStation5Data* data = fSt5data.Add();
541                                 data->fClusterPoint = cluster;
542                                 ProjectToStation4(data, fgZ9);  // This adds a new request for station 4.
543                         }
544                 }
545                 break;
546
547         default:
548                 DebugTrace("ERROR: Unexpected state for SM5 in AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber9!");
549         }
550 }
551
552
553 void AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber10(
554                 const AliHLTMUONRecHitStruct* clusters, AliHLTUInt32_t count
555         )
556 {
557 // State change method for Station 5 state machine.
558
559         switch (fSm5state)
560         {
561         case kWaitChamber10:
562                 fSm5state = kWaitMoreChamber10;
563                 fSm4state = kWaitChamber8;  // Start SM4.
564         
565         case kWaitMoreChamber10:
566                 for (AliHLTUInt32_t j = 0; j < count; j++)
567                 {
568                         AliHLTMUONRecHitStruct cluster = clusters[j];
569                         // Check that the cluster actually is in our region of interest on station 5.
570                         if ( fMc1.fRoi.Contains(cluster) )
571                         {
572                                 DebugTrace("Adding cluster [" << cluster.fX << ", " << cluster.fY << "] from chamber 10.");
573                                 AliStation5Data* data = fSt5data.Add();
574                                 data->fClusterPoint = cluster;
575                                 ProjectToStation4(data, fgZ10);  // This adds a new request for station 4.
576                         }
577                 }
578                 break;
579
580         default:
581                 DebugTrace("ERROR: Unexpected state for SM5 in AliHLTMUONMansoTrackerFSM::ReceiveClustersChamber10!");
582         }
583 }
584
585
586 void AliHLTMUONMansoTrackerFSM::EndOfClustersChamber7()
587 {
588 // State change method for Station 4 state machine.
589
590         fRequestsCompleted++;  // Increment the number of requests completed for station 4.
591         DebugTrace("fRequestsCompleted = " << fRequestsCompleted );
592
593         switch (fSm4state)
594         {
595         case kWaitChamber7:
596                 // If all data from station 5 is received and no data found on
597                 // chambers 7 or 8 then we can not find a track.
598                 if (fSm5state == kSM5Done) NoTrackFound();
599                 break;
600         
601         case kWaitMoreChamber7:
602                 if (fRequestsCompleted == fSt5data.Count() && fSm5state == kSM5Done)
603                         ProcessClusters();
604                 break;
605         
606         default:
607                 DebugTrace("ERROR: Unexpected state for SM4 in AliHLTMUONMansoTrackerFSM::EndOfClustersChamber7!");
608         }
609 }
610
611
612 void AliHLTMUONMansoTrackerFSM::EndOfClustersChamber8()
613 {
614 // State change method for Station 4 state machine.
615
616         fRequestsCompleted++;  // Increment the number of requests completed for station 4.
617         DebugTrace("fRequestsCompleted = " << fRequestsCompleted );
618
619         switch (fSm4state)
620         {
621         case kWaitChamber7:
622                 // Ignore. The requests for chamber 8 are already re-requested below.
623                 break;
624                 
625         case kWaitChamber8:
626                 {
627                 fSm4state = kWaitChamber7;
628                 fSt4chamber = kChamber7;
629         
630                 // We need to resend the requests for chamber 8, but change the request
631                 // to get data for chamber 7 instead:
632                 AliHLTUInt32_t reqlistsize = fSt5data.Count();
633                 DebugTrace("Re-requesting clusters from chamber 7... reqlistsize = " << reqlistsize);
634
635                 Station5List::Iterator rec = fSt5data.First();
636                 for (AliHLTUInt32_t i = 0; i < reqlistsize; i++, rec++)
637                 {
638                         // Need to create a new st5 data block for the request.
639                         AliStation5Data* data = fSt5data.Add();
640                         data->fClusterPoint = rec->fClusterPoint;
641                         data->fTag.fLine = rec->fTag.fLine;
642
643                         // Rebuild a region of interest for chamber 7.
644                         // Remember the parameters a and b are station specific.
645                         AliHLTMUONRecHitStruct p7 = data->fTag.fLine.FindIntersectWithXYPlain( fgZ7 );
646                         data->fTag.fChamber = kChamber7;
647                         data->fTag.fRoi.Create(p7, fgA7, fgB7);
648                         
649                         AliHLTFloat32_t left, right, bottom, top;
650                         data->fTag.fRoi.GetBoundaryBox(left, right, bottom, top);
651                         // Make request for chamber 7 data.
652                         RequestClusters(left, right, bottom, top, kChamber7, &data->fTag);
653                 }
654                 }
655                 break;
656         
657         case kWaitMoreChamber8:
658                 if (fRequestsCompleted == fSt5data.Count() && fSm5state == kSM5Done)
659                         ProcessClusters();
660                 break;
661         
662         default:
663                 DebugTrace("ERROR: Unexpected state for SM4 in AliHLTMUONMansoTrackerFSM::EndOfClustersChamber8!");
664         }
665 }
666
667
668 void AliHLTMUONMansoTrackerFSM::EndOfClustersChamber9()
669 {
670 // State change method for Station 5 state machine.
671
672         switch (fSm5state)
673         {
674         case kWaitChamber9:
675                 fSm5state = kSM5Done;
676                 EndOfClusterRequests();
677                 NoTrackFound();
678                 break;
679                 
680         case kWaitMoreChamber9:
681                 fSm5state = kSM5Done;
682                 EndOfClusterRequests();
683                 if (fRequestsCompleted == fSt5data.Count())
684                         ProcessClusters();
685                 break;
686
687         default:
688                 DebugTrace("ERROR: Unexpected state for SM5 in AliHLTMUONMansoTrackerFSM::EndOfClustersChamber9!");
689         }
690 }
691
692
693 void AliHLTMUONMansoTrackerFSM::EndOfClustersChamber10()
694 {
695 // State change method for Station 5 state machine.
696
697         switch (fSm5state)
698         {
699         case kWaitChamber10:
700                 {
701                 fSm5state = kWaitChamber9;
702                 
703                 // No clusters found on chamber 10 so we need to make a request for
704                 // clusters from chamber 9:
705                 AliHLTMUONRecHitStruct p9 = fMc1.fLine.FindIntersectWithXYPlain( fgZ9 );
706
707                 // Build a region of interest for tracking station 5 (chamber 9).
708                 // Remember the parameters a and b are station specific.
709                 fMc1.fChamber = kChamber9;
710                 fMc1.fRoi.Create(p9, fgA9, fgB9);
711
712                 AliHLTFloat32_t left, right, bottom, top;
713                 fMc1.fRoi.GetBoundaryBox(left, right, bottom, top);
714                 RequestClusters(left, right, bottom, top, kChamber9, &fMc1);
715                 }
716                 break;
717
718         case kWaitMoreChamber10:
719                 fSm5state = kSM5Done;
720                 EndOfClusterRequests();
721                 if (fRequestsCompleted == fSt5data.Count())
722                         ProcessClusters();
723                 break;
724
725         default:
726                 DebugTrace("ERROR: Unexpected state for SM5 in AliHLTMUONMansoTrackerFSM::EndOfClustersChamber10!");
727         }
728 }
729
730
731 void AliHLTMUONMansoTrackerFSM::ProjectToStation4(
732                 AliStation5Data* data, register AliHLTFloat32_t station5z
733         )
734 {
735         // Perform chamber specific operations:
736         // Since certain states of SM4 means that it is fetching for Chamber8
737         // and other states are for fetching from Chamber7. We need to make
738         // requests for the correct chamber.
739         assert( fSm4state == kWaitChamber8 
740                 || fSm4state == kWaitMoreChamber8
741                 || fSm4state == kWaitChamber7
742                 || fSm4state == kWaitMoreChamber7
743         );
744         AliTagData* tag = &data->fTag;
745         if (fSm4state == kWaitChamber8 || fSm4state == kWaitMoreChamber8)
746         {
747                 // Form the vector line between trigger station 1 and tracking station 5,
748                 // and find the intersection point of the line with station 4 (chamber8).
749                 AliLine line51( AliVertex(data->fClusterPoint, station5z), fV1 );
750                 AliHLTMUONRecHitStruct intercept = line51.FindIntersectWithXYPlain( fgZ8 );
751                 tag->fLine = line51;
752                 
753                 // Build a region of interest for tracking station 4.
754                 tag->fChamber = kChamber8;
755                 tag->fRoi.Create(intercept, fgA8, fgB8);
756         }
757         else
758         {
759                 // Form the vector line between trigger station 1 and tracking station 5,
760                 // and find the intersection point of the line with station 4 (chamber7).
761                 AliLine line51( AliVertex(data->fClusterPoint, station5z), fV1 );
762                 AliHLTMUONRecHitStruct intercept = line51.FindIntersectWithXYPlain( fgZ7 );
763                 tag->fLine = line51;
764                 
765                 // Build a region of interest for tracking station 4.
766                 tag->fChamber = kChamber7;
767                 tag->fRoi.Create(intercept, fgA7, fgB7);
768         }
769
770         // Make the request for clusters from station 4.
771         AliHLTFloat32_t left, right, bottom, top;
772         tag->fRoi.GetBoundaryBox(left, right, bottom, top);
773         RequestClusters(left, right, bottom, top, tag->fChamber, tag);
774 }
775
776
777 void AliHLTMUONMansoTrackerFSM::ProcessClusters()
778 {
779 // Process clusters that have been received.
780 // This is called once all clusters have been found.
781
782         DebugTrace("ProcessClusters...");
783         
784         // Check if the cluster point list on station 4 is empty.
785         // If it is then we have not found any tracks.
786         fFoundPoint = fSt4points.First();
787         if (fFoundPoint == fSt4points.End())
788         {
789                 NoTrackFound();
790                 return;
791         }
792         
793         fSt5rec = fSt5data.First();
794         if (fSt5rec != fSt5data.End())
795         {
796                 // Only look at station 5 data records that are for the found chamber number.
797                 // Note: either we only have chamber 8 data or we have chamber 7 data followed
798                 // by chamber 8 data.
799                 // Thus if we hit records that we are not interested in already then the list
800                 // contains no interesting data and we can signal no track found.
801                 if (fSt5rec->fTag.fChamber != fSt4chamber)
802                 {
803                         NoTrackFound();
804                         return;
805                 }
806                  
807                 // For all combinations of cluster point pairs from station 4 and 5
808                 // signal a found track:
809                 do
810                 {
811                         DebugTrace("\tfSt5rec->fTag.chamber = " << fSt5rec->fTag.fChamber
812                                 << " , fSt4chamber = " << fSt4chamber
813                         );
814
815                         for (fFoundPoint = fSt4points.First(); fFoundPoint != fSt4points.End(); fFoundPoint++)
816                         {
817                                 if (fFoundPoint->fSt5tag == &fSt5rec->fTag)
818                                         FoundTrack();
819                         }
820
821                         fSt5rec++;  // Get next station 5 cluster point.
822                 } while (fSt5rec != fSt5data.End() && fSt5rec->fTag.fChamber == fSt4chamber);
823         }
824         else
825                 NoTrackFound();
826 }
827