]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONMansoTrackerFSMComponent.cxx
c810bbf4aa347fa654252afb04135907b56b0139
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONMansoTrackerFSMComponent.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  *   Indranil Das <indra.das@saha.ac.in>                                  *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          * 
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 /* $Id$ */
19
20 ///
21 ///  @file   AliHLTMUONMansoTrackerFSMComponent.cxx
22 ///  @author Artur Szostak <artursz@iafrica.com>,
23 ///          Indranil Das <indra.das@saha.ac.in>
24 ///  @date   
25 ///  @brief  Implementation of AliHLTMUONMansoTrackerFSMComponent class.
26 ///
27
28 #include "AliHLTMUONMansoTrackerFSMComponent.h"
29 #include "AliHLTMUONConstants.h"
30 #include "AliHLTMUONUtils.h"
31 #include "AliHLTMUONMansoTrackerFSM.h"
32 #include "AliHLTMUONDataBlockReader.h"
33 #include "AliHLTMUONDataBlockWriter.h"
34 #include <cstdlib>
35 #include <cstring>
36 #include <cerrno>
37 #include <new>
38
39 ClassImp(AliHLTMUONMansoTrackerFSMComponent);
40
41
42 AliHLTMUONMansoTrackerFSMComponent::AliHLTMUONMansoTrackerFSMComponent() :
43         AliHLTProcessor(),
44         AliHLTMUONMansoTrackerFSMCallback(),
45         fTracker(NULL),
46         fTrackCount(0),
47         fBlock(NULL),
48         fRecHitBlockArraySize(0),
49         fWarnForUnexpecedBlock(false)
50 {
51         ///
52         /// Default constructor.
53         ///
54         
55         for (Int_t i = 0; i < 4; i++)
56         {
57                 fRecHitBlockCount[i] = 0;
58                 fRecHitBlock[i] = NULL;
59         }
60 }
61
62
63 AliHLTMUONMansoTrackerFSMComponent::~AliHLTMUONMansoTrackerFSMComponent()
64 {
65         ///
66         /// Default destructor.
67         ///
68         
69         assert( fTracker == NULL );
70         assert( fRecHitBlock[0] == NULL );
71 }
72
73
74 const char* AliHLTMUONMansoTrackerFSMComponent::GetComponentID()
75 {
76         ///
77         /// Inherited from AliHLTComponent. Returns the component ID.
78         ///
79         
80         return AliHLTMUONConstants::MansoTrackerFSMId();
81 }
82
83
84 void AliHLTMUONMansoTrackerFSMComponent::GetInputDataTypes(
85                 vector<AliHLTComponentDataType>& list
86         )
87 {
88         ///
89         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
90         ///
91         
92         assert( list.empty() );
93         list.push_back( AliHLTMUONConstants::TriggerRecordsBlockDataType() );
94         list.push_back( AliHLTMUONConstants::RecHitsBlockDataType() );
95 }
96
97
98 AliHLTComponentDataType AliHLTMUONMansoTrackerFSMComponent::GetOutputDataType()
99 {
100         ///
101         /// Inherited from AliHLTComponent. Returns the output data type.
102         ///
103         
104         return AliHLTMUONConstants::MansoTracksBlockDataType();
105 }
106
107
108 void AliHLTMUONMansoTrackerFSMComponent::GetOutputDataSize(
109                 unsigned long& constBase, double& inputMultiplier
110         )
111 {
112         ///
113         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
114         ///
115         
116         constBase = sizeof(AliHLTMUONMansoTracksBlockStruct);
117         inputMultiplier = 1;
118 }
119
120
121 AliHLTComponent* AliHLTMUONMansoTrackerFSMComponent::Spawn()
122 {
123         ///
124         /// Inherited from AliHLTComponent. Creates a new object instance.
125         ///
126         
127         return new AliHLTMUONMansoTrackerFSMComponent;
128 }
129
130
131 int AliHLTMUONMansoTrackerFSMComponent::DoInit(int argc, const char** argv)
132 {
133         ///
134         /// Inherited from AliHLTComponent.
135         /// Parses the command line parameters and initialises the component.
136         ///
137         
138         HLTInfo("Initialising dHLT manso tracker FSM component.");
139         
140         try
141         {
142                 fTracker = new AliHLTMUONMansoTrackerFSM();
143         }
144         catch (const std::bad_alloc&)
145         {
146                 HLTError("Could not allocate more memory for the tracker component.");
147                 return -ENOMEM;
148         }
149         fTracker->SetCallback(this);
150         
151         fWarnForUnexpecedBlock = false;
152         
153         for (int i = 0; i < argc; i++)
154         {
155                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
156                 {
157                         fWarnForUnexpecedBlock = true;
158                         continue;
159                 }
160
161                 HLTError("Unknown option '%s'.", argv[i]);
162                 return EINVAL;
163         }
164         
165         const int initArraySize = 10;
166         // allocate some initial memory for the reconstructed hit arrays.
167         try
168         {
169                 fRecHitBlock[0] = new AliRecHitBlockInfo[initArraySize*4];
170         }
171         catch (const std::bad_alloc&)
172         {
173                 HLTError("Could not allocate more memory for the reconstructed hit arrays.");
174                 return -ENOMEM;
175         }
176         // Only set the arrays' size once we have successfully allocated the memory for the arrays.
177         fRecHitBlockArraySize = initArraySize;
178         // Now we need to set the pointers fRecHitBlock[i] {i>0} relative to fRecHitBlock[0].
179         for (Int_t i = 1; i < 4; i++)
180         {
181                 fRecHitBlock[i] = fRecHitBlock[i-1] + fRecHitBlockArraySize;
182         }
183         // And reset the number of records actually stored in the arrays.
184         for (Int_t i = 0; i < 4; i++)
185         {
186                 fRecHitBlockCount[i] = 0;
187         }
188         
189         return 0;
190 }
191
192
193 int AliHLTMUONMansoTrackerFSMComponent::DoDeinit()
194 {
195         ///
196         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
197         ///
198         
199         HLTInfo("Deinitialising dHLT manso tracker FSM component.");
200         
201         if (fTracker != NULL)
202         {
203                 delete fTracker;
204                 fTracker = NULL;
205         }
206         
207         // Remember that only fRecHitBlock[0] stores the pointer to the allocated memory.
208         // The other pointers are just reletive to this.
209         if (fRecHitBlock[0] != NULL)
210                 delete [] fRecHitBlock[0];
211         
212         fRecHitBlockArraySize = 0;
213         for (Int_t i = 0; i < 4; i++)
214         {
215                 fRecHitBlockCount[i] = 0;
216                 fRecHitBlock[i] = NULL;
217         }
218         
219         return 0;
220 }
221
222
223 int AliHLTMUONMansoTrackerFSMComponent::DoEvent(
224                 const AliHLTComponentEventData& evtData,
225                 const AliHLTComponentBlockData* blocks,
226                 AliHLTComponentTriggerData& /*trigData*/,
227                 AliHLTUInt8_t* outputPtr,
228                 AliHLTUInt32_t& size,
229                 std::vector<AliHLTComponentBlockData>& outputBlocks
230         )
231 {
232         ///
233         /// Inherited from AliHLTProcessor. Processes the new event data.
234         ///
235         
236         Reset();
237         AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
238         
239         // Resize the rec hit arrays if we need to. To guarantee that they will not overflow
240         // we need to make sure each array is at least as big as the number of input data block.
241         if (fRecHitBlockArraySize < evtData.fBlockCnt)
242         {
243                 // Release the old memory block and allocate more memory.
244                 delete [] fRecHitBlock[0];
245                 // Reset the number of records actually stored in the arrays.
246                 for (Int_t i = 0; i < 4; i++)
247                 {
248                         fRecHitBlockCount[i] = 0;
249                 }
250                 
251                 try
252                 {
253                         fRecHitBlock[0] = new AliRecHitBlockInfo[evtData.fBlockCnt*4];
254                 }
255                 catch (const std::bad_alloc&)
256                 {
257                         HLTError("Could not allocate more memory for the reconstructed hit arrays.");
258                         // Ok so now we need to clear all the pointers because we actually
259                         // deleted the memory.
260                         fRecHitBlockArraySize = 0;
261                         for (Int_t i = 0; i < 4; i++)
262                         {
263                                 fRecHitBlock[i] = NULL;
264                         }
265                         return -ENOMEM;
266                 }
267                 // Only set the arrays' size once we have successfully allocated the memory for the arrays.
268                 fRecHitBlockArraySize = evtData.fBlockCnt;
269                 // Now we need to set the pointers fRecHitBlock[i] {i>0} relative to fRecHitBlock[0].
270                 for (Int_t i = 1; i < 4; i++)
271                 {
272                         fRecHitBlock[i] = fRecHitBlock[i-1] + fRecHitBlockArraySize;
273                 }
274         }
275         
276         AliHLTMUONMansoTracksBlockWriter block(outputPtr, size);
277         fBlock = &block;
278         
279         if (not block.InitCommonHeader())
280         {
281                 Logging(kHLTLogError,
282                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
283                         "Buffer overflow",
284                         "The buffer is only %d bytes in size. We need a minimum of %d bytes.",
285                         size, sizeof(AliHLTMUONMansoTracksBlockWriter::HeaderType)
286                 );
287                 size = 0; // Important to tell framework that nothing was generated.
288                 return -ENOBUFS;
289         }
290
291         // Loop over all input blocks in the event and add the ones that contain
292         // reconstructed hits into the hit buffers. The blocks containing trigger
293         // records are ignored for now and will be processed later.
294         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
295         {
296                 if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
297                 {
298                         specification |= blocks[n].fSpecification;
299                         
300                         AliHLTMUONRecHitsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
301                         if (not inblock.BufferSizeOk())
302                         {
303                                 size_t headerSize = sizeof(AliHLTMUONRecHitsBlockReader::HeaderType);
304                                 if (blocks[n].fSize < headerSize)
305                                 {
306                                         HLTError("Received a reconstructed hits data block with a size of %d bytes,"
307                                                 " which is smaller than the minimum valid header size of %d bytes."
308                                                 " The block must be corrupt.",
309                                                 blocks[n].fSize, headerSize
310                                         );
311                                         continue;
312                                 }
313                                 
314                                 size_t expectedWidth = sizeof(AliHLTMUONRecHitsBlockReader::ElementType);
315                                 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
316                                 {
317                                         HLTError("Received a reconstructed hits data block with a record"
318                                                 " width of %d bytes, but the expected value is %d bytes."
319                                                 " The block might be corrupt.",
320                                                 inblock.CommonBlockHeader().fRecordWidth, expectedWidth
321                                         );
322                                         continue;
323                                 }
324                                 
325                                 HLTError("Received a reconstructed hits data block with a size of %d bytes,"
326                                         " but the block header claims the block should be %d bytes."
327                                         " The block might be corrupt.",
328                                         blocks[n].fSize, inblock.BytesUsed()
329                                 );
330                                 continue;
331                         }
332                         
333                         if (inblock.Nentries() != 0)
334                                 AddRecHits(blocks[n].fSpecification, inblock.GetArray(), inblock.Nentries());
335                         else
336                         {
337                                 Logging(kHLTLogDebug,
338                                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
339                                         "Block empty",
340                                         "Received a reconstructed hits data block which contains no entries."
341                                 );
342                         }
343                 }
344                 else if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
345                 {
346                         // Log a message indicating that we got a data block that we
347                         // do not know how to handle.
348                         char id[kAliHLTComponentDataTypefIDsize+1];
349                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
350                                 id[i] = blocks[n].fDataType.fID[i];
351                         id[kAliHLTComponentDataTypefIDsize] = '\0';
352                         char origin[kAliHLTComponentDataTypefOriginSize+1];
353                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
354                                 origin[i] = blocks[n].fDataType.fOrigin[i];
355                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
356                         
357                         if (fWarnForUnexpecedBlock)
358                                 HLTWarning("Received a data block of a type we cannot handle: %s origin: %s",
359                                         static_cast<char*>(id), static_cast<char*>(origin)
360                                 );
361                         else
362                                 HLTDebug("Received a data block of a type we cannot handle: %s origin: %s",
363                                         static_cast<char*>(id), static_cast<char*>(origin)
364                                 );
365                 }
366         }
367   
368         // Again loop over all input blocks in the event, but this time look for
369         // the trigger record blocks and process these.
370         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
371         {
372                 if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
373                         continue;
374                 
375                 AliHLTMUONTriggerRecordsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
376                 if (not inblock.BufferSizeOk())
377                 {
378                         size_t headerSize = sizeof(AliHLTMUONTriggerRecordsBlockReader::HeaderType);
379                         if (blocks[n].fSize < headerSize)
380                         {
381                                 HLTError("Received a trigger records data block with a size of %d bytes,"
382                                         " which is smaller than the minimum valid header size of %d bytes."
383                                         " The block must be corrupt.",
384                                         blocks[n].fSize, headerSize
385                                 );
386                                 continue;
387                         }
388                         
389                         size_t expectedWidth = sizeof(AliHLTMUONTriggerRecordsBlockReader::ElementType);
390                         if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
391                         {
392                                 HLTError("Received a trigger records data block with a record"
393                                         " width of %d bytes, but the expected value is %d bytes."
394                                         " The block might be corrupt.",
395                                         inblock.CommonBlockHeader().fRecordWidth, expectedWidth
396                                 );
397                                 continue;
398                         }
399                         
400                         HLTError("Received a trigger records data block with a size of %d bytes,"
401                                 " but the block header claims the block should be %d bytes."
402                                 " The block might be corrupt.",
403                                 blocks[n].fSize, inblock.BytesUsed()
404                         );
405                         continue;
406                 }
407                 DebugTrace("Processing a trigger block with "
408                         << inblock.Nentries() << " entries."
409                 );
410                 
411                 specification |= blocks[n].fSpecification;
412                 
413                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
414                 {
415                         fTracker->FindTrack(inblock[i]);
416                         
417                         // Reset the tracker so that we do not double count tracks.
418                         fTracker->Reset();
419                 }
420         }
421         
422         AliHLTComponentBlockData bd;
423         FillBlockData(bd);
424         bd.fPtr = outputPtr;
425         bd.fOffset = 0;
426         bd.fSize = block.BytesUsed();
427         bd.fDataType = AliHLTMUONConstants::MansoTracksBlockDataType();
428         bd.fSpecification = specification;
429         outputBlocks.push_back(bd);
430         size = block.BytesUsed();
431
432         return 0;
433 }
434
435
436 void AliHLTMUONMansoTrackerFSMComponent::Reset()
437 {
438         ///
439         /// Reset the track count and reconstructed hit data block arrays.
440         ///
441         
442         DebugTrace("Resetting AliHLTMUONMansoTrackerFSMComponent.");
443
444         //fTracker->Reset();  // Not necessary here because it is done after every FindTrack call.
445         fTrackCount = 0;
446         fBlock = NULL;  // Do not delete. Already done implicitly at the end of DoEvent.
447         for (int i = 0; i < 4; i++)
448         {
449                 fRecHitBlockCount[i] = 0;
450         }
451 }
452
453
454 void AliHLTMUONMansoTrackerFSMComponent::AddRecHits(
455                 AliHLTUInt32_t specification,
456                 const AliHLTMUONRecHitStruct* recHits,
457                 AliHLTUInt32_t count
458         )
459 {
460         ///
461         /// Adds a new reconstructed hit data block to the internal list of blocks
462         /// for the tracker to process.
463         /// These lists will later be used when the tracker requests them through
464         /// the callback method 'RequestClusters'.
465         ///
466         
467         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::AddRecHits called with specification = 0x"
468                  << std::hex << specification << std::dec << " and count = "
469                  << count << " rec hits."
470         );
471         
472         AliHLTUInt8_t chamberMap[20] = {
473                 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10
474         };
475         
476         // Identify the chamber the rec hits came from using the specifications field.
477         bool gotDataFromDDL[22];
478         AliHLTMUONUtils::UnpackSpecBits(specification, gotDataFromDDL);
479                 
480         AliHLTInt8_t chamber = -1;
481         for (int i = 0; i < 20; i++)
482         {
483                 if (not gotDataFromDDL[i]) continue;
484                 if (7 <= chamberMap[i] and chamberMap[i] <= 10)
485                 {
486                         if (chamber != -1 and chamber != chamberMap[i])
487                         {
488                                 Logging(kHLTLogError,
489                                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
490                                         "Invalid block",
491                                         "Received a data block with data from multiple chambers."
492                                           " This component cannot handle such a case."
493                                 );
494                                 return;
495                         }
496                         else
497                                 chamber = chamberMap[i];
498                 }
499                 else
500                 {
501                         Logging(kHLTLogError,
502                                 "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
503                                 "Invalid chamber",
504                                 "Received a data block with data from chamber %d"
505                                   " which is outside the expected range: [7..10].",
506                                 chamberMap[i]
507                         );
508                         return;
509                 }
510         }
511         
512         // Make sure we got one chamber number.
513         if (chamber < 7 or 10 < chamber)
514         {
515                 Logging(kHLTLogError,
516                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
517                         "Invalid block",
518                         "Received a reconstructed hit data block with a null specification."
519                          " Cannot know which chamber the data comes from."
520                 );
521                 return;
522         }
523         
524         DebugTrace("Added " << count << " reconstructed hits from chamber "
525                 << (int)chamber << " to the internal arrays."
526         );
527         
528         assert( fRecHitBlockCount[chamber-7] < fRecHitBlockArraySize );
529         AliRecHitBlockInfo info(count, recHits);
530         fRecHitBlock[chamber-7][fRecHitBlockCount[chamber-7]] = info;
531         fRecHitBlockCount[chamber-7]++;
532 }
533
534
535 void AliHLTMUONMansoTrackerFSMComponent::RequestClusters(
536                 AliHLTMUONMansoTrackerFSM* tracker,
537                 AliHLTFloat32_t left, AliHLTFloat32_t right,
538                 AliHLTFloat32_t bottom, AliHLTFloat32_t top,
539                 AliHLTMUONChamberName chamber, const void* tag
540         )
541 {
542         ///
543         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
544         /// This is the call back method used by the tracker algorithm to request
545         /// clusters on a certain chamber.
546         ///
547
548         DebugTrace("AliHLTMUONMansoTracker::RequestClusters(chamber = " << chamber << ")");
549         void* ctag = const_cast<void*>(tag);
550         int chNo = -1;
551         AliHLTUInt32_t recHitsCount = 0;
552         AliRecHitBlockInfo* recHitsBlock = NULL;
553         switch (chamber)
554         {
555         case kChamber7:
556                 recHitsCount = fRecHitBlockCount[0];
557                 recHitsBlock = fRecHitBlock[0];
558                 chNo = 7;
559                 break;
560
561         case kChamber8:
562                 recHitsCount = fRecHitBlockCount[1];
563                 recHitsBlock = fRecHitBlock[1];
564                 chNo = 8;
565                 break;
566
567         case kChamber9:
568                 recHitsCount = fRecHitBlockCount[2];
569                 recHitsBlock = fRecHitBlock[2];
570                 chNo = 9;
571                 break;
572
573         case kChamber10:
574                 recHitsCount = fRecHitBlockCount[3];
575                 recHitsBlock = fRecHitBlock[3];
576                 chNo = 10;
577                 break;
578
579         default: return;
580         }
581         
582         DebugTrace("Returning requested hits for chamber " << chNo << ":");
583         for (AliHLTUInt32_t i = 0; i < recHitsCount; i++)
584         for (AliHLTUInt32_t j = 0; j < recHitsBlock[i].Count(); j++)
585         {
586                 const AliHLTMUONRecHitStruct* hit = &(recHitsBlock[i].Data()[j]);
587                 if (left < hit->fX and hit->fX < right and bottom < hit->fY and hit->fY < top)
588                         tracker->ReturnClusters(ctag, hit, 1);
589         }
590         DebugTrace("Done returning hits from chamber " << chNo << ".");
591         tracker->EndOfClusters(ctag);
592 }
593
594
595 void AliHLTMUONMansoTrackerFSMComponent::EndOfClusterRequests(
596                 AliHLTMUONMansoTrackerFSM* /*tracker*/
597         )
598 {
599         ///
600         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
601         /// Nothing special to do here.
602         ///
603         
604         DebugTrace("End of cluster requests.");
605 }
606
607
608 void AliHLTMUONMansoTrackerFSMComponent::FoundTrack(AliHLTMUONMansoTrackerFSM* tracker)
609 {
610         ///
611         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
612         /// This is the call back method used by the tracker algorithm to declare
613         /// that a new track has been found.
614         ///
615         
616         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::FoundTrack()");
617         
618         AliHLTMUONMansoTracksBlockWriter* block =
619                 reinterpret_cast<AliHLTMUONMansoTracksBlockWriter*>(fBlock);
620         
621         AliHLTMUONMansoTrackStruct* track = block->AddEntry();
622         if (track == NULL)
623         {
624                 Logging(kHLTLogError,
625                         "AliHLTMUONMansoTrackerFSMComponent::FoundTrack",
626                         "Buffer overflow",
627                         "We have overflowed the output buffer for Manso track data."
628                           " The output buffer size is only %d bytes.",
629                         block->BufferSize()
630                 );
631                 return;
632         }
633  
634         fTrackCount++;
635         tracker->FillTrackData(*track);
636         DebugTrace("\tTrack data = " << *track);
637 }
638
639
640 void AliHLTMUONMansoTrackerFSMComponent::NoTrackFound(AliHLTMUONMansoTrackerFSM* /*tracker*/)
641 {
642         ///
643         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
644         /// Nothing special to do here.
645         ///
646         
647         DebugTrace("No track found.");
648 }
649