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