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