c718ac12f1770458f06774800b68bf224bf3f21e
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONTriggerReconstructorComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Indranil Das <indra.das@saha.ac.in>                                  *
7  *   Artur Szostak <artursz@iafrica.com>                                  *
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   AliHLTMUONTriggerReconstructorComponent.cxx
22  * @author Indranil Das <indra.das@saha.ac.in>, Artur Szostak <artursz@iafrica.com>
23  * @date
24  * @brief  Implementation of the trigger DDL reconstructor component.
25  */
26
27 #include "AliHLTMUONTriggerReconstructorComponent.h"
28 #include "AliHLTMUONTriggerReconstructor.h"
29 #include "AliHLTMUONHitReconstructor.h"
30 #include "AliHLTMUONConstants.h"
31 #include "AliHLTMUONUtils.h"
32 #include "AliHLTMUONDataBlockWriter.h"
33 #include <cstdlib>
34 #include <cerrno>
35 #include <cassert>
36 #include <fstream>
37
38 namespace
39 {
40         // This is a global object used for automatic component registration,
41         // do not use this for calculation.
42         AliHLTMUONTriggerReconstructorComponent gAliHLTMUONTriggerReconstructorComponent;
43
44 } // end of namespace
45
46
47 ClassImp(AliHLTMUONTriggerReconstructorComponent)
48
49
50 AliHLTMUONTriggerReconstructorComponent::AliHLTMUONTriggerReconstructorComponent() :
51         fTrigRec(NULL),
52         fDDL(-1),
53         fWarnForUnexpecedBlock(false),
54         fSuppressPartialTrigs(false)
55 {
56 }
57
58
59 AliHLTMUONTriggerReconstructorComponent::~AliHLTMUONTriggerReconstructorComponent()
60 {
61 }
62
63
64 const char* AliHLTMUONTriggerReconstructorComponent::GetComponentID()
65 {
66         return AliHLTMUONConstants::TriggerReconstructorId();
67 }
68
69
70 void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
71 {
72         list.clear();
73         list.push_back( AliHLTMUONConstants::TriggerDDLRawDataType() );
74 }
75
76
77 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
78 {
79         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
80 }
81
82
83 void AliHLTMUONTriggerReconstructorComponent::GetOutputDataSize(
84                 unsigned long& constBase, double& inputMultiplier
85         )
86 {
87         constBase = sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType);
88         inputMultiplier = 4;
89 }
90
91
92 AliHLTComponent* AliHLTMUONTriggerReconstructorComponent::Spawn()
93 {
94         return new AliHLTMUONTriggerReconstructorComponent;
95 }
96
97
98 int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
99 {
100         // perform initialization.
101         
102         HLTInfo("Initialising dHLT trigger reconstructor component.");
103         
104         fWarnForUnexpecedBlock = false;
105         fSuppressPartialTrigs = false;
106         assert(fTrigRec == NULL);
107         fTrigRec = new AliHLTMUONTriggerReconstructor();
108         
109         const char* lutFileName = NULL;
110         
111         for (int i = 0; i < argc; i++)
112         {
113                 if ( !strcmp( argv[i], "-lut" ) )
114                 {
115                         if ( argc <= i+1 )
116                         {
117                                 HLTError("LookupTable filename not specified." );
118                                 return EINVAL; /* Invalid argument */ 
119                         }
120                         
121                         lutFileName = argv[i+1];
122                         
123                         i++;
124                         continue;
125                 }
126                 
127                 if ( !strcmp( argv[i], "-ddl" ) )
128                 {
129                         if ( argc <= i+1 )
130                         {
131                                 HLTError("DDL number not specified." );
132                                 return EINVAL;  /* Invalid argument */
133                         }
134                 
135                         char* cpErr = NULL;
136                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
137                         if (cpErr == NULL or *cpErr != '\0')
138                         {
139                                 HLTError("Cannot convert '%s' to a DDL Number.", argv[i+1] );
140                                 return EINVAL;
141                         }
142                         if (num < 21 or 22 < num)
143                         {
144                                 HLTError("The DDL number must be in the range [21..22].");
145                                 return EINVAL;
146                         }
147                         fDDL = num - 1; // Convert to DDL number in the range 0..21
148                         
149                         i++;
150                         continue;
151                 }
152                         
153                 if (not strcmp( argv[i], "-warn_on_unexpected_block" ))
154                 {
155                         fWarnForUnexpecedBlock = true;
156                         continue;
157                 }
158                         
159                 if (not strcmp( argv[i], "-suppress_partial_triggers" ))
160                 {
161                         fSuppressPartialTrigs = true;
162                         continue;
163                 }
164                 
165                 HLTError("Unknown option '%s'.", argv[i] );
166                 return EINVAL;
167                         
168         }//while loop
169         
170         if (fDDL == -1)
171         {
172                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
173         }
174         
175         if (lutFileName != NULL)
176         {
177                 if (not ReadLookUpTable(lutFileName))
178                 {
179                         HLTError("Failed to read lut, lut cannot be read");
180                         return ENOENT ; /* No such file or directory */
181                 }
182         }
183         else
184         {
185                 HLTWarning("The lookup table has not been specified. Output results will be invalid.");
186         }
187         
188         return 0;
189 }
190
191
192 int AliHLTMUONTriggerReconstructorComponent::DoDeinit()
193 {
194         HLTInfo("Deinitialising dHLT trigger reconstructor component.");
195
196         if (fTrigRec != NULL)
197         {
198                 delete fTrigRec;
199                 fTrigRec = NULL;
200         }
201         return 0;
202 }
203
204
205 int AliHLTMUONTriggerReconstructorComponent::DoEvent(
206                 const AliHLTComponentEventData& evtData,
207                 const AliHLTComponentBlockData* blocks,
208                 AliHLTComponentTriggerData& /*trigData*/,
209                 AliHLTUInt8_t* outputPtr,
210                 AliHLTUInt32_t& size,
211                 std::vector<AliHLTComponentBlockData>& outputBlocks
212         )
213 {
214         // Process an event
215         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
216
217         HLTDebug("Processing event %llu with %u input data blocks.",
218                 evtData.fEventID, evtData.fBlockCnt
219         );
220         
221         // Loop over all input blocks in the event and run the trigger DDL
222         // reconstruction algorithm on the raw data.
223         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
224         {
225 #ifdef __DEBUG
226                 char id[kAliHLTComponentDataTypefIDsize+1];
227                 for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
228                         id[i] = blocks[n].fDataType.fID[i];
229                 id[kAliHLTComponentDataTypefIDsize] = '\0';
230                 char origin[kAliHLTComponentDataTypefOriginSize+1];
231                 for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
232                         origin[i] = blocks[n].fDataType.fOrigin[i];
233                 origin[kAliHLTComponentDataTypefOriginSize] = '\0';
234 #endif // __DEBUG
235                 HLTDebug("Handling block: %u, with fDataType.fID = '%s',"
236                           " fDataType.fID = '%s', fPtr = %p and fSize = %u bytes.",
237                         n, static_cast<char*>(id), static_cast<char*>(origin),
238                         blocks[n].fPtr, blocks[n].fSize
239                 );
240
241                 if (blocks[n].fDataType != AliHLTMUONConstants::TriggerDDLRawDataType())
242                 {
243                         // Log a message indicating that we got a data block that we
244                         // do not know how to handle.
245                         char id[kAliHLTComponentDataTypefIDsize+1];
246                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
247                                 id[i] = blocks[n].fDataType.fID[i];
248                         id[kAliHLTComponentDataTypefIDsize] = '\0';
249                         char origin[kAliHLTComponentDataTypefOriginSize+1];
250                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
251                                 origin[i] = blocks[n].fDataType.fOrigin[i];
252                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
253                         
254                         if (fWarnForUnexpecedBlock)
255                                 HLTWarning("Received a data block of a type we can not handle: %s origin %s",
256                                         static_cast<char*>(id), static_cast<char*>(origin)
257                                 );
258                         else
259                                 HLTDebug("Received a data block of a type we can not handle: %s origin %s",
260                                         static_cast<char*>(id), static_cast<char*>(origin)
261                                 );
262                         
263                         continue;
264                 }
265                 
266                 bool ddl[22];
267                 AliHLTMUONUtils::UnpackSpecBits(blocks[n].fSpecification, ddl);
268                 if (not ddl[fDDL])
269                 {
270                         HLTWarning("Received trigger DDL raw data from a DDL which we did not expect.");
271                 }
272                 
273                 // Create a new output data block and initialise the header.
274                 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr+totalSize, size-totalSize);
275                 if (not block.InitCommonHeader())
276                 {
277                         HLTError("There is not enough space in the output buffer for the new data block.",
278                                  " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
279                                 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
280                                 block.BufferSize()
281                         );
282                         break;
283                 }
284
285                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize / sizeof(AliHLTUInt32_t);
286                 AliHLTUInt32_t ddlRawDataSize = totalDDLSize - 8;
287                 AliHLTUInt32_t* buffer = reinterpret_cast<AliHLTUInt32_t*>(blocks[n].fPtr) + 8;
288                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
289
290                 bool runOk = fTrigRec->Run(
291                                 buffer, ddlRawDataSize,
292                                 block.GetArray(), nofTrigRec,
293                                 fSuppressPartialTrigs
294                         );
295                 if (not runOk)
296                 {
297                         HLTError("Error while processing of trigger DDL reconstruction algorithm.");
298                         size = totalSize; // Must tell the framework how much buffer space was used.
299                         return EIO;
300                 }
301                 
302                 // nofTrigRec should now contain the number of triggers actually found
303                 // and filled into the output data block, so we can set this number.
304                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
305                 block.SetNumberOfEntries(nofTrigRec);
306                 
307                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
308                 
309                 // Fill a block data structure for our output block.
310                 AliHLTComponentBlockData bd;
311                 FillBlockData(bd);
312                 bd.fPtr = outputPtr;
313                 // This block's start (offset) is after all other blocks written so far.
314                 bd.fOffset = totalSize;
315                 bd.fSize = block.BytesUsed();
316                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
317                 bd.fSpecification = blocks[n].fSpecification;
318                 outputBlocks.push_back(bd);
319                 
320                 HLTDebug("Created a new output data block at fPtr = %p,"
321                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
322                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
323                 );
324                 
325                 // Increase the total amount of data written so far to our output memory.
326                 totalSize += block.BytesUsed();
327         }
328         
329         // Finally we set the total size of output memory we consumed.
330         size = totalSize;
331         return 0;
332 }
333
334
335 bool AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
336 {
337         assert(fTrigRec != NULL);
338
339         fstream file;
340         file.open(lutpath, fstream::binary | fstream::in);
341         if (not file)
342         {
343                 HLTError("Could not open file: %s", lutpath);
344                 return false;
345         }
346         
347         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
348         if (file.eof())
349         {
350                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
351                 file.close();
352                 return false;
353         }
354         if (file.bad())
355         {
356                 HLTError("Could not read from file: %s", lutpath);
357                 file.close();
358                 return false;
359         }
360         
361         file.close();
362         return true;
363 }