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