]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.cxx
Fixing problem with duplicated structure IDs per event.
[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   18 Sep 2007
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 "AliRawDataHeader.h"
34 #include "AliCDBManager.h"
35 #include "AliCDBStorage.h"
36 #include "AliGeomManager.h"
37 #include "AliMUONGeometryTransformer.h"
38 #include "AliMUONGeometryDetElement.h"
39 #include "AliMpCDB.h"
40 #include "AliMpDDLStore.h"
41 #include "AliMpPad.h"
42 #include "AliMpSegmentation.h"
43 #include "AliMpDEIterator.h"
44 #include "AliMpVSegmentation.h"
45 #include "AliMpDEManager.h"
46 #include "AliMpLocalBoard.h"
47 #include "AliMpTriggerCrate.h"
48 #include <cstdlib>
49 #include <cerrno>
50 #include <cassert>
51 #include <fstream>
52
53
54 ClassImp(AliHLTMUONTriggerReconstructorComponent)
55
56
57 AliHLTMUONTriggerReconstructorComponent::AliHLTMUONTriggerReconstructorComponent() :
58         AliHLTMUONProcessor(),
59         fTrigRec(NULL),
60         fDDL(-1),
61         fWarnForUnexpecedBlock(false),
62         fSuppressPartialTrigs(false)
63 {
64         ///
65         /// Default constructor.
66         ///
67 }
68
69
70 AliHLTMUONTriggerReconstructorComponent::~AliHLTMUONTriggerReconstructorComponent()
71 {
72         ///
73         /// Default destructor.
74         ///
75         
76         if (fTrigRec != NULL) delete fTrigRec;
77 }
78
79
80 const char* AliHLTMUONTriggerReconstructorComponent::GetComponentID()
81 {
82         ///
83         /// Inherited from AliHLTComponent. Returns the component ID.
84         ///
85         
86         return AliHLTMUONConstants::TriggerReconstructorId();
87 }
88
89
90 void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
91 {
92         ///
93         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
94         ///
95         
96         list.clear();
97         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
98 }
99
100
101 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
102 {
103         ///
104         /// Inherited from AliHLTComponent. Returns the output data type.
105         ///
106         
107         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
108 }
109
110
111 void AliHLTMUONTriggerReconstructorComponent::GetOutputDataSize(
112                 unsigned long& constBase, double& inputMultiplier
113         )
114 {
115         ///
116         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
117         ///
118         
119         constBase = sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType);
120         inputMultiplier = 4;
121 }
122
123
124 AliHLTComponent* AliHLTMUONTriggerReconstructorComponent::Spawn()
125 {
126         ///
127         /// Inherited from AliHLTComponent. Creates a new object instance.
128         ///
129         
130         return new AliHLTMUONTriggerReconstructorComponent;
131 }
132
133
134 int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
135 {
136         ///
137         /// Inherited from AliHLTComponent.
138         /// Parses the command line parameters and initialises the component.
139         ///
140         
141         // perform initialization.
142         
143         HLTInfo("Initialising dHLT trigger reconstructor component.");
144         
145         // Make sure to cleanup fTrigRec if it is still there for some reason.
146         if (fTrigRec != NULL)
147         {
148                 delete fTrigRec;
149                 fTrigRec = NULL;
150         }
151         
152         try
153         {
154                 fTrigRec = new AliHLTMUONTriggerReconstructor();
155         }
156         catch (const std::bad_alloc&)
157         {
158                 HLTError("Could not allocate more memory for the trigger reconstructor component.");
159                 return -ENOMEM;
160         }
161         
162         fDDL = -1;
163         fWarnForUnexpecedBlock = false;
164         fSuppressPartialTrigs = false;
165         
166         const char* lutFileName = NULL;
167         const char* cdbPath = NULL;
168         Int_t run = -1;
169         bool useCDB = false;
170         bool tryRecover = false;
171         
172         for (int i = 0; i < argc; i++)
173         {
174                 if (strcmp( argv[i], "-lut" ) == 0)
175                 {
176                         if ( argc <= i+1 )
177                         {
178                                 HLTError("LookupTable filename not specified." );
179                                 // Make sure to delete fTrigRec to avoid partial initialisation.
180                                 delete fTrigRec;
181                                 fTrigRec = NULL;
182                                 return -EINVAL;
183                         }
184                         
185                         lutFileName = argv[i+1];
186                         
187                         i++;
188                         continue;
189                 }
190                 
191                 if (strcmp( argv[i], "-ddl" ) == 0)
192                 {
193                         if ( argc <= i+1 )
194                         {
195                                 HLTError("DDL number not specified. It must be in the range [21..22]" );
196                                 // Make sure to delete fTrigRec to avoid partial initialisation.
197                                 delete fTrigRec;
198                                 fTrigRec = NULL;
199                                 return -EINVAL;
200                         }
201                 
202                         char* cpErr = NULL;
203                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
204                         if (cpErr == NULL or *cpErr != '\0')
205                         {
206                                 HLTError("Cannot convert '%s' to a DDL Number.", argv[i+1]);
207                                 // Make sure to delete fTrigRec to avoid partial initialisation.
208                                 delete fTrigRec;
209                                 fTrigRec = NULL;
210                                 return -EINVAL;
211                         }
212                         if (num < 21 or 22 < num)
213                         {
214                                 HLTError("The DDL ID number must be in the range [21..22].");
215                                 // Make sure to delete fTrigRec to avoid partial initialisation.
216                                 delete fTrigRec;
217                                 fTrigRec = NULL;
218                                 return -EINVAL;
219                         }
220                         fDDL = num - 1; // Convert to DDL number in the range 0..21
221                         
222                         i++;
223                         continue;
224                 }
225                 
226                 if (strcmp( argv[i], "-cdb" ) == 0)
227                 {
228                         useCDB = true;
229                         continue;
230                 }
231                 
232                 if (strcmp( argv[i], "-cdbpath" ) == 0)
233                 {
234                         if ( argc <= i+1 )
235                         {
236                                 HLTError("The CDB path was not specified." );
237                                 // Make sure to delete fTrigRec to avoid partial initialisation.
238                                 delete fTrigRec;
239                                 fTrigRec = NULL;
240                                 return -EINVAL;
241                         }
242                         cdbPath = argv[i+1];
243                         useCDB = true;
244                         i++;
245                         continue;
246                 }
247         
248                 if (strcmp( argv[i], "-run" ) == 0)
249                 {
250                         if ( argc <= i+1 )
251                         {
252                                 HLTError("The RUN number was not specified." );
253                                 // Make sure to delete fTrigRec to avoid partial initialisation.
254                                 delete fTrigRec;
255                                 fTrigRec = NULL;
256                                 return -EINVAL;
257                         }
258                         
259                         char* cpErr = NULL;
260                         run = Int_t( strtoul(argv[i+1], &cpErr, 0) );
261                         if (cpErr == NULL or *cpErr != '\0')
262                         {
263                                 HLTError("Cannot convert '%s' to a valid run number."
264                                         " Expected an integer value.", argv[i+1]
265                                 );
266                                 // Make sure to delete fTrigRec to avoid partial initialisation.
267                                 delete fTrigRec;
268                                 fTrigRec = NULL;
269                                 return -EINVAL;
270                         }
271                         
272                         i++;
273                         continue;
274                 }
275                 
276                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
277                 {
278                         fWarnForUnexpecedBlock = true;
279                         continue;
280                 }
281                 
282                 if (strcmp( argv[i], "-suppress_partial_triggers" ) == 0)
283                 {
284                         fSuppressPartialTrigs = true;
285                         continue;
286                 }
287                 
288                 if (strcmp( argv[i], "-tryrecover" ) == 0)
289                 {
290                         tryRecover = true;
291                         continue;
292                 }
293                 
294                 HLTError("Unknown option '%s'.", argv[i] );
295                 // Make sure to delete fTrigRec to avoid partial initialisation.
296                 delete fTrigRec;
297                 fTrigRec = NULL;
298                 return -EINVAL;
299                 
300         } // for loop
301         
302         if (lutFileName == NULL) useCDB = true;
303         
304         if (fDDL == -1)
305         {
306                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
307         }
308         
309         int result = 0;
310         if (useCDB)
311         {
312                 HLTInfo("Loading lookup table information from CDB for DDL %d.", fDDL+1);
313                 if (fDDL == -1)
314                         HLTWarning("DDL number not specified. The lookup table loaded from CDB will be empty!");
315                 result = ReadCDB(cdbPath, run);
316         }
317         else
318         {
319                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
320                 result = ReadLookUpTable(lutFileName);
321         }
322         if (result != 0)
323         {
324                 // Error messages already generated in ReadCDB or ReadLookUpTable.
325                 
326                 // Make sure to delete fTrigRec to avoid partial initialisation.
327                 delete fTrigRec;
328                 fTrigRec = NULL;
329                 return result;
330         }
331         
332         fTrigRec->TryRecover(tryRecover);
333         
334         return 0;
335 }
336
337
338 int AliHLTMUONTriggerReconstructorComponent::DoDeinit()
339 {
340         ///
341         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
342         ///
343         
344         HLTInfo("Deinitialising dHLT trigger reconstructor component.");
345
346         if (fTrigRec != NULL)
347         {
348                 delete fTrigRec;
349                 fTrigRec = NULL;
350         }
351         return 0;
352 }
353
354
355 int AliHLTMUONTriggerReconstructorComponent::DoEvent(
356                 const AliHLTComponentEventData& evtData,
357                 const AliHLTComponentBlockData* blocks,
358                 AliHLTComponentTriggerData& /*trigData*/,
359                 AliHLTUInt8_t* outputPtr,
360                 AliHLTUInt32_t& size,
361                 std::vector<AliHLTComponentBlockData>& outputBlocks
362         )
363 {
364         ///
365         /// Inherited from AliHLTProcessor. Processes the new event data.
366         ///
367         
368         // Process an event
369         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
370
371         HLTDebug("Processing event %llu with %u input data blocks.",
372                 evtData.fEventID, evtData.fBlockCnt
373         );
374         
375         // Loop over all input blocks in the event and run the trigger DDL
376         // reconstruction algorithm on the raw data.
377         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
378         {
379                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
380                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
381                 );
382
383                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
384                     or not AliHLTMUONUtils::IsTriggerDDL(blocks[n].fSpecification)
385                    )
386                 {
387                         // Log a message indicating that we got a data block that we
388                         // do not know how to handle.
389                         if (fWarnForUnexpecedBlock)
390                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
391                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
392                                 );
393                         else
394                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
395                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
396                                 );
397                         
398                         continue;
399                 }
400                 
401                 AliHLTInt32_t receivedDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
402                 if (fDDL != -1)
403                 {
404                         if (receivedDDL != fDDL)
405                         {
406                                 HLTWarning("Received raw data from an unexpected DDL.");
407                         }
408                 }
409                 
410                 // Create a new output data block and initialise the header.
411                 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr+totalSize, size-totalSize);
412                 if (not block.InitCommonHeader())
413                 {
414                         HLTError("There is not enough space in the output buffer for the new data block."
415                                  " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
416                                 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
417                                 block.BufferSize()
418                         );
419                         break;
420                 }
421
422                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize;
423                 if (totalDDLSize < sizeof(AliRawDataHeader))
424                 {
425                         HLTError("Raw data block %d is %d bytes in size and is too short to"
426                                  " possibly contain valid DDL raw data. We expect it to have"
427                                  " at least %d bytes for the commond data header.",
428                                 n, totalDDLSize, sizeof(AliRawDataHeader)
429                         );
430                         continue;
431                 }
432                 AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(blocks[n].fPtr);
433                 AliHLTUInt32_t payloadSize = totalDDLSize - sizeof(AliRawDataHeader);
434                 AliHLTUInt8_t* buffer = reinterpret_cast<AliHLTUInt8_t*>(header + 1);
435                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
436                 
437                 // Decode if this is a scalar event or not.
438                 bool scalarEvent = ((header->GetL1TriggerMessage() & 0x1) == 0x1);
439                 
440                 // Remember: the following does NOT change the mapping!
441                 // It is just to generate unique trigger record IDs.
442                 fTrigRec->SetDDL(receivedDDL);
443                 
444                 bool runOk = fTrigRec->Run(
445                                 buffer, payloadSize, scalarEvent,
446                                 block.GetArray(), nofTrigRec,
447                                 fSuppressPartialTrigs
448                         );
449                 if (not runOk)
450                 {
451                         HLTError("Error while processing the trigger DDL reconstruction algorithm.");
452                         size = totalSize; // Must tell the framework how much buffer space was used.
453                         return -EIO;
454                 }
455                 
456                 // nofTrigRec should now contain the number of triggers actually found
457                 // and filled into the output data block, so we can set this number.
458                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
459                 block.SetNumberOfEntries(nofTrigRec);
460                 
461                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
462                 
463                 // Fill a block data structure for our output block.
464                 AliHLTComponentBlockData bd;
465                 FillBlockData(bd);
466                 bd.fPtr = outputPtr;
467                 // This block's start (offset) is after all other blocks written so far.
468                 bd.fOffset = totalSize;
469                 bd.fSize = block.BytesUsed();
470                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
471                 bd.fSpecification = blocks[n].fSpecification;
472                 outputBlocks.push_back(bd);
473                 
474                 HLTDebug("Created a new output data block at fPtr = %p,"
475                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
476                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
477                 );
478                 
479                 // Increase the total amount of data written so far to our output memory.
480                 totalSize += block.BytesUsed();
481         }
482         
483         // Finally we set the total size of output memory we consumed.
484         size = totalSize;
485         return 0;
486 }
487
488
489 int AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
490 {
491         ///
492         /// Read in the lookup table from file.
493         ///
494         
495         assert(fTrigRec != NULL);
496
497         fstream file;
498         file.open(lutpath, fstream::binary | fstream::in);
499         if (not file)
500         {
501                 HLTError("Could not open file: %s", lutpath);
502                 return -ENOENT;
503         }
504         
505         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
506         if (file.eof())
507         {
508                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
509                 file.close();
510                 return -EIO;
511         }
512         if (file.fail())
513         {
514                 HLTError("Could not read from file: %s", lutpath);
515                 file.close();
516                 return -EIO;
517         }
518         
519         file.close();
520         return 0;
521 }
522
523
524 int AliHLTMUONTriggerReconstructorComponent::ReadCDB(const char* cdbPath, Int_t run)
525 {
526         /// Loads the lookup table containing channel and geometrical position
527         /// information about trigger strips from CDB.
528         /// \param cdbPath  This specifies the CDB path to use to load from.
529         ///                 Can be set to NULL meaning the default storage is used.
530         /// \param run  Specifies the run number to use. If set to -1 then the
531         ///             default / current run number set for the CDB is used.
532         /// \return 0 on success and non zero codes for errors.
533
534         if (fDDL == -1)
535         {
536                 HLTError("No DDL number specified for which to load LUT data from CDB.");
537                 return -EINVAL;
538         }
539
540         int result = FetchMappingStores(cdbPath, run);
541         // Error message already generated in FetchMappingStores.
542         if (result != 0) return result;
543         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
544         
545         AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
546         if (segmentation == NULL)
547         {
548                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
549                 return -EIO;
550         }
551         
552         // Only load geometry if not already loaded.
553         if (AliGeomManager::GetGeometry() == NULL)
554         {
555                 AliGeomManager::LoadGeometry();
556         }
557         AliMUONGeometryTransformer transformer;
558         if (not transformer.LoadGeometryData())
559         {
560                 HLTError("Could not load geometry into transformer.");
561                 return -ENOENT;
562         }
563         
564         AliHLTMUONTriggerRecoLookupTable* lookupTable = fTrigRec->LookupTableBuffer();
565         
566         for (Int_t i = 0; i < 8; i++)
567         for (Int_t j = 0; j < 16; j++)
568         for (Int_t k = 0; k < 4; k++)
569         for (Int_t n = 0; n < 2; n++)
570         for (Int_t m = 0; m < 16; m++)
571         {
572                 lookupTable->fRow[i][j][k][n][m].fIdFlags = 0x0;
573                 lookupTable->fRow[i][j][k][n][m].fX = 0;
574                 lookupTable->fRow[i][j][k][n][m].fY = 0;
575                 lookupTable->fRow[i][j][k][n][m].fZ = 0;
576         }
577         
578         AliMpDEIterator detElemIter;
579         for (Int_t iReg = 0; iReg < 8; iReg++)
580         {
581                 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(fDDL, iReg);
582                 if (crate == NULL)
583                 {
584                         cerr << "ERROR: Could not get crate for regional header = " << iReg
585                                 << ", and DDL ID = " << fDDL << endl;
586                         continue;
587                 }
588                 
589                 for (Int_t iLocBoard = 0; iLocBoard < 16; iLocBoard++)
590                 {
591                         Int_t boardId = crate->GetLocalBoardId(iLocBoard);
592                         if (boardId == 0) continue;
593                         
594                         AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(boardId);
595                         if (localBoard == NULL)
596                         {
597                                 cerr << "ERROR: Could not get loacl board: " << boardId << endl;
598                                 continue;
599                         }
600
601                         // skip copy cards
602                         if (! localBoard->IsNotified()) continue;
603                 
604                         for (Int_t iChamber = 0; iChamber < 4; iChamber++)
605                         {
606                                 Int_t detElemId = ddlStore->GetDEfromLocalBoard(boardId, iChamber);
607                                 
608                                 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(iChamber+10, detElemId);
609                                 
610                                 const AliMUONGeometryDetElement* detElemTransform = transformer.GetDetElement(detElemId);
611                                 if (detElemTransform == NULL)
612                                 {
613                                         cerr << "ERROR: Got NULL pointer for geometry transformer for detection element ID = "
614                                                 << detElemId << endl;
615                                         continue;
616                                 }
617                                 
618                                 for (Int_t iCathode = 0; iCathode <= 1; iCathode++)
619                                 {
620                                         const AliMpVSegmentation* seg = segmentation->GetMpSegmentation(
621                                                         detElemId, AliMp::GetCathodType(iCathode)
622                                                 );
623                                         
624                                         for (Int_t bitxy = 0; bitxy < 16; bitxy++)
625                                         {
626                                                 Int_t offset = 0;
627                                                 if (iCathode && localBoard->GetSwitch(6)) offset = -8;
628                                                 
629                                                 AliMpPad pad = seg->PadByLocation(AliMpIntPair(boardId, bitxy+offset), kFALSE);
630                                         
631                                                 if (! pad.IsValid())
632                                                 {
633                                                         // There is no pad associated with the given local board and bit pattern.
634                                                         continue;
635                                                 }
636                                                 
637                                                 // Get the global coodinates of the pad.
638                                                 Float_t lx = pad.Position().X();
639                                                 Float_t ly = pad.Position().Y();
640                                                 Float_t gx, gy, gz;
641                                                 detElemTransform->Local2Global(lx, ly, 0, gx, gy, gz);
642                                                 
643                                                 // Fill the LUT
644                                                 lookupTable->fRow[iReg][iLocBoard][iChamber][iCathode][bitxy].fIdFlags = idflags;
645                                                 lookupTable->fRow[iReg][iLocBoard][iChamber][iCathode][bitxy].fX = gx;
646                                                 lookupTable->fRow[iReg][iLocBoard][iChamber][iCathode][bitxy].fY = gy;
647                                                 lookupTable->fRow[iReg][iLocBoard][iChamber][iCathode][bitxy].fZ = gz;
648                                         }
649                                 }
650                         }
651                 }
652         }
653         
654         return 0;
655 }
656
657
658 bool AliHLTMUONTriggerReconstructorComponent::GenerateLookupTable(
659                 AliHLTInt32_t ddl, const char* filename,
660                 const char* cdbPath, Int_t run
661         )
662 {
663         /// Generates a binary file containing the lookup table (LUT) from the
664         /// CDB, which can be used for the trigger reconstructor component later.
665         /// @param ddl  Must be the DDL for which to generate the DDL,
666         ///             in the range [20..21].
667         /// @param filename  The name of the LUT file to generate.
668         /// @param cdbPath  The CDB path to use.
669         /// @param run  The run number to use for the CDB.
670         /// @return  True if the generation of the LUT file succeeded.
671         
672         AliHLTMUONTriggerReconstructorComponent comp;
673         
674         if (ddl < 20 or 21 < ddl)
675         {
676                 std::cerr << "ERROR: the DDL number must be in the range [20..21]." << std::endl;
677                 return false;
678         }
679         
680         char ddlNum[32];
681         char runNum[32];
682         sprintf(ddlNum, "%d", ddl+1);
683         sprintf(runNum, "%d", run);
684         const char* argv[7] = {"-ddl", ddlNum, "-cdbpath", cdbPath, "-run", runNum, NULL};
685         int result = comp.DoInit(6, argv);
686         if (result != 0)
687         {
688                 // Error message already generated in DoInit.
689                 return false;
690         }
691         
692         std::fstream file(filename, std::ios::out);
693         if (not file)
694         {
695                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
696                 return false;
697         }
698         
699         file.write(
700                         reinterpret_cast<char*>(comp.fTrigRec->LookupTableBuffer()),
701                         comp.fTrigRec->LookupTableSize()
702                 );
703         if (not file)
704         {
705                 cerr << "ERROR: There was a problem writing to the file: " << filename << endl;
706                 return false;
707         }
708         file.close();
709         
710         comp.DoDeinit();
711         
712         return true;
713 }