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