1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Artur Szostak
4 // Email: artur@alice.phy.uct.ac.za | artursz@iafrica.com
6 ////////////////////////////////////////////////////////////////////////////////
8 #include "Tracking/MansoTracker.hpp"
10 #include "Tracking/Calculations.hpp"
13 #include "RegionOfInterest.hpp"
18 #include "Debug/print.hpp"
22 using dHLT::Tracking::MansoTracker;
24 std::ostream& operator << (std::ostream& os, MansoTracker::StatesSM4 state)
28 case MansoTracker::SM4Idle: os << "SM4Idle"; break;
29 case MansoTracker::WaitChamber8: os << "WaitChamber8"; break;
30 case MansoTracker::WaitMoreChamber8: os << "WaitMoreChamber8"; break;
31 case MansoTracker::WaitChamber7: os << "WaitChamber7"; break;
32 case MansoTracker::WaitMoreChamber7: os << "WaitMoreChamber7"; break;
33 default: os << "FAULT!!";
38 std::ostream& operator << (std::ostream& os, MansoTracker::StatesSM5 state)
42 case MansoTracker::SM5Idle: os << "SM5Idle"; break;
43 case MansoTracker::WaitChamber10: os << "WaitChamber10"; break;
44 case MansoTracker::WaitMoreChamber10: os << "WaitMoreChamber10"; break;
45 case MansoTracker::WaitChamber9: os << "WaitChamber9"; break;
46 case MansoTracker::WaitMoreChamber9: os << "WaitMoreChamber9"; break;
47 case MansoTracker::SM5Done: os << "SM5Done"; break;
48 default: os << "FAULT!!";
53 }; // end of namespace
63 // Deviate from the Manso implementation by allowing a and b
64 // parameters per chamber and not just per station.
65 // The default values are derived from the work done in
66 // "A first algorithm for dimuon High Level Trigger"
67 // Ref ID: ALICE-INT-2002-04 version 1.0
68 Float MansoTracker::a7 = 0.016f;
69 Float MansoTracker::b7 = 2.0f;
70 Float MansoTracker::a8 = 0.016f;
71 Float MansoTracker::b8 = 2.0f;
72 Float MansoTracker::a9 = 0.020f;
73 Float MansoTracker::b9 = 3.0f;
74 Float MansoTracker::a10 = 0.020f;
75 Float MansoTracker::b10 = 3.0f;
76 Float MansoTracker::z7 = 1251.5f;
77 Float MansoTracker::z8 = 1278.5f;
78 Float MansoTracker::z9 = 1416.5f;
79 Float MansoTracker::z10 = 1443.5f;
80 Float MansoTracker::z11 = 1603.5f;
81 Float MansoTracker::z13 = 1703.5f;
84 void MansoTracker::RegionOfInterest::Create(Point p, Float a, Float b)
87 // Compute the radius Rp
88 Float Rp = (Float) sqrt( p.x * p.x + p.y * p.y );
90 // The radius Rs for the region of interest is computed from the
91 // specification given in the document:
92 // "A first algorithm for dimuon High Level Trigger"
93 // Ref ID: ALICE-INT-2002-04 version 1.0
96 // given on page 3 section 4.
101 bool MansoTracker::RegionOfInterest::Contains(Point p) const
103 // Compute the distance between the centre of the region of interest and
104 // the point p. This distance must be less than the radius of the region
105 // of interest for p to be contained in the region of interest.
106 register Float lx = centre.x - p.x;
107 register Float ly = centre.y - p.y;
108 register Float r = (Float) sqrt( lx * lx + ly * ly );
109 DebugMsg(4, "\tRegionOfInterest::Contains : p = " << p
110 << " , centre = " << centre << " , r = " << r << " , Rs = " << Rs
116 void MansoTracker::RegionOfInterest::GetBoundaryBox(Float& left, Float& right, Float& bottom, Float& top)
118 left = centre.x - Rs;
119 right = centre.x + Rs;
120 bottom = centre.y - Rs;
125 MansoTracker::Vertex::Vertex(Float x, Float y, Float z)
133 MansoTracker::Vertex::Vertex(Point xy, Float z)
141 MansoTracker::Line::Line(
142 Float Ax, Float Ay, Float Az,
143 Float Bx, Float By, Float Bz
155 MansoTracker::Line::Line(Vertex A, Vertex B)
166 Point MansoTracker::Line::FindIntersectWithXYPlain(Float z) const
168 Assert( Mz != 0.0 ); // Should not have a ray perpendicular to the beam axis.
169 Float t = (z - Cz) / Mz;
170 Float Lx = Mx*t + Cx;
171 Float Ly = My*t + Cy;
173 return Point(Lx, Ly);
177 MansoTracker::MansoTracker() : Tracker()
181 requests_completed = 0;
185 void MansoTracker::FindTrack(const TriggerRecord& trigger)
187 DebugMsg(4, "SM5 state = " << sm5state << " , SM4 state = " << sm4state);
188 DebugMsg(1, "Processing trigger with pt = " << trigger.pt);
189 v1 = Vertex( trigger.station1impact, z11 );
190 Vertex v2 = Vertex( trigger.station2impact, z13 );
192 // Form the vector line between the above two impact points and
193 // find the crossing point of the line with chamber 10 (i.e. station 5).
194 mc1.line = Line(v1, v2);
195 Point p10 = mc1.line.FindIntersectWithXYPlain( z10 );
197 // Build a region of interest for tracking station 5 (chamber 10).
198 // Remember the parameters a and b are station specific.
199 mc1.chamber = Chamber10;
200 mc1.roi.Create(p10, a10, b10);
202 // Make SM5 state transition before the call to RequestClusters since
203 // that method could call one of our methods again, so we need to be
204 // in a consistant internal state.
205 sm5state = WaitChamber10;
207 Float left, right, bottom, top;
208 mc1.roi.GetBoundaryBox(left, right, bottom, top);
209 RequestClusters(left, right, bottom, top, Chamber10, &mc1);
213 void MansoTracker::ReturnClusters(void* tag, const ClusterPoint* clusters, UInt count)
216 Assert( clusters != NULL );
218 TagData* data = (TagData*)tag;
219 DebugMsg(4, "Got MansoTracker::ReturnClusters(tag = " << tag
220 << ", chamber = " << data->chamber
221 << ", clusters = " << clusters << ", count = " << count << ")"
223 DebugMsg(4, "SM5 state = " << sm5state << " , SM4 state = " << sm4state);
225 switch (data->chamber)
227 case Chamber7: ReceiveClustersChamber7(clusters, count, data); break;
228 case Chamber8: ReceiveClustersChamber8(clusters, count, data); break;
229 case Chamber9: ReceiveClustersChamber9(clusters, count); break;
230 case Chamber10: ReceiveClustersChamber10(clusters, count); break;
233 DebugMsg(1, "ERROR: Got tag with an invalid value: " << data->chamber);
238 void MansoTracker::EndOfClusters(void* tag)
240 TagData* data = (TagData*)tag;
241 DebugMsg(4, "Got MansoTracker::EndOfClusters(chamber = " << data->chamber << ")");
242 DebugMsg(4, "SM5 state = " << sm5state << " , SM4 state = " << sm4state);
244 switch (data->chamber)
246 case Chamber7: EndOfClustersChamber7(); break;
247 case Chamber8: EndOfClustersChamber8(); break;
248 case Chamber9: EndOfClustersChamber9(); break;
249 case Chamber10: EndOfClustersChamber10(); break;
252 DebugMsg(1, "ERROR: Got tag with an invalid value: " << data->chamber);
257 void MansoTracker::FillTrackData(Track& track)
259 DebugMsg(4, "FillTrack: st5 = " << st5rec->clusterpoint << ", st4 = " << *foundpoint);
261 Float x1 = foundpoint->x;
262 Float y1 = foundpoint->y;
263 Float y2 = st5rec->clusterpoint.y;
265 Float pt = CalculateSignedPt(x1, y1, y2, st4z, st5z, momentum);
266 DebugMsg(1, "Calculated Pt = " << pt);
267 DebugMsg(1, "\tusing x1 = " << x1 << " , y1 = " << y1 << " , y2 = " << y2
268 << " , z1 = " << st4z << " , z2 = " << st5z
276 track.sign = UnknownSign;
279 track.pt = (Float) fabs(pt);
280 for (UInt i = 0; i < 6; i++)
282 track.point[i] = Point(0.0, 0.0);
283 track.region[i] = INVALID_ROI;
286 Float left, right, bottom, top;
288 // Have to create the ROI numbers from the internal region of interest structures.
289 st5rec->tag.roi.GetBoundaryBox(left, right, bottom, top);
290 dHLT::RegionOfInterest region4(left, right, bottom, top, st4chamber);
291 mc1.roi.GetBoundaryBox(left, right, bottom, top);
292 dHLT::RegionOfInterest region5(left, right, bottom, top, mc1.chamber);
294 // Depending on the chamber we received cluster points from, fill the appropriate
295 // point and ROI number. This is done for station 4 then 5.
296 if (st4chamber == Chamber8)
298 track.point[6] = Point(0.0, 0.0);
299 track.region[6] = INVALID_ROI;
300 track.point[7] = *foundpoint;
301 track.region[7] = region4;
305 track.point[6] = *foundpoint;
306 track.region[6] = region4;
307 track.point[7] = Point(0.0, 0.0);
308 track.region[7] = INVALID_ROI;
310 if (mc1.chamber == Chamber10)
312 track.point[8] = Point(0.0, 0.0);
313 track.region[8] = INVALID_ROI;
314 track.point[9] = st5rec->clusterpoint;
315 track.region[9] = region5;
319 track.point[8] = st5rec->clusterpoint;
320 track.region[8] = region5;
321 track.point[9] = Point(0.0, 0.0);
322 track.region[9] = INVALID_ROI;
327 void MansoTracker::Reset()
329 DebugMsg(4, "SM5 state = " << sm5state << " , SM4 state = " << sm4state);
334 requests_completed = 0;
338 // Note: In the following ReceiveClustersXXX and EndOfClustersXXX methods we make
339 // the state machine transitions before calls to RequestClusters, FoundTrack,
340 // NoTrackFound or EndOfClusterRequests. This is important since the callback
341 // object will make recursive calls the trackers methods so we need to maintain
342 // a consistant internal state.
343 // The same would go for updating internal variables.
344 // In general one should only call the callback methods at the end of any of the
345 // following routines.
347 void MansoTracker::ReceiveClustersChamber7(const ClusterPoint* clusters, UInt count, const TagData* data)
352 sm4state = WaitMoreChamber7;
354 case WaitMoreChamber7:
355 for (UInt j = 0; j < count; j++)
357 ClusterPoint cluster = clusters[j];
358 // Check that the cluster actually is in our region of interest on station 4.
359 if ( data->roi.Contains(cluster) )
361 DebugMsg(4, "Adding cluster [" << cluster.x << ", " << cluster.y << "] from chamber 7.");
362 st4points.Add(cluster);
368 DebugMsg(1, "ERROR: Unexpected state for SM4 in MansoTracker::ReceiveClustersChamber7!");
373 void MansoTracker::ReceiveClustersChamber8(const ClusterPoint* clusters, UInt count, const TagData* data)
378 sm4state = WaitMoreChamber8;
380 st4chamber = Chamber8;
382 case WaitMoreChamber8:
383 for (UInt j = 0; j < count; j++)
385 ClusterPoint cluster = clusters[j];
386 // Check that the cluster actually is in our region of interest on station 4.
387 if ( data->roi.Contains(cluster) )
389 DebugMsg(4, "Adding cluster [" << cluster.x << ", " << cluster.y << "] from chamber 8.");
390 st4points.Add(cluster);
396 DebugMsg(1, "ERROR: Unexpected state for SM4 in MansoTracker::ReceiveClustersChamber8!");
401 void MansoTracker::ReceiveClustersChamber9(const ClusterPoint* clusters, UInt count)
406 sm5state = WaitMoreChamber9;
407 sm4state = WaitChamber8; // Start SM4.
409 case WaitMoreChamber9:
410 for (UInt j = 0; j < count; j++)
412 ClusterPoint cluster = clusters[j];
413 // Check that the cluster actually is in our region of interest on station 5.
414 if ( mc1.roi.Contains(cluster) )
416 DebugMsg(4, "Adding cluster [" << cluster.x << ", " << cluster.y << "] from chamber 9.");
417 Station5Data* data = st5data.New();
418 data->clusterpoint = cluster;
419 ProjectToStation4(data, z9); // This adds a new request for station 4.
425 DebugMsg(1, "ERROR: Unexpected state for SM5 in MansoTracker::ReceiveClustersChamber9!");
430 void MansoTracker::ReceiveClustersChamber10(const ClusterPoint* clusters, UInt count)
435 sm5state = WaitMoreChamber10;
437 sm4state = WaitChamber8; // Start SM4.
439 case WaitMoreChamber10:
440 for (UInt j = 0; j < count; j++)
442 ClusterPoint cluster = clusters[j];
443 // Check that the cluster actually is in our region of interest on station 5.
444 if ( mc1.roi.Contains(cluster) )
446 DebugMsg(4, "Adding cluster [" << cluster.x << ", " << cluster.y << "] from chamber 10.");
447 Station5Data* data = st5data.New();
448 data->clusterpoint = cluster;
449 ProjectToStation4(data, z10); // This adds a new request for station 4.
455 DebugMsg(1, "ERROR: Unexpected state for SM5 in MansoTracker::ReceiveClustersChamber10!");
460 void MansoTracker::EndOfClustersChamber7()
462 requests_completed++; // Increment the number of requests completed for station 4.
463 DebugMsg(4, "requests_completed = " << requests_completed );
468 // If all data from station 5 is received and no data found on
469 // chambers 7 or 8 then we can not find a track.
470 if (sm5state == SM5Done) NoTrackFound();
473 case WaitMoreChamber7:
474 if (requests_completed == st5data.Count() and sm5state == SM5Done)
479 DebugMsg(1, "ERROR: Unexpected state for SM4 in MansoTracker::EndOfClustersChamber7!");
484 void MansoTracker::EndOfClustersChamber8()
486 requests_completed++; // Increment the number of requests completed for station 4.
487 DebugMsg(4, "requests_completed = " << requests_completed );
492 // Ignore. The requests for chamber 8 are already re-requested below.
497 sm4state = WaitChamber7;
499 st4chamber = Chamber7;
501 // We need to resend the requests for chamber 8, but change the request
502 // to get data for chamber 7 instead:
503 UInt reqlistsize = st5data.Count();
504 DebugMsg(4, "Re-requesting clusters from chamber 7... reqlistsize = " << reqlistsize);
506 Station5List::Iterator rec = st5data.First();
507 for (UInt i = 0; i < reqlistsize; i++, rec++)
509 // Need to create a new st5 data block for the request.
510 Station5Data* data = st5data.New();
511 data->clusterpoint = rec->clusterpoint;
512 data->tag.line = rec->tag.line;
514 // Rebuild a region of interest for chamber 7.
515 // Remember the parameters a and b are station specific.
516 Point p7 = data->tag.line.FindIntersectWithXYPlain( z7 );
517 data->tag.chamber = Chamber7;
518 data->tag.roi.Create(p7, a7, b7);
520 Float left, right, bottom, top;
521 data->tag.roi.GetBoundaryBox(left, right, bottom, top);
522 // Make request for chamber 7 data.
523 RequestClusters(left, right, bottom, top, Chamber7, &data->tag);
528 case WaitMoreChamber8:
529 if (requests_completed == st5data.Count() and sm5state == SM5Done)
534 DebugMsg(1, "ERROR: Unexpected state for SM4 in MansoTracker::EndOfClustersChamber8!");
539 void MansoTracker::EndOfClustersChamber9()
545 EndOfClusterRequests();
549 case WaitMoreChamber9:
551 EndOfClusterRequests();
552 if (requests_completed == st5data.Count())
557 DebugMsg(1, "ERROR: Unexpected state for SM5 in MansoTracker::EndOfClustersChamber9!");
562 void MansoTracker::EndOfClustersChamber10()
568 sm5state = WaitChamber9;
571 // No clusters found on chamber 10 so we need to make a request for
572 // clusters from chamber 9:
573 Point p9 = mc1.line.FindIntersectWithXYPlain( z9 );
575 // Build a region of interest for tracking station 5 (chamber 9).
576 // Remember the parameters a and b are station specific.
577 mc1.chamber = Chamber9;
578 mc1.roi.Create(p9, a9, b9);
580 Float left, right, bottom, top;
581 mc1.roi.GetBoundaryBox(left, right, bottom, top);
582 RequestClusters(left, right, bottom, top, Chamber9, &mc1);
586 case WaitMoreChamber10:
588 EndOfClusterRequests();
589 if (requests_completed == st5data.Count())
594 DebugMsg(1, "ERROR: Unexpected state for SM5 in MansoTracker::EndOfClustersChamber10!");
599 void MansoTracker::ProjectToStation4(Station5Data* data, register Float station5z)
601 // Perform chamber specific operations:
602 // Since certain states of SM4 means that it is fetching for Chamber8
603 // and other states are for fetching from Chamber7. We need to make
604 // requests for the correct chamber.
605 Assert( sm4state == WaitChamber8 or sm4state == WaitMoreChamber8 or
606 sm4state == WaitChamber7 or sm4state == WaitMoreChamber7
608 TagData* tag = &data->tag;
609 if (sm4state == WaitChamber8 or sm4state == WaitMoreChamber8)
611 // Form the vector line between trigger station 1 and tracking station 5,
612 // and find the intersection point of the line with station 4 (chamber8).
613 Line line51( Vertex(data->clusterpoint, station5z), v1 );
614 Point intercept = line51.FindIntersectWithXYPlain(z8);
617 // Build a region of interest for tracking station 4.
618 tag->chamber = Chamber8;
619 tag->roi.Create(intercept, a8, b8);
623 // Form the vector line between trigger station 1 and tracking station 5,
624 // and find the intersection point of the line with station 4 (chamber7).
625 Line line51( Vertex(data->clusterpoint, station5z), v1 );
626 Point intercept = line51.FindIntersectWithXYPlain(z7);
629 // Build a region of interest for tracking station 4.
630 tag->chamber = Chamber7;
631 tag->roi.Create(intercept, a7, b7);
634 // Make the request for clusters from station 4.
635 Float left, right, bottom, top;
636 tag->roi.GetBoundaryBox(left, right, bottom, top);
637 RequestClusters(left, right, bottom, top, tag->chamber, tag);
641 void MansoTracker::ProcessClusters()
643 DebugMsg(2, "ProcessClusters...");
645 // Check if the cluster point list on station 4 is empty.
646 // If it is then we have not found any tracks.
647 foundpoint = st4points.First();
648 if (foundpoint == st4points.End())
654 st5rec = st5data.First();
655 if (st5rec != st5data.End())
657 // Only look at station 5 data records that are for the found chamber number.
658 // Note: either we only have chamber 8 data or we have chamber 7 data followed
659 // by chamber 8 data.
660 // Thus if we hit records that we are not interested in already then the list
661 // contains no interesting data and we can signal no track found.
662 if (st5rec->tag.chamber != st4chamber)
668 // For all combinations of cluster point pairs from station 4 and 5
669 // signal a found track:
672 DebugMsg(4, "\tst5rec->tag.chamber = " << st5rec->tag.chamber
673 << " , st4chamber = " << st4chamber
676 for (foundpoint = st4points.First(); foundpoint != st4points.End(); foundpoint++)
679 st5rec++; // Get next station 5 cluster point.
680 } while (st5rec != st5data.End() and st5rec->tag.chamber == st4chamber);