Made changes to the trigger reconstructor component algorithm to interpret raw DDL...
[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         AliHLTMUONProcessor(),
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         bool tryRecover = false;
182         
183         for (int i = 0; i < argc; i++)
184         {
185                 HLTDebug("argv[%d] == %s", i, argv[i]);
186                 
187                 if (strcmp( argv[i], "-ddl" ) == 0)
188                 {
189                         if (argc <= i+1)
190                         {
191                                 HLTError("The DDL number was not specified. Must be in the range [13..20].");
192                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
193                                 return -EINVAL;
194                         }
195                         
196                         char* cpErr = NULL;
197                         unsigned long num = strtoul( argv[i+1], &cpErr, 0 );
198                         if (cpErr == NULL or *cpErr != '\0')
199                         {
200                                 HLTError("Cannot convert '%s' to DDL a number.", argv[i+1] );
201                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
202                                 return -EINVAL;
203                         }
204                         if (num < 13 or 20 < num)
205                         {
206                                 HLTError("The DDL number must be in the range [13..20].");
207                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
208                                 return -EINVAL;
209                         }
210                         fDDL = num - 1;  // convert to range [12..19]
211                         
212                         i++;
213                         continue;
214                 } // -ddl argument
215                 
216                 if (strcmp( argv[i], "-ddlid" ) == 0)
217                 {
218                         if ( argc <= i+1 )
219                         {
220                                 HLTError("DDL equipment ID number not specified. It must be in the range [2572..2579]" );
221                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
222                                 return -EINVAL;
223                         }
224                 
225                         char* cpErr = NULL;
226                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
227                         if (cpErr == NULL or *cpErr != '\0')
228                         {
229                                 HLTError("Cannot convert '%s' to a DDL equipment ID Number.", argv[i+1]);
230                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
231                                 return -EINVAL;
232                         }
233                         fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
234                         if (fDDL < 12 or 19 < fDDL)
235                         {
236                                 HLTError("The DDL equipment ID number must be in the range [2572..2579].");
237                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
238                                 return -EINVAL;
239                         }
240                         
241                         i++;
242                         continue;
243                 }
244                 
245                 if (strcmp( argv[i], "-lut" ) == 0)
246                 {
247                         if (argc <= i+1)
248                         {
249                                 HLTError("The lookup table filename was not specified.");
250                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
251                                 return -EINVAL;
252                         }
253                         lutFileName = argv[i+1];
254                         i++;
255                         continue;
256                 } // -lut argument
257                 
258                 if (strcmp( argv[i], "-cdb" ) == 0)
259                 {
260                         useCDB = true;
261                         continue;
262                 } // -cdb argument
263                 
264                 if (strcmp( argv[i], "-cdbpath" ) == 0)
265                 {
266                         if ( argc <= i+1 )
267                         {
268                                 HLTError("The CDB path was not specified." );
269                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
270                                 return -EINVAL;
271                         }
272                         cdbPath = argv[i+1];
273                         useCDB = true;
274                         i++;
275                         continue;
276                 } // -cdb argument
277         
278                 if (strcmp( argv[i], "-run" ) == 0)
279                 {
280                         if ( argc <= i+1 )
281                         {
282                                 HLTError("The RUN number was not specified." );
283                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
284                                 return -EINVAL;
285                         }
286                         
287                         char* cpErr = NULL;
288                         run = Int_t( strtoul(argv[i+1], &cpErr, 0) );
289                         if (cpErr == NULL or *cpErr != '\0')
290                         {
291                                 HLTError("Cannot convert '%s' to a valid run number."
292                                         " Expected an integer value.", argv[i+1]
293                                 );
294                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
295                                 return -EINVAL;
296                         }
297                         
298                         i++;
299                         continue;
300                 } // -run argument
301                 
302                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
303                 {
304                         fWarnForUnexpecedBlock = true;
305                         continue;
306                 }
307                 
308                 if (strcmp( argv[i], "-tryrecover" ) == 0)
309                 {
310                         tryRecover = true;
311                         continue;
312                 }
313         
314                 HLTError("Unknown option '%s'", argv[i]);
315                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
316                 return -EINVAL;
317         
318         } // for loop
319         
320         if (lutFileName == NULL) useCDB = true;
321         
322         if (fDDL == -1)
323         {
324                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
325         }
326         
327         int result = 0;
328         if (useCDB)
329         {
330                 HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
331                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
332                 );
333                 if (fDDL == -1)
334                         HLTWarning("DDL number not specified. The lookup table loaded from CDB will be empty!");
335                 result = ReadCDB(cdbPath, run);
336         }
337         else
338         {
339                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
340                 result = ReadLookUpTable(lutFileName);
341         }
342         if (result != 0)
343         {
344                 // Error messages already generated in ReadCDB or ReadLookUpTable.
345                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
346                 return result;
347         }
348         
349         fHitRec->SetLookUpTable(fLut, &fIdToEntry);
350         fHitRec->TryRecover(tryRecover);
351         
352         return 0;
353 }
354
355
356 int AliHLTMUONHitReconstructorComponent::DoDeinit()
357 {
358         ///
359         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
360         ///
361         
362         HLTInfo("Deinitialising dHLT hit reconstruction component.");
363         FreeMemory();
364         return 0;
365 }
366
367
368 int AliHLTMUONHitReconstructorComponent::DoEvent(
369                 const AliHLTComponentEventData& evtData,
370                 const AliHLTComponentBlockData* blocks,
371                 AliHLTComponentTriggerData& /*trigData*/,
372                 AliHLTUInt8_t* outputPtr,
373                 AliHLTUInt32_t& size,
374                 std::vector<AliHLTComponentBlockData>& outputBlocks
375         )
376 {
377         ///
378         /// Inherited from AliHLTProcessor. Processes the new event data.
379         ///
380         
381         // Process an event
382         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
383
384         HLTDebug("Processing event %llu with %u input data blocks.",
385                 evtData.fEventID, evtData.fBlockCnt
386         );
387
388         // Loop over all input blocks in the event
389         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
390         {
391                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
392                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
393                 );
394
395                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
396                     or not AliHLTMUONUtils::IsTrackerDDL(blocks[n].fSpecification)
397                    )
398                 {
399                         // Log a message indicating that we got a data block that we
400                         // do not know how to handle.
401                         if (fWarnForUnexpecedBlock)
402                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
403                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
404                                 );
405                         else
406                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
407                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
408                                 );
409                         
410                         continue;
411                 }
412                 
413                 if (fDDL != -1)
414                 {
415                         AliHLTInt32_t receivedDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
416                         if (receivedDDL != fDDL)
417                         {
418                                 HLTWarning("Received raw data from DDL %d (ID = %d),"
419                                         " but expect data only from DDL %d (ID = %d).",
420                                         receivedDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(receivedDDL),
421                                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
422                                 );
423                         }
424                 }
425                 
426                 // Create a new output data block and initialise the header.
427                 AliHLTMUONRecHitsBlockWriter block(outputPtr+totalSize, size-totalSize);
428                 if (not block.InitCommonHeader())
429                 {
430                         HLTError("There is not enough space in the output buffer for the new data block."
431                                  " We require at least %u bytes, but have %u bytes left.",
432                                 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
433                                 block.BufferSize()
434                         );
435                         break;
436                 }
437                 
438                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize / sizeof(AliHLTUInt32_t);
439                 AliHLTUInt32_t ddlRawDataSize = totalDDLSize - fHitRec->GetkDDLHeaderSize();
440                 AliHLTUInt32_t* buffer = reinterpret_cast<AliHLTUInt32_t*>(blocks[n].fPtr)
441                         + fHitRec->GetkDDLHeaderSize();
442                 AliHLTUInt32_t nofHit = block.MaxNumberOfEntries();
443
444 #ifdef DEBUG
445                 HLTDebug("=========== Dumping DDL payload buffer ==========");
446                 for (AliHLTUInt32_t j = 0; j < totalDDLSize; j++)
447                         HLTDebug("buffer[%d] : %x",j,buffer[j]);
448                 HLTDebug("================== End of dump =================");
449 #endif // DEBUG
450
451                 if (not fHitRec->Run(buffer, ddlRawDataSize, block.GetArray(), nofHit))
452                 {
453                         HLTError("Error while processing the hit reconstruction algorithm.");
454                         size = totalSize; // Must tell the framework how much buffer space was used.
455                         return -EIO;
456                 }
457                 
458                 // nofHit should now contain the number of reconstructed hits actually found
459                 // and filled into the output data block, so we can set this number.
460                 assert( nofHit <= block.MaxNumberOfEntries() );
461                 block.SetNumberOfEntries(nofHit);
462                 
463                 HLTDebug("Number of reconstructed hits found is %d", nofHit);
464
465                 // Fill a block data structure for our output block.
466                 AliHLTComponentBlockData bd;
467                 FillBlockData(bd);
468                 bd.fPtr = outputPtr;
469                 // This block's start (offset) is after all other blocks written so far.
470                 bd.fOffset = totalSize;
471                 bd.fSize = block.BytesUsed();
472                 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
473                 bd.fSpecification = blocks[n].fSpecification;
474                 outputBlocks.push_back(bd);
475
476                 // Increase the total amount of data written so far to our output memory
477                 totalSize += block.BytesUsed();
478         }
479         // Finally we set the total size of output memory we consumed.
480         size = totalSize;
481
482         return 0;
483 }
484
485
486 void AliHLTMUONHitReconstructorComponent::FreeMemory()
487 {
488         /// Deletes any allocated objects if they are allocated else nothing is
489         /// done for objects not yet allocated.
490         /// This is used as a helper method to make sure the corresponding pointers
491         /// are NULL and we get back to a well defined state.
492
493         if (fHitRec != NULL)
494         {
495                 delete fHitRec;
496                 fHitRec = NULL;
497         }
498         if (fLut != NULL)
499         {
500                 delete [] fLut;
501                 fLut = NULL;
502                 fLutSize = 0;
503         }
504         
505         fIdToEntry.clear();
506 }
507
508
509 int AliHLTMUONHitReconstructorComponent::ReadLookUpTable(const char* lutFileName)
510 {
511         /// Read in the lookup table from a text file.
512         /// Note that this method could leave fLut allocated which is cleaned up
513         /// by DoInit with a call to FreeMemory().
514         
515         assert( fLut == NULL );
516         assert( fLutSize == 0 );
517         assert( fIdToEntry.empty() );
518         
519         std::ifstream file(lutFileName);
520         if (not file.good())
521         {
522                 HLTError("Could not open the LUT file %s", lutFileName);
523                 return -ENOENT;
524         }
525         
526         // First count the number of lines of text in the LUT file before decoding.
527         // This is not the most optimal. It would be better to read and decode at the
528         // same time but we are not allowed to use STL and ROOT containers are too
529         // heavy for this task. At least this is done only at the start of run.
530         std::string str;
531         AliHLTUInt32_t lineCount = 0;
532         while (std::getline(file, str)) lineCount++;
533         if (not file.eof())
534         {
535                 HLTError("There was a problem reading the LUT file %s", lutFileName);
536                 return -EIO;
537         }
538         if (lineCount == 0)
539         {
540                 HLTWarning("The LUT file %s was empty.", lutFileName);
541         }
542         
543         // Add one extra LUT line for the first element which is used as a sentinel value.
544         lineCount++;
545         
546         try
547         {
548                 fLut = new AliHLTMUONHitRecoLutRow[lineCount];
549                 fLutSize = lineCount;
550         }
551         catch (const std::bad_alloc&)
552         {
553                 HLTError("Could not allocate more memory for the lookuptable.");
554                 return -ENOMEM;
555         }
556         
557         // Initialise the sentinel value.
558         fLut[0].fDetElemId = 0;
559         fLut[0].fIX = 0;
560         fLut[0].fIY = 0;
561         fLut[0].fRealX = 0.0;
562         fLut[0].fRealY = 0.0;
563         fLut[0].fRealZ = 0.0;
564         fLut[0].fHalfPadSize = 0.0;
565         fLut[0].fPlane = -1;
566         fLut[0].fPed = -1;
567         fLut[0].fSigma = -1;
568         fLut[0].fA0 = -1;
569         fLut[0].fA1 = -1;
570         fLut[0].fThres = -1;
571         fLut[0].fSat = -1;
572         
573         // Clear the eof flag and start reading from the beginning of the file again.
574         file.clear();
575         file.seekg(0, std::ios::beg);
576         if (not file.good())
577         {
578                 HLTError("There was a problem seeking in the LUT file %s", lutFileName);
579                 return -EIO;
580         }
581         
582         AliHLTInt32_t idManuChannel;
583         for (AliHLTUInt32_t i = 1; i < fLutSize; i++)
584         {
585                 if (std::getline(file, str).fail())
586                 {
587                         HLTError("There was a problem reading line %d of LUT file %s", i, lutFileName);
588                         return -EIO;
589                 }
590                 
591                 int result = sscanf(
592                         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",
593                         &idManuChannel, &fLut[i].fDetElemId, &fLut[i].fIX,
594                         &fLut[i].fIY, &fLut[i].fRealX,
595                         &fLut[i].fRealY, &fLut[i].fRealZ,
596                         &fLut[i].fHalfPadSize, &fLut[i].fPlane,
597                         &fLut[i].fPed, &fLut[i].fSigma, &fLut[i].fA0,
598                         &fLut[i].fA1, &fLut[i].fThres, &fLut[i].fSat
599                 );
600                 
601                 if (result != 15)
602                 {
603                         HLTError("Line %d in LUT file %s does not contain 15 elements.", i, lutFileName);
604                         return -EIO;
605                 }
606                 
607                 fIdToEntry[idManuChannel] = i;
608         }
609         
610         return 0;
611 }
612
613
614 int AliHLTMUONHitReconstructorComponent::ReadCDB(const char* cdbPath, Int_t run)
615 {
616         /// Reads LUT from CDB.
617
618         assert( fLut == NULL );
619         assert( fLutSize == 0 );
620         assert( fIdToEntry.empty() );
621         
622         if (fDDL == -1)
623         {
624                 HLTError("No DDL number specified for which to load LUT data from CDB.");
625                 return -EINVAL;
626         }
627         
628         std::vector<AliHLTMUONHitRecoLutRow> lutList;
629         AliHLTMUONHitRecoLutRow lut;
630         AliHLTUInt32_t iEntry = 0;
631         
632         int result = FetchMappingStores(cdbPath, run);
633         // Error message already generated in FetchMappingStores.
634         if (result != 0) return result;
635         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
636         
637         AliMpSegmentation* mpSegFactory = AliMpSegmentation::Instance();
638         if (mpSegFactory == NULL)
639         {
640                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
641                 return -EIO;
642         }
643         
644         // Only load geometry if not already loaded.
645         if (AliGeomManager::GetGeometry() == NULL)
646         {
647                 AliGeomManager::LoadGeometry();
648         }
649         AliMUONGeometryTransformer chamberGeometryTransformer;
650         if (not chamberGeometryTransformer.LoadGeometryData())
651         {
652                 HLTError("Failed to load geomerty data.");
653                 return -ENOENT;
654         }
655         
656         AliMUONCalibrationData calibData(run);
657         
658         Int_t chamberId;
659         
660         for(Int_t iCh = 6; iCh < 10; iCh++)
661         {
662                 chamberId = iCh;
663                 
664                 AliMpDEIterator it;
665                 for ( it.First(chamberId); ! it.IsDone(); it.Next() )
666                 {
667                         Int_t detElemId = it.CurrentDEId();
668                         int iDDL = ddlStore->GetDetElement(detElemId)->GetDdlId();
669                         if (iDDL != fDDL) continue;
670                 
671                         for (Int_t iCath = 0 ; iCath <= 1 ; iCath++)
672                         {
673                                 AliMp::CathodType cath;
674                                 
675                                 if(iCath == 0)
676                                         cath = AliMp::kCath0;
677                                 else
678                                         cath = AliMp::kCath1;
679                                 
680                                 const AliMpVSegmentation* seg = mpSegFactory->GetMpSegmentation(detElemId, cath);
681                                 AliMp::PlaneType plane = seg->PlaneType();
682                                 Int_t maxIX = seg->MaxPadIndexX();
683                                 Int_t maxIY = seg->MaxPadIndexY();
684                                 
685                                 Int_t idManuChannel, manuId, channelId, buspatchId;
686                                 AliHLTFloat32_t padSizeX, padSizeY;
687                                 AliHLTFloat32_t halfPadSize;
688                                 Double_t realX, realY, realZ;
689                                 Double_t localX, localY, localZ;
690                                 Float_t calibA0Coeff,calibA1Coeff,pedestal,sigma;
691                                 Int_t thresold,saturation;
692                                 
693                                 // Pad Info of a slat to print in lookuptable
694                                 for (Int_t iX = 0; iX<= maxIX ; iX++)
695                                 for (Int_t iY = 0; iY<= maxIY ; iY++)
696                                 {
697                                         if (not seg->HasPad(AliMpIntPair(iX,iY))) continue;
698
699                                         AliMpPad pad = seg->PadByIndices(AliMpIntPair(iX,iY), kFALSE);
700                                         
701                                         // Getting Manu id
702                                         manuId = pad.GetLocation().GetFirst();
703                                         manuId &= 0x7FF; // 11 bits 
704                         
705                                         buspatchId = ddlStore->GetBusPatchId(detElemId,manuId);
706                                         
707                                         // Getting channel id
708                                         channelId =  pad.GetLocation().GetSecond();
709                                         channelId &= 0x3F; // 6 bits
710                                         
711                                         idManuChannel = buspatchId << 11;
712                                         idManuChannel = (idManuChannel | manuId) << 6;
713                                         idManuChannel |= channelId;
714                                         
715                                         localX = pad.Position().X();
716                                         localY = pad.Position().Y();
717                                         localZ = 0.0;
718                                         
719                                         chamberGeometryTransformer.Local2Global(
720                                                 detElemId,localX,localY,localZ,
721                                                 realX,realY,realZ
722                                         );
723                                         
724                                         padSizeX = pad.Dimensions().X();
725                                         padSizeY = pad.Dimensions().Y();
726                                         
727                                         calibA0Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 0);
728                                         calibA1Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 1);
729                                         thresold = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 2);
730                                         saturation = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 4);
731                                         
732                                         pedestal = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 0);
733                                         sigma = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 1);
734                                         
735                                         if (plane == 0)
736                                                 halfPadSize = padSizeX;
737                                         else
738                                                 halfPadSize = padSizeY;
739                                         
740                                         fIdToEntry[idManuChannel] = iEntry+1;
741                         
742                                         lut.fDetElemId = detElemId;
743                                         lut.fIX = iX;
744                                         lut.fIY = iY;
745                                         lut.fRealX = realX;
746                                         lut.fRealY = realY;
747                                         lut.fRealZ = realZ;
748                                         lut.fHalfPadSize = halfPadSize;
749                                         lut.fPlane = plane;
750                                         lut.fPed = pedestal;
751                                         lut.fSigma = sigma;
752                                         lut.fA0 = calibA0Coeff;
753                                         lut.fA1 = calibA1Coeff;
754                                         lut.fThres = thresold;
755                                         lut.fSat = saturation;
756                                         
757                                         lutList.push_back(lut);
758                                         iEntry++;
759                                 } // iX, iY loop
760                         } // iCath loop
761                 } // detElemId loop
762         } // ichamber loop
763
764         try
765         {
766                 // Use iEntry+1 since we add one extra LUT line for the first element
767                 // which is used as a sentinel value.
768                 fLut = new AliHLTMUONHitRecoLutRow[iEntry+1];
769                 fLutSize = iEntry+1;
770         }
771         catch (const std::bad_alloc&)
772         {
773                 HLTError("Could not allocate more memory for the lookuptable.");
774                 return -ENOMEM;
775         }
776         
777         // Initialise the sentinel value.
778         fLut[0].fDetElemId = 0;
779         fLut[0].fIX = 0;
780         fLut[0].fIY = 0;
781         fLut[0].fRealX = 0.0;
782         fLut[0].fRealY = 0.0;
783         fLut[0].fRealZ = 0.0;
784         fLut[0].fHalfPadSize = 0.0;
785         fLut[0].fPlane = -1;
786         fLut[0].fPed = -1;
787         fLut[0].fSigma = -1;
788         fLut[0].fA0 = -1;
789         fLut[0].fA1 = -1;
790         fLut[0].fThres = -1;
791         fLut[0].fSat = -1;
792         
793         for (AliHLTUInt32_t i = 0; i < iEntry; i++)
794                 fLut[i+1] = lutList[i];
795         
796         return 0;
797 }
798
799
800 bool AliHLTMUONHitReconstructorComponent::GenerateLookupTable(
801                 AliHLTInt32_t ddl, const char* filename,
802                 const char* cdbPath, Int_t run
803         )
804 {
805         /// Generates a ASCII text file containing the lookup table (LUT) from
806         /// the CDB, which can be used for the hit reconstructor component later.
807         /// @param ddl  Must be the DDL for which to generate the DDL,
808         ///             in the range [13..20].
809         /// @param filename  The name of the LUT file to generate.
810         /// @param cdbPath  The CDB path to use.
811         /// @param run  The run number to use for the CDB.
812         /// @return  True if the generation of the LUT file succeeded.
813         
814         AliHLTMUONHitReconstructorComponent comp;
815         
816         if (ddl < 12 or 19 < ddl)
817         {
818                 std::cerr << "ERROR: the DDL number must be in the range [12..19]." << std::endl;
819                 return false;
820         }
821         
822         comp.fDDL = ddl;
823         if (comp.ReadCDB(cdbPath, run) != 0) return false;
824         
825         char str[1024*4];
826         std::fstream file(filename, std::ios::out);
827         if (not file)
828         {
829                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
830                 return false;
831         }
832         
833         assert( comp.fLut != NULL );
834         
835         for (IdManuChannelToEntry::iterator id = comp.fIdToEntry.begin();
836              id != comp.fIdToEntry.end();
837              id++
838             )
839         {
840                 AliHLTInt32_t idManuChannel = id->first;
841                 AliHLTInt32_t row = id->second;
842                 
843                 assert( row < comp.fLutSize );
844                 
845                 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",
846                         idManuChannel, comp.fLut[row].fDetElemId, comp.fLut[row].fIX,
847                         comp.fLut[row].fIY, comp.fLut[row].fRealX,
848                         comp.fLut[row].fRealY, comp.fLut[row].fRealZ,
849                         comp.fLut[row].fHalfPadSize, comp.fLut[row].fPlane,
850                         comp.fLut[row].fPed, comp.fLut[row].fSigma, comp.fLut[row].fA0,
851                         comp.fLut[row].fA1, comp.fLut[row].fThres, comp.fLut[row].fSat
852                 );
853                 
854                 file << str << endl;
855                 if (file.fail())
856                 {
857                         std::cerr << "ERROR: There was an I/O error when writing to the file: "
858                                 << filename << std::endl;
859                         return false;
860                 }
861         }
862         
863         return true;
864 }