1a75b966a23ec4cb370d4ffbcfb6d74d88d239bd
[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
38 namespace
39 {
40         // The global object used for automatic component registration.
41         // Note DO NOT use this component for calculation!
42         AliHLTMUONMansoTrackerFSMComponent gAliHLTMUONMansoTrackerFSMComponent;
43
44 } // end of namespace
45
46
47 ClassImp(AliHLTMUONMansoTrackerFSMComponent);
48
49
50 AliHLTMUONMansoTrackerFSMComponent::AliHLTMUONMansoTrackerFSMComponent() :
51         AliHLTProcessor(),
52         AliHLTMUONMansoTrackerFSMCallback(),
53         fTracker(NULL),
54         fTrackCount(0),
55         fBlock(NULL),
56         fWarnForUnexpecedBlock(false)
57 {
58 }
59
60
61 AliHLTMUONMansoTrackerFSMComponent::~AliHLTMUONMansoTrackerFSMComponent()
62 {
63         assert( fTracker == NULL );
64 }
65
66
67 const char* AliHLTMUONMansoTrackerFSMComponent::GetComponentID()
68 {
69         return AliHLTMUONConstants::MansoTrackerFSMId();
70 }
71
72
73 void AliHLTMUONMansoTrackerFSMComponent::GetInputDataTypes(
74                 vector<AliHLTComponentDataType>& list
75         )
76 {
77         assert( list.empty() );
78         list.push_back( AliHLTMUONConstants::TriggerRecordsBlockDataType() );
79         list.push_back( AliHLTMUONConstants::RecHitsBlockDataType() );
80 }
81
82
83 AliHLTComponentDataType AliHLTMUONMansoTrackerFSMComponent::GetOutputDataType()
84 {
85         return AliHLTMUONConstants::MansoTracksBlockDataType();
86 }
87
88
89 void AliHLTMUONMansoTrackerFSMComponent::GetOutputDataSize(
90                 unsigned long& constBase, double& inputMultiplier
91         )
92 {
93         constBase = sizeof(AliHLTMUONMansoTracksBlockStruct);
94         inputMultiplier = 1;
95 }
96
97
98 AliHLTComponent* AliHLTMUONMansoTrackerFSMComponent::Spawn()
99 {
100         return new AliHLTMUONMansoTrackerFSMComponent;
101 }
102
103
104 int AliHLTMUONMansoTrackerFSMComponent::DoInit(int argc, const char** argv)
105 {
106         fTracker = new AliHLTMUONMansoTrackerFSM();
107         fTracker->SetCallback(this);
108         
109         fWarnForUnexpecedBlock = false;
110         
111         for (int i = 0; i < argc; i++)
112         {
113                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
114                         fWarnForUnexpecedBlock = true;
115         }
116         
117         return 0;
118 }
119
120
121 int AliHLTMUONMansoTrackerFSMComponent::DoDeinit()
122 {
123         if (fTracker != NULL)
124         {
125                 delete fTracker;
126                 fTracker = NULL;
127         }
128         return 0;
129 }
130
131
132 int AliHLTMUONMansoTrackerFSMComponent::DoEvent(
133                 const AliHLTComponentEventData& evtData,
134                 const AliHLTComponentBlockData* blocks,
135                 AliHLTComponentTriggerData& /*trigData*/,
136                 AliHLTUInt8_t* outputPtr,
137                 AliHLTUInt32_t& size,
138                 std::vector<AliHLTComponentBlockData>& outputBlocks
139         )
140 {
141         Reset();
142         AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
143         
144         AliHLTMUONMansoTracksBlockWriter block(outputPtr, size);
145         fBlock = &block;
146         
147         if (not block.InitCommonHeader())
148         {
149                 Logging(kHLTLogError,
150                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
151                         "Buffer overflow",
152                         "The buffer is only %d bytes in size. We need a minimum of %d bytes.",
153                         size, sizeof(AliHLTMUONMansoTracksBlockWriter::HeaderType)
154                 );
155                 size = 0; // Important to tell framework that nothing was generated.
156                 return ENOBUFS;
157         }
158
159         // Loop over all input blocks in the event and add the ones that contain
160         // reconstructed hits into the hit buffers. The blocks containing trigger
161         // records are ignored for now and will be processed later.
162         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
163         {
164                 if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
165                 {
166                         specification |= blocks[n].fSpecification;
167                         
168                         AliHLTMUONRecHitsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
169                         if (not inblock.BufferSizeOk())
170                         {
171                                 size_t headerSize = sizeof(AliHLTMUONRecHitsBlockReader::HeaderType);
172                                 if (blocks[n].fSize < headerSize)
173                                 {
174                                         HLTError("Received a reconstructed hits data block with a size of %d bytes,"
175                                                 " which is smaller than the minimum valid header size of %d bytes."
176                                                 " The block must be corrupt.",
177                                                 blocks[n].fSize, headerSize
178                                         );
179                                         continue;
180                                 }
181                                 
182                                 size_t expectedWidth = sizeof(AliHLTMUONRecHitsBlockReader::ElementType);
183                                 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
184                                 {
185                                         HLTError("Received a reconstructed hits data block with a record"
186                                                 " width of %d bytes, but the expected value is %d bytes."
187                                                 " The block might be corrupt.",
188                                                 blocks[n].fSize, headerSize
189                                         );
190                                         continue;
191                                 }
192                                 
193                                 HLTError("Received a reconstructed hits data block with a size of %d bytes,"
194                                         " but the block header claims the block should be %d bytes."
195                                         " The block might be corrupt.",
196                                         blocks[n].fSize, inblock.BytesUsed()
197                                 );
198                                 continue;
199                         }
200                         
201                         if (inblock.Nentries() != 0)
202                                 AddRecHits(blocks[n].fSpecification, inblock.GetArray(), inblock.Nentries());
203                         else
204                         {
205                                 Logging(kHLTLogDebug,
206                                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
207                                         "Block empty",
208                                         "Received a reconstructed hits data block which contains no entries."
209                                 );
210                         }
211                 }
212                 else if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
213                 {
214                         // Log a message indicating that we got a data block that we
215                         // do not know how to handle.
216                         char id[kAliHLTComponentDataTypefIDsize+1];
217                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
218                                 id[i] = blocks[n].fDataType.fID[i];
219                         id[kAliHLTComponentDataTypefIDsize] = '\0';
220                         char origin[kAliHLTComponentDataTypefOriginSize+1];
221                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
222                                 origin[i] = blocks[n].fDataType.fOrigin[i];
223                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
224                         
225                         if (fWarnForUnexpecedBlock)
226                                 HLTWarning("Received a data block of a type we cannot handle: %s origin: %s",
227                                         static_cast<char*>(id), static_cast<char*>(origin)
228                                 );
229                         else
230                                 HLTDebug("Received a data block of a type we cannot handle: %s origin: %s",
231                                         static_cast<char*>(id), static_cast<char*>(origin)
232                                 );
233                 }
234         }
235   
236         // Again loop over all input blocks in the event, but this time look for
237         // the trigger record blocks and process these.
238         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
239         {
240                 if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
241                         continue;
242                 
243                 AliHLTMUONTriggerRecordsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
244                 if (not inblock.BufferSizeOk())
245                 {
246                         size_t headerSize = sizeof(AliHLTMUONTriggerRecordsBlockReader::HeaderType);
247                         if (blocks[n].fSize < headerSize)
248                         {
249                                 HLTError("Received a trigger records data block with a size of %d bytes,"
250                                         " which is smaller than the minimum valid header size of %d bytes."
251                                         " The block must be corrupt.",
252                                         blocks[n].fSize, headerSize
253                                 );
254                                 continue;
255                         }
256                         
257                         size_t expectedWidth = sizeof(AliHLTMUONTriggerRecordsBlockReader::ElementType);
258                         if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
259                         {
260                                 HLTError("Received a trigger records data block with a record"
261                                         " width of %d bytes, but the expected value is %d bytes."
262                                         " The block might be corrupt.",
263                                         blocks[n].fSize, headerSize
264                                 );
265                                 continue;
266                         }
267                         
268                         HLTError("Received a trigger records data block with a size of %d bytes,"
269                                 " but the block header claims the block should be %d bytes."
270                                 " The block might be corrupt.",
271                                 blocks[n].fSize, inblock.BytesUsed()
272                         );
273                         continue;
274                 }
275                 DebugTrace("Processing a trigger block with "
276                         << inblock.Nentries() << " entries."
277                 );
278                 
279                 specification |= blocks[n].fSpecification;
280                 
281                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
282                 {
283                         fTracker->FindTrack(inblock[i]);
284                         
285                         // Reset the tracker so that we do not double count tracks.
286                         fTracker->Reset();
287                 }
288         }
289         
290         AliHLTComponentBlockData bd;
291         FillBlockData(bd);
292         bd.fPtr = outputPtr;
293         bd.fOffset = 0;
294         bd.fSize = block.BytesUsed();
295         bd.fDataType = AliHLTMUONConstants::MansoTracksBlockDataType();
296         bd.fSpecification = specification;
297         outputBlocks.push_back(bd);
298         size = block.BytesUsed();
299
300         return 0;
301 }
302
303
304 void AliHLTMUONMansoTrackerFSMComponent::Reset()
305 {
306         DebugTrace("Resetting AliHLTMUONMansoTrackerFSMComponent.");
307
308         //fTracker->Reset();  // Not necessary here because it is done after every FindTrack call.
309         fTrackCount = 0;
310         fBlock = NULL;  // Do not delete. Already done implicitly at the end of DoEvent.
311         for (int i = 0; i < 4; i++)
312         {
313                 fRecHitBlock[i].erase(fRecHitBlock[i].begin(), fRecHitBlock[i].end());
314         }
315 }
316
317
318 void AliHLTMUONMansoTrackerFSMComponent::AddRecHits(
319                 AliHLTUInt32_t specification,   
320                 const AliHLTMUONRecHitStruct* recHits,
321                 AliHLTUInt32_t count
322         )
323 {
324         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::AddRecHits called with specification = 0x"
325                  << std::hex << specification << std::dec << " and count = "
326                  << count << " rec hits."
327         );
328         
329         AliHLTUInt8_t chamberMap[20] = {
330                 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10
331         };
332         
333         // Identify the chamber the rec hits came from using the specifications field.
334         bool gotDataFromDDL[22];
335         AliHLTMUONUtils::UnpackSpecBits(specification, gotDataFromDDL);
336                 
337         AliHLTInt8_t chamber = -1;
338         for (int i = 0; i < 20; i++)
339         {
340                 if (not gotDataFromDDL[i]) continue;
341                 if (7 <= chamberMap[i] and chamberMap[i] <= 10)
342                 {
343                         if (chamber != -1 and chamber != chamberMap[i])
344                         {
345                                 Logging(kHLTLogError,
346                                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
347                                         "Invalid block",
348                                         "Received a data block with data from multiple chambers."
349                                           " This component cannot handle such a case."
350                                 );
351                                 return;
352                         }
353                         else
354                                 chamber = chamberMap[i];
355                 }
356                 else
357                 {
358                         Logging(kHLTLogError,
359                                 "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
360                                 "Invalid chamber",
361                                 "Received a data block with data from chamber %d"
362                                   " which is outside the expected range: [7..10].",
363                                 chamberMap[i]
364                         );
365                         return;
366                 }
367         }
368         
369         // Make sure we got one chamber number.
370         if (chamber < 7 or 10 < chamber)
371         {
372                 Logging(kHLTLogError,
373                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
374                         "Invalid block",
375                         "Received a reconstructed hit data block with a null specification."
376                          " Cannot know which chamber the data comes from."
377                 );
378                 return;
379         }
380         
381         DebugTrace("Added " << count << " reconstructed hits from chamber "
382                 << (int)chamber << " to the internal arrays."
383         );
384         
385         RecHitBlockInfo info;
386         info.fCount = count;
387         info.fData = recHits;
388         fRecHitBlock[chamber-7].push_back(info);
389 }
390
391
392 void AliHLTMUONMansoTrackerFSMComponent::RequestClusters(
393                 AliHLTMUONMansoTrackerFSM* tracker,
394                 AliHLTFloat32_t left, AliHLTFloat32_t right,
395                 AliHLTFloat32_t bottom, AliHLTFloat32_t top,
396                 AliHLTMUONChamberName chamber, const void* tag
397         )
398 {
399         DebugTrace("AliHLTMUONMansoTracker::RequestClusters(chamber = " << chamber << ")");
400         void* ctag = const_cast<void*>(tag);
401         int chNo = -1;
402         std::vector<RecHitBlockInfo>* recHitsBlock = NULL;
403         switch (chamber)
404         {
405         case kChamber7:
406                 recHitsBlock = &fRecHitBlock[0];
407                 chNo = 7;
408                 break;
409
410         case kChamber8:
411                 recHitsBlock = &fRecHitBlock[1];
412                 chNo = 8;
413                 break;
414
415         case kChamber9:
416                 recHitsBlock = &fRecHitBlock[2];
417                 chNo = 9;
418                 break;
419
420         case kChamber10:
421                 recHitsBlock = &fRecHitBlock[3];
422                 chNo = 10;
423                 break;
424
425         default: return;
426         }
427         
428         DebugTrace("Returning requested hits for chamber " << chNo << ":");
429         for (AliHLTUInt32_t i = 0; i < recHitsBlock->size(); i++)
430         for (AliHLTUInt32_t j = 0; j < (*recHitsBlock)[i].fCount; j++)
431         {
432                 const AliHLTMUONRecHitStruct* hit = &((*recHitsBlock)[i].fData[j]);
433                 if (left < hit->fX and hit->fX < right and bottom < hit->fY and hit->fY < top)
434                         tracker->ReturnClusters(ctag, hit, 1);
435         }
436         DebugTrace("Done returning hits from chamber " << chNo << ".");
437         tracker->EndOfClusters(ctag);
438 }
439
440
441 void AliHLTMUONMansoTrackerFSMComponent::EndOfClusterRequests(
442                 AliHLTMUONMansoTrackerFSM* /*tracker*/
443         )
444 {
445         DebugTrace("End of cluster requests.");
446 }
447
448
449 void AliHLTMUONMansoTrackerFSMComponent::FoundTrack(AliHLTMUONMansoTrackerFSM* tracker)
450 {
451         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::FoundTrack()");
452         
453         AliHLTMUONMansoTracksBlockWriter* block =
454                 reinterpret_cast<AliHLTMUONMansoTracksBlockWriter*>(fBlock);
455         
456         AliHLTMUONMansoTrackStruct* track = block->AddEntry();
457         if (track == NULL)
458         {
459                 Logging(kHLTLogError,
460                         "AliHLTMUONMansoTrackerFSMComponent::FoundTrack",
461                         "Buffer overflow",
462                         "We have overflowed the output buffer for Manso track data."
463                           " The output buffer size is only %d bytes.",
464                         block->BufferSize()
465                 );
466                 return;
467         }
468  
469         fTrackCount++;
470         tracker->FillTrackData(*track);
471         DebugTrace("\tTrack data = " << *track);
472 }
473
474
475 void AliHLTMUONMansoTrackerFSMComponent::NoTrackFound(AliHLTMUONMansoTrackerFSM* /*tracker*/)
476 {
477         DebugTrace("No track found.");
478 }