Cleaning up generation and reading back of lookup tables. Also moved core generation...
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONHitReconstructorComponent.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  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          * 
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19 ///
20 ///
21 ///  The HitRec Component is designed to deal the rawdata inputfiles to findout the 
22 ///  the reconstructed hits. The output is send to the output block for further 
23 ///  processing.
24 ///
25 ///  Author : Indranil Das ( indra.das@saha.ac.in || indra.ehep@gmail.com )
26 ///
27
28 #include "AliHLTMUONRecHitsBlockStruct.h"
29 #include "AliHLTMUONHitReconstructorComponent.h"
30 #include "AliHLTMUONHitReconstructor.h"
31 #include "AliHLTMUONConstants.h"
32 #include "AliHLTMUONUtils.h"
33 #include "AliHLTMUONDataBlockWriter.h"
34 #include "AliHLTMUONHitReconstructor.h"
35 #include "AliHLTLogging.h"
36 #include "AliHLTSystem.h"
37 #include "AliHLTDefinitions.h"
38 #include <cstdlib>
39 #include <cerrno>
40 #include <cassert>
41 #include <fstream>
42
43 //STEER 
44 #include "AliCDBManager.h"
45 #include "AliCDBStorage.h"
46 #include "AliGeomManager.h"
47
48 //MUON
49 #include "AliMUONGeometryTransformer.h"
50 #include "AliMUONCalibrationData.h"
51 #include "AliMUONVCalibParam.h"
52
53 //MUON/mapping
54 #include "AliMpCDB.h"
55 #include "AliMpPad.h"
56 #include "AliMpSegmentation.h"
57 #include "AliMpDDLStore.h"
58 #include "AliMpDEIterator.h"
59 #include "AliMpVSegmentation.h"
60 #include "AliMpDEManager.h"
61 #include "AliMpDetElement.h"
62
63 ClassImp(AliHLTMUONHitReconstructorComponent)
64
65
66 AliHLTMUONHitReconstructorComponent::AliHLTMUONHitReconstructorComponent() :
67         AliHLTProcessor(),
68         fHitRec(NULL),
69         fDDL(-1),
70         fLutSize(0),
71         fLut(NULL),
72         fIdToEntry(),
73         fWarnForUnexpecedBlock(false)
74 {
75         ///
76         /// Default constructor.
77         ///
78 }
79
80
81 AliHLTMUONHitReconstructorComponent::~AliHLTMUONHitReconstructorComponent()
82 {
83         ///
84         /// Default destructor.
85         ///
86         
87         if (fHitRec != NULL)
88         {
89                 delete fHitRec;
90         }
91         if (fLut != NULL)
92         {
93                 delete fLut;
94         }
95 }
96
97 const char* AliHLTMUONHitReconstructorComponent::GetComponentID()
98 {
99         ///
100         /// Inherited from AliHLTComponent. Returns the component ID.
101         ///
102         
103         return AliHLTMUONConstants::HitReconstructorId();
104 }
105
106
107 void AliHLTMUONHitReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
108 {
109         ///
110         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
111         ///
112         
113         list.clear();
114         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
115 }
116
117
118 AliHLTComponentDataType AliHLTMUONHitReconstructorComponent::GetOutputDataType()
119 {
120         ///
121         /// Inherited from AliHLTComponent. Returns the output data type.
122         ///
123         
124         return AliHLTMUONConstants::RecHitsBlockDataType();
125 }
126
127
128 void AliHLTMUONHitReconstructorComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
129 {
130         ///
131         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
132         ///
133         
134         constBase = sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType);
135         inputMultiplier = 1;
136 }
137
138
139 AliHLTComponent* AliHLTMUONHitReconstructorComponent::Spawn()
140 {
141         ///
142         /// Inherited from AliHLTComponent. Creates a new object instance.
143         ///
144         
145         return new AliHLTMUONHitReconstructorComponent;
146 }
147
148
149 int AliHLTMUONHitReconstructorComponent::DoInit(int argc, const char** argv)
150 {
151         ///
152         /// Inherited from AliHLTComponent.
153         /// Parses the command line parameters and initialises the component.
154         ///
155
156         HLTInfo("Initialising dHLT hit reconstruction component.");
157         
158         // Must make sure that fHitRec and fLut is deleted if it is still
159         // allocated for whatever reason.
160         FreeMemory();
161         
162         try
163         {
164                 fHitRec = new AliHLTMUONHitReconstructor();
165         }
166         catch (const std::bad_alloc&)
167         {
168                 HLTError("Could not allocate more memory for the hit reconstructor component.");
169                 return -ENOMEM;
170         }
171         
172         // Initialise fields with default values then parse the command line.
173         fDDL = -1;
174         fIdToEntry.clear();
175         fWarnForUnexpecedBlock = false;
176         
177         const char* lutFileName = NULL;
178         const char* cdbPath = NULL;
179         Int_t run = -1;
180         bool useCDB = false;
181         
182         for (int i = 0; i < argc; i++)
183         {
184                 HLTDebug("argv[%d] == %s", i, argv[i]);
185                 
186                 if (strcmp( argv[i], "-ddl" ) == 0)
187                 {
188                         if (argc <= i+1)
189                         {
190                                 HLTError("The DDL number was not specified. Must be in the range [13..20].");
191                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
192                                 return -EINVAL;
193                         }
194                         
195                         char* cpErr = NULL;
196                         unsigned long num = strtoul( argv[i+1], &cpErr, 0 );
197                         if (cpErr == NULL or *cpErr != '\0')
198                         {
199                                 HLTError("Cannot convert '%s' to DDL a number.", argv[i+1] );
200                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
201                                 return -EINVAL;
202                         }
203                         if (num < 13 or 20 < num)
204                         {
205                                 HLTError("The DDL number must be in the range [13..20].");
206                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
207                                 return -EINVAL;
208                         }
209                         fDDL = num - 1;  // convert to range [12..19]
210                         
211                         i++;
212                         continue;
213                 } // -ddl argument
214                 
215                 if (strcmp( argv[i], "-lut" ) == 0)
216                 {
217                         if (argc <= i+1)
218                         {
219                                 HLTError("The lookup table filename was not specified.");
220                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
221                                 return -EINVAL;
222                         }
223                         lutFileName = argv[i+1];
224                         i++;
225                         continue;
226                 } // -lut argument
227                 
228                 if (strcmp( argv[i], "-cdb" ) == 0)
229                 {
230                         useCDB = true;
231                         continue;
232                 } // -cdb argument
233                 
234                 if (strcmp( argv[i], "-cdbpath" ) == 0)
235                 {
236                         if ( argc <= i+1 )
237                         {
238                                 HLTError("The CDB path was not specified." );
239                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
240                                 return -EINVAL;
241                         }
242                         cdbPath = argv[i+1];
243                         useCDB = true;
244                         i++;
245                         continue;
246                 } // -cdb argument
247         
248                 if (strcmp( argv[i], "-run" ) == 0)
249                 {
250                         if ( argc <= i+1 )
251                         {
252                                 HLTError("The RUN number was not specified." );
253                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
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                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
265                                 return -EINVAL;
266                         }
267                         
268                         i++;
269                         continue;
270                 } // -run argument
271                 
272                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
273                 {
274                         fWarnForUnexpecedBlock = true;
275                         continue;
276                 }
277         
278                 HLTError("Unknown option '%s'", argv[i]);
279                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
280                 return -EINVAL;
281         
282         } // for loop
283         
284         if (lutFileName == NULL) useCDB = true;
285         
286         if (fDDL == -1)
287         {
288                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
289         }
290         
291         int result = 0;
292         if (useCDB)
293         {
294                 HLTInfo("Loading lookup table information from CDB for DDL %d.", fDDL+1);
295                 if (fDDL == -1)
296                         HLTWarning("DDL number not specified. The lookup table loaded from CDB will be empty!");
297                 result = ReadCDB(cdbPath, run);
298         }
299         else
300         {
301                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
302                 result = ReadLookUpTable(lutFileName);
303         }
304         if (result != 0)
305         {
306                 // Error messages already generated in ReadCDB or ReadLookUpTable.
307                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
308                 return result;
309         }
310         
311         fHitRec->SetLookUpTable(fLut, &fIdToEntry);
312         
313         return 0;
314 }
315
316
317 int AliHLTMUONHitReconstructorComponent::DoDeinit()
318 {
319         ///
320         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
321         ///
322         
323         HLTInfo("Deinitialising dHLT hit reconstruction component.");
324         FreeMemory();
325         return 0;
326 }
327
328
329 int AliHLTMUONHitReconstructorComponent::DoEvent(
330                 const AliHLTComponentEventData& evtData,
331                 const AliHLTComponentBlockData* blocks,
332                 AliHLTComponentTriggerData& /*trigData*/,
333                 AliHLTUInt8_t* outputPtr,
334                 AliHLTUInt32_t& size,
335                 std::vector<AliHLTComponentBlockData>& outputBlocks
336         )
337 {
338         ///
339         /// Inherited from AliHLTProcessor. Processes the new event data.
340         ///
341         
342         // Process an event
343         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
344
345         HLTDebug("Processing event %llu with %u input data blocks.",
346                 evtData.fEventID, evtData.fBlockCnt
347         );
348
349         // Loop over all input blocks in the event
350         for ( unsigned long n = 0; n < evtData.fBlockCnt; n++ )
351         {
352 #ifdef __DEBUG
353                 char id[kAliHLTComponentDataTypefIDsize+1];
354                 for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
355                         id[i] = blocks[n].fDataType.fID[i];
356                 id[kAliHLTComponentDataTypefIDsize] = '\0';
357                 char origin[kAliHLTComponentDataTypefOriginSize+1];
358                 for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
359                         origin[i] = blocks[n].fDataType.fOrigin[i];
360                 origin[kAliHLTComponentDataTypefOriginSize] = '\0';
361 #endif // __DEBUG
362                 HLTDebug("Handling block: %u, with fDataType.fID = '%s',"
363                           " fDataType.fID = '%s', fPtr = %p and fSize = %u bytes.",
364                         n, static_cast<char*>(id), static_cast<char*>(origin),
365                         blocks[n].fPtr, blocks[n].fSize
366                 );
367
368                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
369                     or not AliHLTMUONUtils::IsTrackerDDL(blocks[n].fSpecification)
370                    )
371                 {
372                         // Log a message indicating that we got a data block that we
373                         // do not know how to handle.
374                         char id[kAliHLTComponentDataTypefIDsize+1];
375                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
376                                 id[i] = blocks[n].fDataType.fID[i];
377                         id[kAliHLTComponentDataTypefIDsize] = '\0';
378                         char origin[kAliHLTComponentDataTypefOriginSize+1];
379                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
380                                 origin[i] = blocks[n].fDataType.fOrigin[i];
381                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
382                         
383                         if (fWarnForUnexpecedBlock)
384                                 HLTWarning("Received a data block of a type we cannot handle: '%s' origin: '%s' spec: 0x%X",
385                                         static_cast<char*>(id), static_cast<char*>(origin), blocks[n].fSpecification
386                                 );
387                         else
388                                 HLTDebug("Received a data block of a type we cannot handle: '%s' origin: '%s' spec: 0x%X",
389                                         static_cast<char*>(id), static_cast<char*>(origin), blocks[n].fSpecification
390                                 );
391                         
392                         continue;
393                 }
394                 
395                 if (fDDL != -1)
396                 {
397                         bool ddl[22];
398                         AliHLTMUONUtils::UnpackSpecBits(blocks[n].fSpecification, ddl);
399                         if (not ddl[fDDL])
400                         {
401                                 HLTWarning("Received raw data from an unexpected DDL.");
402                         }
403                 }
404                 
405                 // Create a new output data block and initialise the header.
406                 AliHLTMUONRecHitsBlockWriter block(outputPtr+totalSize, size-totalSize);
407                 if (not block.InitCommonHeader())
408                 {
409                         HLTError("There is not enough space in the output buffer for the new data block.",
410                                  " We require at least %u bytes, but have %u bytes left.",
411                                 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
412                                 block.BufferSize()
413                         );
414                         break;
415                 }
416                 
417                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize / sizeof(AliHLTUInt32_t);
418                 AliHLTUInt32_t ddlRawDataSize = totalDDLSize - fHitRec->GetkDDLHeaderSize();
419                 AliHLTUInt32_t* buffer = reinterpret_cast<AliHLTUInt32_t*>(blocks[n].fPtr)
420                         + fHitRec->GetkDDLHeaderSize();
421                 AliHLTUInt32_t nofHit = block.MaxNumberOfEntries();
422
423 #ifdef DEBUG
424                 HLTDebug("=========== Dumping DDL payload buffer ==========");
425                 for (AliHLTUInt32_t j = 0; j < totalDDLSize; j++)
426                         HLTDebug("buffer[%d] : %x",j,buffer[j]);
427                 HLTDebug("================== End of dump =================");
428 #endif // DEBUG
429
430                 if (not fHitRec->Run(buffer, ddlRawDataSize, block.GetArray(), nofHit))
431                 {
432                         HLTError("Error while processing of hit reconstruction algorithm.");
433                         size = totalSize; // Must tell the framework how much buffer space was used.
434                         return -EIO;
435                 }
436                 
437                 // nofHit should now contain the number of reconstructed hits actually found
438                 // and filled into the output data block, so we can set this number.
439                 assert( nofHit <= block.MaxNumberOfEntries() );
440                 block.SetNumberOfEntries(nofHit);
441                 
442                 HLTDebug("Number of reconstructed hits found is %d", nofHit);
443
444                 // Fill a block data structure for our output block.
445                 AliHLTComponentBlockData bd;
446                 FillBlockData(bd);
447                 bd.fPtr = outputPtr;
448                 // This block's start (offset) is after all other blocks written so far.
449                 bd.fOffset = totalSize;
450                 bd.fSize = block.BytesUsed();
451                 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
452                 bd.fSpecification = blocks[n].fSpecification;
453                 outputBlocks.push_back(bd);
454
455                 // Increase the total amount of data written so far to our output memory
456                 totalSize += block.BytesUsed();
457         }
458         // Finally we set the total size of output memory we consumed.
459         size = totalSize;
460
461         return 0;
462 }
463
464
465 void AliHLTMUONHitReconstructorComponent::FreeMemory()
466 {
467         /// Deletes any allocated objects if they are allocated else nothing is
468         /// done for objects not yet allocated.
469         /// This is used as a helper method to make sure the corresponding pointers
470         /// are NULL and we get back to a well defined state.
471
472         if (fHitRec != NULL)
473         {
474                 delete fHitRec;
475                 fHitRec = NULL;
476         }
477         if (fLut != NULL)
478         {
479                 delete fLut;
480                 fLut = NULL;
481                 fLutSize = 0;
482         }
483         
484         fIdToEntry.clear();
485 }
486
487
488 int AliHLTMUONHitReconstructorComponent::ReadLookUpTable(const char* lutFileName)
489 {
490         /// Read in the lookup table from a text file.
491         /// Note that this method could leave fLut allocated which is cleaned up
492         /// by DoInit with a call to FreeMemory().
493         
494         assert( fLut == NULL );
495         assert( fLutSize == 0 );
496         assert( fIdToEntry.empty() );
497         
498         std::ifstream file(lutFileName);
499         if (not file.good())
500         {
501                 HLTError("Could not open the LUT file %s", lutFileName);
502                 return -ENOENT;
503         }
504         
505         // First count the number of lines of text in the LUT file before decoding.
506         // This is not the most optimal. It would be better to read and decode at the
507         // same time but we are not allowed to use STL and ROOT containers are too
508         // heavy for this task. At least this is done only at the start of run.
509         std::string str;
510         AliHLTUInt32_t lineCount = 0;
511         while (std::getline(file, str)) lineCount++;
512         if (not file.eof())
513         {
514                 HLTError("There was a problem reading the LUT file %s", lutFileName);
515                 return -EIO;
516         }
517         if (lineCount == 0)
518         {
519                 HLTWarning("The LUT file %s was empty.", lutFileName);
520         }
521         
522         // Add one extra LUT line for the first element which is used as a sentinel value.
523         lineCount++;
524         
525         try
526         {
527                 fLut = new AliHLTMUONHitRecoLutRow[lineCount];
528                 fLutSize = lineCount;
529         }
530         catch (const std::bad_alloc&)
531         {
532                 HLTError("Could not allocate more memory for the lookuptable.");
533                 return -ENOMEM;
534         }
535         
536         // Initialise the sentinel value.
537         fLut[0].fDetElemId = 0;
538         fLut[0].fIX = 0;
539         fLut[0].fIY = 0;
540         fLut[0].fRealX = 0.0;
541         fLut[0].fRealY = 0.0;
542         fLut[0].fRealZ = 0.0;
543         fLut[0].fHalfPadSize = 0.0;
544         fLut[0].fPlane = -1;
545         fLut[0].fPed = -1;
546         fLut[0].fSigma = -1;
547         fLut[0].fA0 = -1;
548         fLut[0].fA1 = -1;
549         fLut[0].fThres = -1;
550         fLut[0].fSat = -1;
551         
552         // Clear the eof flag and start reading from the beginning of the file again.
553         file.clear();
554         file.seekg(0, std::ios::beg);
555         if (not file.good())
556         {
557                 HLTError("There was a problem seeking in the LUT file %s", lutFileName);
558                 return -EIO;
559         }
560         
561         AliHLTInt32_t idManuChannel;
562         for (AliHLTUInt32_t i = 1; i < fLutSize; i++)
563         {
564                 if (std::getline(file, str).fail())
565                 {
566                         HLTError("There was a problem reading line %d of LUT file %s", i, lutFileName);
567                         return -EIO;
568                 }
569                 
570                 int result = sscanf(
571                         str.c_str(), "%d\t%d\t%d\t%d\t%e\t%e\t%e\t%e\t%d\t%e\t%e\t%e\t%e\t%d\t%d",
572                         &idManuChannel, &fLut[i].fDetElemId, &fLut[i].fIX,
573                         &fLut[i].fIY, &fLut[i].fRealX,
574                         &fLut[i].fRealY, &fLut[i].fRealZ,
575                         &fLut[i].fHalfPadSize, &fLut[i].fPlane,
576                         &fLut[i].fPed, &fLut[i].fSigma, &fLut[i].fA0,
577                         &fLut[i].fA1, &fLut[i].fThres, &fLut[i].fSat
578                 );
579                 
580                 if (result != 15)
581                 {
582                         HLTError("Line %d in LUT file %s does not contain 15 elements.", i, lutFileName);
583                         return -EIO;
584                 }
585                 
586                 fIdToEntry[idManuChannel] = i;
587         }
588         
589         return 0;
590 }
591
592
593 int AliHLTMUONHitReconstructorComponent::ReadCDB(const char* cdbPath, Int_t run)
594 {
595         // Reads LUT from CDB.
596         // TODO: merge this with CreateHitRecoLookupTables.C, make this static and use in the macro for example.
597
598         assert( fLut == NULL );
599         assert( fLutSize == 0 );
600         assert( fIdToEntry.empty() );
601         
602         std::vector<AliHLTMUONHitRecoLutRow> lutList;
603         AliHLTMUONHitRecoLutRow lut;
604         AliHLTUInt32_t iEntry = 0;
605         
606         Bool_t warn = kFALSE;
607         
608         AliCDBManager* cdbManager = AliCDBManager::Instance();
609         if (cdbManager == NULL)
610         {
611                 HLTError("CDB manager instance does not exist.");
612                 return -EIO;
613         }
614         
615         const char* cdbPathUsed = "unknown (not set)";
616         if (cdbPath != NULL)
617         {
618                 cdbManager->SetDefaultStorage(cdbPath);
619                 cdbPathUsed = cdbPath;
620         }
621         else
622         {
623                 AliCDBStorage* store = cdbManager->GetDefaultStorage();
624                 if (store != NULL) cdbPathUsed = store->GetURI().Data();
625         }
626         
627         if (run != -1) cdbManager->SetRun(run);
628         Int_t runUsed = cdbManager->GetRun();
629         
630         if (not AliMpCDB::LoadDDLStore(warn))
631         {
632                 HLTError("Failed to load DDL store specified for CDB path '%s' and run no. %d",
633                         cdbPathUsed, runUsed
634                 );
635                 return -ENOENT;
636         }
637         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
638         if (ddlStore == NULL)
639         {
640                 HLTError("Could not find DDL store instance.");
641                 return -EIO;
642         }
643         AliMpSegmentation* mpSegFactory = AliMpSegmentation::Instance();
644         if (mpSegFactory == NULL)
645         {
646                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
647                 return -EIO;
648         }
649         
650         AliGeomManager::LoadGeometry();
651         AliMUONGeometryTransformer chamberGeometryTransformer;
652         if (not chamberGeometryTransformer.LoadGeometryData())
653         {
654                 HLTError("Failed to load geomerty data.");
655                 return -ENOENT;
656         }
657         
658         AliMUONCalibrationData calibData(run);
659         
660         Int_t chamberId;
661         
662         for(Int_t iCh = 6; iCh < 10; iCh++)
663         {
664                 chamberId = iCh;
665                 
666                 AliMpDEIterator it;
667                 for ( it.First(chamberId); ! it.IsDone(); it.Next() )
668                 {
669                         Int_t detElemId = it.CurrentDEId();
670                         int iDDL = ddlStore->GetDetElement(detElemId)->GetDdlId();
671                         if (iDDL != fDDL) continue;
672                 
673                         for (Int_t iCath = 0 ; iCath <= 1 ; iCath++)
674                         {
675                                 AliMp::CathodType cath;
676                                 
677                                 if(iCath == 0)
678                                         cath = AliMp::kCath0;
679                                 else
680                                         cath = AliMp::kCath1;
681                                 
682                                 const AliMpVSegmentation* seg = mpSegFactory->GetMpSegmentation(detElemId, cath);
683                                 AliMp::PlaneType plane = seg->PlaneType();
684                                 Int_t maxIX = seg->MaxPadIndexX();
685                                 Int_t maxIY = seg->MaxPadIndexY();
686                                 
687                                 Int_t idManuChannel, manuId, channelId, buspatchId;
688                                 AliHLTFloat32_t padSizeX, padSizeY;
689                                 AliHLTFloat32_t halfPadSize;
690                                 Double_t realX, realY, realZ;
691                                 Double_t localX, localY, localZ;
692                                 Float_t calibA0Coeff,calibA1Coeff,pedestal,sigma;
693                                 Int_t thresold,saturation;
694                                 
695                                 // Pad Info of a slat to print in lookuptable
696                                 for (Int_t iX = 0; iX<= maxIX ; iX++)
697                                 for (Int_t iY = 0; iY<= maxIY ; iY++)
698                                 {
699                                         if (not seg->HasPad(AliMpIntPair(iX,iY))) continue;
700
701                                         AliMpPad pad = seg->PadByIndices(AliMpIntPair(iX,iY), kFALSE);
702                                         
703                                         // Getting Manu id
704                                         manuId = pad.GetLocation().GetFirst();
705                                         manuId &= 0x7FF; // 11 bits 
706                         
707                                         buspatchId = ddlStore->GetBusPatchId(detElemId,manuId);
708                                         
709                                         // Getting channel id
710                                         channelId =  pad.GetLocation().GetSecond();
711                                         channelId &= 0x3F; // 6 bits
712                                         
713                                         idManuChannel = buspatchId << 11;
714                                         idManuChannel = (idManuChannel | manuId) << 6;
715                                         idManuChannel |= channelId;
716                                         
717                                         localX = pad.Position().X();
718                                         localY = pad.Position().Y();
719                                         localZ = 0.0;
720                                         
721                                         chamberGeometryTransformer.Local2Global(
722                                                 detElemId,localX,localY,localZ,
723                                                 realX,realY,realZ
724                                         );
725                                         
726                                         padSizeX = pad.Dimensions().X();
727                                         padSizeY = pad.Dimensions().Y();
728                                         
729                                         calibA0Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 0);
730                                         calibA1Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 1);
731                                         thresold = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 2);
732                                         saturation = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 4);
733                                         
734                                         pedestal = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 0);
735                                         sigma = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 1);
736                                         
737                                         if (plane == 0)
738                                                 halfPadSize = padSizeX;
739                                         else
740                                                 halfPadSize = padSizeY;
741                                         
742                                         fIdToEntry[idManuChannel] = iEntry+1;
743                         
744                                         lut.fDetElemId = detElemId;
745                                         lut.fIX = iX;
746                                         lut.fIY = iY;
747                                         lut.fRealX = realX;
748                                         lut.fRealY = realY;
749                                         lut.fRealZ = realZ;
750                                         lut.fHalfPadSize = halfPadSize;
751                                         lut.fPlane = plane;
752                                         lut.fPed = pedestal;
753                                         lut.fSigma = sigma;
754                                         lut.fA0 = calibA0Coeff;
755                                         lut.fA1 = calibA1Coeff;
756                                         lut.fThres = thresold;
757                                         lut.fSat = saturation;
758                                         
759                                         lutList.push_back(lut);
760                                         iEntry++;
761                                 } // iX, iY loop
762                         } // iCath loop
763                 } // detElemId loop
764         } // ichamber loop
765
766         try
767         {
768                 // Use iEntry+1 since we add one extra LUT line for the first element
769                 // which is used as a sentinel value.
770                 fLut = new AliHLTMUONHitRecoLutRow[iEntry+1];
771                 fLutSize = iEntry+1;
772         }
773         catch (const std::bad_alloc&)
774         {
775                 HLTError("Could not allocate more memory for the lookuptable.");
776                 return -ENOMEM;
777         }
778         
779         // Initialise the sentinel value.
780         fLut[0].fDetElemId = 0;
781         fLut[0].fIX = 0;
782         fLut[0].fIY = 0;
783         fLut[0].fRealX = 0.0;
784         fLut[0].fRealY = 0.0;
785         fLut[0].fRealZ = 0.0;
786         fLut[0].fHalfPadSize = 0.0;
787         fLut[0].fPlane = -1;
788         fLut[0].fPed = -1;
789         fLut[0].fSigma = -1;
790         fLut[0].fA0 = -1;
791         fLut[0].fA1 = -1;
792         fLut[0].fThres = -1;
793         fLut[0].fSat = -1;
794         
795         for (AliHLTUInt32_t i = 0; i < iEntry; i++)
796                 fLut[i+1] = lutList[i];
797         
798         return 0;
799 }
800
801
802 bool AliHLTMUONHitReconstructorComponent::GenerateLookupTable(
803                 AliHLTInt32_t ddl, const char* filename,
804                 const char* cdbPath, Int_t run
805         )
806 {
807         /// Generates a ASCII text file containing the lookup table (LUT) from
808         /// the CDB, which can be used for the hit reconstructor component later.
809         /// @param ddl  Must be the DDL for which to generate the DDL,
810         ///             in the range [13..20].
811         /// @param filename  The name of the LUT file to generate.
812         /// @param cdbPath  The CDB path to use.
813         /// @param run  The run number to use for the CDB.
814         /// @return  True if the generation of the LUT file succeeded.
815         
816         AliHLTMUONHitReconstructorComponent comp;
817         
818         if (ddl < 12 or 19 < ddl)
819         {
820                 std::cerr << "ERROR: the DDL number must be in the range [12..19]." << std::endl;
821                 return false;
822         }
823         
824         comp.fDDL = ddl;
825         if (comp.ReadCDB(cdbPath, run) != 0) return false;
826         
827         char str[1024*4];
828         std::fstream file(filename, std::ios::out);
829         if (not file)
830         {
831                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
832                 return false;
833         }
834         
835         assert( comp.fLut != NULL );
836         
837         for (IdManuChannelToEntry::iterator id = comp.fIdToEntry.begin();
838              id != comp.fIdToEntry.end();
839              id++
840             )
841         {
842                 AliHLTInt32_t idManuChannel = id->first;
843                 AliHLTInt32_t row = id->second;
844                 
845                 assert( row < comp.fLutSize );
846                 
847                 sprintf(str, "%d\t%d\t%d\t%d\t%.15e\t%.15e\t%.15e\t%.15e\t%d\t%.15e\t%.15e\t%.15e\t%.15e\t%d\t%d",
848                         idManuChannel, comp.fLut[row].fDetElemId, comp.fLut[row].fIX,
849                         comp.fLut[row].fIY, comp.fLut[row].fRealX,
850                         comp.fLut[row].fRealY, comp.fLut[row].fRealZ,
851                         comp.fLut[row].fHalfPadSize, comp.fLut[row].fPlane,
852                         comp.fLut[row].fPed, comp.fLut[row].fSigma, comp.fLut[row].fA0,
853                         comp.fLut[row].fA1, comp.fLut[row].fThres, comp.fLut[row].fSat
854                 );
855                 
856                 file << str << endl;
857                 if (file.fail())
858                 {
859                         std::cerr << "ERROR: There was an I/O error when writing to the file: "
860                                 << filename << std::endl;
861                         return false;
862                 }
863         }
864         
865         return true;
866 }