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