89b814de3997d739dec43431b162a0836bf712d6
[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  *   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   AliHLTMUONHitReconstructorComponent.cxx
22 ///  @author Indranil Das <indra.das@saha.ac.in> | <indra.ehep@gmail.com>, Artur Szostak <artursz@iafrica.com>
23 ///  @date   28 May 2007
24 ///  @brief  Implementation of the hit Reconstruction processing component.
25 ///
26 ///  The HitRec Component is designed to deal the rawdata inputfiles to findout the 
27 ///  the reconstructed hits. The output is send to the output block for further 
28 ///  processing.
29 ///
30 ///  Author : Indranil Das ( indra.das@saha.ac.in || indra.ehep@gmail.com )
31 ///
32
33 #include "AliHLTMUONRecHitsBlockStruct.h"
34 #include "AliHLTMUONHitReconstructorComponent.h"
35 #include "AliHLTMUONHitReconstructor.h"
36 #include "AliHLTMUONConstants.h"
37 #include "AliHLTMUONUtils.h"
38 #include "AliHLTMUONDataBlockWriter.h"
39 #include "AliHLTMUONHitReconstructor.h"
40 #include "AliHLTLogging.h"
41 #include "AliHLTSystem.h"
42 #include "AliHLTDefinitions.h"
43 #include <cstdlib>
44 #include <cerrno>
45 #include <cassert>
46 #include <fstream>
47
48 #include "TMap.h"
49
50 //STEER
51 #include "AliCDBManager.h"
52 #include "AliGeomManager.h"
53
54 //MUON
55 #include "AliMUONGeometryTransformer.h"
56 #include "AliMUONCalibrationData.h"
57 #include "AliMUONVCalibParam.h"
58
59 //MUON/mapping
60 #include "AliMpCDB.h"
61 #include "AliMpPad.h"
62 #include "AliMpSegmentation.h"
63 #include "AliMpDDLStore.h"
64 #include "AliMpDEIterator.h"
65 #include "AliMpVSegmentation.h"
66 #include "AliMpDEManager.h"
67 #include "AliMpDetElement.h"
68
69 ClassImp(AliHLTMUONHitReconstructorComponent)
70
71
72 AliHLTMUONHitReconstructorComponent::AliHLTMUONHitReconstructorComponent() :
73         AliHLTMUONProcessor(),
74         fHitRec(NULL),
75         fDDL(-1),
76         fLutSize(0),
77         fLut(NULL),
78         fIdToEntry(),
79         fWarnForUnexpecedBlock(false),
80         fDelaySetup(false)
81 {
82         ///
83         /// Default constructor.
84         ///
85 }
86
87
88 AliHLTMUONHitReconstructorComponent::~AliHLTMUONHitReconstructorComponent()
89 {
90         ///
91         /// Default destructor.
92         ///
93         
94         if (fHitRec != NULL)
95         {
96                 delete fHitRec;
97         }
98         if (fLut != NULL)
99         {
100                 delete [] fLut;
101         }
102 }
103
104 const char* AliHLTMUONHitReconstructorComponent::GetComponentID()
105 {
106         ///
107         /// Inherited from AliHLTComponent. Returns the component ID.
108         ///
109         
110         return AliHLTMUONConstants::HitReconstructorId();
111 }
112
113
114 void AliHLTMUONHitReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
115 {
116         ///
117         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
118         ///
119         
120         list.clear();
121         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
122 }
123
124
125 AliHLTComponentDataType AliHLTMUONHitReconstructorComponent::GetOutputDataType()
126 {
127         ///
128         /// Inherited from AliHLTComponent. Returns the output data type.
129         ///
130         
131         return AliHLTMUONConstants::RecHitsBlockDataType();
132 }
133
134
135 void AliHLTMUONHitReconstructorComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
136 {
137         ///
138         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
139         ///
140         
141         constBase = sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType);
142         inputMultiplier = 1;
143 }
144
145
146 AliHLTComponent* AliHLTMUONHitReconstructorComponent::Spawn()
147 {
148         ///
149         /// Inherited from AliHLTComponent. Creates a new object instance.
150         ///
151         
152         return new AliHLTMUONHitReconstructorComponent;
153 }
154
155
156 int AliHLTMUONHitReconstructorComponent::DoInit(int argc, const char** argv)
157 {
158         ///
159         /// Inherited from AliHLTComponent.
160         /// Parses the command line parameters and initialises the component.
161         ///
162
163         HLTInfo("Initialising dHLT hit reconstruction component.");
164         
165         // Must make sure that fHitRec and fLut is deleted if it is still
166         // allocated for whatever reason.
167         FreeMemory();
168         
169         try
170         {
171                 fHitRec = new AliHLTMUONHitReconstructor();
172         }
173         catch (const std::bad_alloc&)
174         {
175                 HLTError("Could not allocate more memory for the hit reconstructor component.");
176                 return -ENOMEM;
177         }
178         
179         // Initialise fields with default values then parse the command line.
180         fDDL = -1;
181         fIdToEntry.clear();
182         fWarnForUnexpecedBlock = false;
183         fDelaySetup = false;
184         
185         const char* lutFileName = NULL;
186         const char* cdbPath = NULL;
187         Int_t run = -1;
188         bool useCDB = false;
189         bool tryRecover = false;
190         AliHLTInt32_t dccut = -1;
191         
192         for (int i = 0; i < argc; i++)
193         {
194                 HLTDebug("argv[%d] == %s", i, argv[i]);
195                 
196                 if (strcmp( argv[i], "-ddl" ) == 0)
197                 {
198                         if (fDDL != -1)
199                         {
200                                 HLTWarning("DDL number was already specified."
201                                         " Will replace previous value given by -ddl or -ddlid."
202                                 );
203                         }
204                         
205                         if (argc <= i+1)
206                         {
207                                 HLTError("The DDL number was not specified. Must be in the range [13..20].");
208                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
209                                 return -EINVAL;
210                         }
211                         
212                         char* cpErr = NULL;
213                         unsigned long num = strtoul( argv[i+1], &cpErr, 0 );
214                         if (cpErr == NULL or *cpErr != '\0')
215                         {
216                                 HLTError("Cannot convert '%s' to DDL a number.", argv[i+1] );
217                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
218                                 return -EINVAL;
219                         }
220                         if (num < 13 or 20 < num)
221                         {
222                                 HLTError("The DDL number must be in the range [13..20].");
223                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
224                                 return -EINVAL;
225                         }
226                         fDDL = num - 1;  // convert to range [12..19]
227                         
228                         i++;
229                         continue;
230                 } // -ddl argument
231                 
232                 if (strcmp( argv[i], "-ddlid" ) == 0)
233                 {
234                         if (fDDL != -1)
235                         {
236                                 HLTWarning("DDL number was already specified."
237                                         " Will replace previous value given by -ddl or -ddlid."
238                                 );
239                         }
240                         
241                         if ( argc <= i+1 )
242                         {
243                                 HLTError("DDL equipment ID number not specified. It must be in the range [2572..2579]" );
244                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
245                                 return -EINVAL;
246                         }
247                 
248                         char* cpErr = NULL;
249                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
250                         if (cpErr == NULL or *cpErr != '\0')
251                         {
252                                 HLTError("Cannot convert '%s' to a DDL equipment ID Number.", argv[i+1]);
253                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
254                                 return -EINVAL;
255                         }
256                         fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
257                         if (fDDL < 12 or 19 < fDDL)
258                         {
259                                 HLTError("The DDL equipment ID number must be in the range [2572..2579].");
260                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
261                                 return -EINVAL;
262                         }
263                         
264                         i++;
265                         continue;
266                 }
267                 
268                 if (strcmp( argv[i], "-lut" ) == 0)
269                 {
270                         if (lutFileName != NULL)
271                         {
272                                 HLTWarning("LUT path was already specified."
273                                         " Will replace previous value given by -lut."
274                                 );
275                         }
276                         
277                         if (argc <= i+1)
278                         {
279                                 HLTError("The lookup table filename was not specified.");
280                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
281                                 return -EINVAL;
282                         }
283                         lutFileName = argv[i+1];
284                         i++;
285                         continue;
286                 } // -lut argument
287                 
288                 if (strcmp( argv[i], "-cdb" ) == 0)
289                 {
290                         useCDB = true;
291                         continue;
292                 } // -cdb argument
293                 
294                 if (strcmp( argv[i], "-cdbpath" ) == 0)
295                 {
296                         if (cdbPath != NULL)
297                         {
298                                 HLTWarning("CDB path was already specified."
299                                         " Will replace previous value given by -cdbpath."
300                                 );
301                         }
302                         
303                         if ( argc <= i+1 )
304                         {
305                                 HLTError("The CDB path was not specified." );
306                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
307                                 return -EINVAL;
308                         }
309                         cdbPath = argv[i+1];
310                         useCDB = true;
311                         i++;
312                         continue;
313                 } // -cdb argument
314         
315                 if (strcmp( argv[i], "-run" ) == 0)
316                 {
317                         if (run != -1)
318                         {
319                                 HLTWarning("Run number was already specified."
320                                         " Will replace previous value given by -run."
321                                 );
322                         }
323                         
324                         if ( argc <= i+1 )
325                         {
326                                 HLTError("The run number was not specified." );
327                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
328                                 return -EINVAL;
329                         }
330                         
331                         char* cpErr = NULL;
332                         run = Int_t( strtol(argv[i+1], &cpErr, 0) );
333                         if (cpErr == NULL or *cpErr != '\0' or run < 0)
334                         {
335                                 HLTError("Cannot convert '%s' to a valid run number."
336                                         " Expected a positive integer value.", argv[i+1]
337                                 );
338                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
339                                 return -EINVAL;
340                         }
341                         
342                         i++;
343                         continue;
344                 } // -run argument
345         
346                 if (strcmp( argv[i], "-dccut" ) == 0)
347                 {
348                         if (dccut != -1)
349                         {
350                                 HLTWarning("DC cut parameter was already specified."
351                                         " Will replace previous value given by -dccut."
352                                 );
353                         }
354                         
355                         if ( argc <= i+1 )
356                         {
357                                 HLTError("No DC cut value was specified. It should be a positive integer value." );
358                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
359                                 return -EINVAL;
360                         }
361                         
362                         char* cpErr = NULL;
363                         dccut = AliHLTInt32_t( strtol(argv[i+1], &cpErr, 0) );
364                         if (cpErr == NULL or *cpErr != '\0' or dccut < 0)
365                         {
366                                 HLTError("Cannot convert '%s' to a valid DC cut value."
367                                         " Expected a positive integer value.", argv[i+1]
368                                 );
369                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
370                                 return -EINVAL;
371                         }
372                         
373                         i++;
374                         continue;
375                 }
376                 
377                 if (strcmp( argv[i], "-delaysetup" ) == 0)
378                 {
379                         fDelaySetup = true;
380                         continue;
381                 }
382                 
383                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
384                 {
385                         fWarnForUnexpecedBlock = true;
386                         continue;
387                 }
388                 
389                 if (strcmp( argv[i], "-tryrecover" ) == 0)
390                 {
391                         tryRecover = true;
392                         continue;
393                 }
394         
395                 HLTError("Unknown option '%s'", argv[i]);
396                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
397                 return -EINVAL;
398         
399         } // for loop
400         
401         if (dccut != -1 and useCDB)
402         {
403                 HLTWarning("The -cdb or -cdbpath parameter was specified, which indicates that"
404                         " this component should read from the CDB, but then the -dccut argument"
405                         " was also used. Will override the value from CDB with the command"
406                         " line DC cut parameter given."
407                 );
408         }
409         
410         if (lutFileName != NULL and useCDB == true)
411         {
412                 HLTWarning("The -cdb or -cdbpath parameter was specified, which indicates that"
413                         " this component should read from the CDB, but then the -lut argument"
414                         " was also used. Will ignore the -lut option and load from CDB anyway."
415                 );
416         }
417         
418         if (lutFileName == NULL) useCDB = true;
419         
420         if (fDDL == -1 and not fDelaySetup)
421         {
422                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
423         }
424         
425         if (cdbPath != NULL or run != -1)
426         {
427                 int result = SetCDBPathAndRunNo(cdbPath, run);
428                 if (result != 0)
429                 {
430                         // Error messages already generated in SetCDBPathAndRunNo.
431                         FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
432                         return result;
433                 }
434         }
435         
436         if (useCDB)
437         {
438                 if (not fDelaySetup)
439                 {
440                         HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
441                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
442                         );
443                         int result = ReadLutFromCDB();
444                         if (result != 0)
445                         {
446                                 // Error messages already generated in ReadLutFromCDB.
447                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
448                                 return result;
449                         }
450                         fHitRec->SetLookUpTable(fLut, &fIdToEntry);
451                 }
452         }
453         else
454         {
455                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
456                 int result = ReadLookUpTable(lutFileName);
457                 if (result != 0)
458                 {
459                         // Error messages already generated in ReadLookUpTable.
460                         FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
461                         return result;
462                 }
463                 fHitRec->SetLookUpTable(fLut, &fIdToEntry);
464         }
465         
466         if (dccut == -1)
467         {
468                 if (not fDelaySetup)
469                 {
470                         HLTInfo("Loading DC cut parameters from CDB for DDL %d (ID = %d).",
471                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
472                         );
473                         int result = ReadDCCutFromCDB();
474                         if (result != 0)
475                         {
476                                 // Error messages already generated in ReadDCCutFromCDB.
477                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
478                                 return result;
479                         }
480                 }
481                 else
482                 {
483                         // Print the debug messages here since ReadDCCutFromCDB does not get called,
484                         // in-which the debug messages would have been printed.
485                         HLTDebug("Using DC cut parameter of %d ADC channels.", fHitRec->GetDCCut());
486                 }
487         }
488         else
489         {
490                 fHitRec->SetDCCut(dccut);
491                 HLTDebug("Using DC cut parameter of %d ADC channels.", fHitRec->GetDCCut());
492         }
493         
494         fHitRec->TryRecover(tryRecover);
495         
496         return 0;
497 }
498
499
500 int AliHLTMUONHitReconstructorComponent::DoDeinit()
501 {
502         ///
503         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
504         ///
505         
506         HLTInfo("Deinitialising dHLT hit reconstruction component.");
507         FreeMemory();
508         return 0;
509 }
510
511
512 int AliHLTMUONHitReconstructorComponent::Reconfigure(
513                 const char* cdbEntry, const char* componentId
514         )
515 {
516         /// Inherited from AliHLTComponent. This method will reload CDB configuration
517         /// entries for this component from the CDB.
518         /// \param cdbEntry If this is NULL then it is assumed that all CDB entries should
519         ///      be reloaded. Otherwise a particular value for 'cdbEntry' will trigger
520         ///      reloading of the LUT if the path contains 'MUON/' and reloading of the DC
521         ///      cut parameter if 'cdbEntry' equals "HLT/ConfigMUON/HitReconstructor".
522         /// \param componentId  The name of the component in the current chain.
523         
524         bool startsWithMUON = TString(cdbEntry).Index("MUON/", 5, 0, TString::kExact) == 0;
525         bool givenConfigPath = strcmp(cdbEntry, AliHLTMUONConstants::HitReconstructorCDBPath()) == 0;
526         
527         if (cdbEntry == NULL or startsWithMUON or givenConfigPath)
528         {
529                 HLTInfo("Reading new configuration entries from CDB for component '%s'.", componentId);
530         }
531                 
532         if (cdbEntry == NULL or startsWithMUON)
533         {
534                 // First clear the current LUT data and then load in the new values.
535                 if (fLut != NULL)
536                 {
537                         delete [] fLut;
538                         fLut = NULL;
539                         fLutSize = 0;
540                 }
541                 
542                 fIdToEntry.clear();
543         
544                 int result = ReadLutFromCDB();
545                 if (result != 0) return result;
546                 fHitRec->SetLookUpTable(fLut, &fIdToEntry);
547         }
548         
549         if (cdbEntry == NULL or not startsWithMUON)
550         {
551                 int result = ReadDCCutFromCDB();
552                 if (result != 0) return result;
553         }
554         
555         return 0;
556 }
557
558
559 int AliHLTMUONHitReconstructorComponent::ReadPreprocessorValues(const char* modules)
560 {
561         /// Inherited from AliHLTComponent. 
562         /// Updates the configuration of this component if either HLT or MUON have
563         /// been specified in the 'modules' list.
564
565         TString mods = modules;
566         if (mods.Contains("ALL") or (mods.Contains("HLT") and mods.Contains("MUON")))
567         {
568                 return Reconfigure(NULL, GetComponentID());
569         }
570         if (mods.Contains("HLT"))
571         {
572                 return Reconfigure(AliHLTMUONConstants::HitReconstructorCDBPath(), GetComponentID());
573         }
574         if (mods.Contains("MUON"))
575         {
576                 return Reconfigure("MUON/*", GetComponentID());
577         }
578         return 0;
579 }
580
581
582 int AliHLTMUONHitReconstructorComponent::DoEvent(
583                 const AliHLTComponentEventData& evtData,
584                 const AliHLTComponentBlockData* blocks,
585                 AliHLTComponentTriggerData& /*trigData*/,
586                 AliHLTUInt8_t* outputPtr,
587                 AliHLTUInt32_t& size,
588                 std::vector<AliHLTComponentBlockData>& outputBlocks
589         )
590 {
591         ///
592         /// Inherited from AliHLTProcessor. Processes the new event data.
593         ///
594         
595         // Initialise the LUT and DC cut parameter from CDB if we were requested
596         // to initialise only when the first event was received.
597         if (fDelaySetup)
598         {
599                 // Use the specification given by the first data block if we
600                 // have not been given a DDL number on the command line.
601                 if (fDDL == -1)
602                 {
603                         bool blockFound = false;
604                         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt and not blockFound; n++)
605                         {
606                                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()) continue;
607                                 blockFound = true;
608
609                                 fDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
610                                 
611                                 if (fDDL == -1)
612                                 {
613                                         HLTError("Received a data block with a specification (0x%8.8X)"
614                                                 " indicating multiple DDL data sources, but we must only"
615                                                 " receive raw DDL data from one tracking station DDL.",
616                                                 blocks[n].fSpecification
617                                         );
618                                         return -EPROTO;
619                                 }
620                         }
621
622                         if (not blockFound)
623                         {
624                                 HLTError("The initialisation from CDB of the component has"
625                                         " been delayed to the first received event. However,"
626                                         " no raw DDL data blocks have been found in the first event."
627                                 );
628                                 return -ENOENT;
629                         }
630                 }
631                 
632                 // Check that the LUT was not already loaded in DoInit.
633                 if (fLut == NULL)
634                 {
635                         HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
636                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
637                         );
638                         int result = ReadLutFromCDB();
639                         if (result != 0) return result;
640                         
641                         fHitRec->SetLookUpTable(fLut, &fIdToEntry);
642                 }
643                 
644                 // Check that the DC cut was not already loaded in DoInit.
645                 if (fHitRec->GetDCCut() == -1)
646                 {
647                         HLTInfo("Loading DC cut parameters from CDB for DDL %d (ID = %d).",
648                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
649                         );
650                         int result = ReadDCCutFromCDB();
651                         if (result != 0) return result;
652                 }
653                 
654                 fDelaySetup = false;
655         }
656         
657         if (fLut == NULL)
658         {
659                 HLTFatal("Lookup table not loaded! Cannot continue processing data.");
660                 return -ENOENT;
661         }
662         
663         // Process an event
664         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
665
666         HLTDebug("Processing event %llu with %u input data blocks.",
667                 evtData.fEventID, evtData.fBlockCnt
668         );
669
670         // Loop over all input blocks in the event
671         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
672         {
673                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
674                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
675                 );
676
677                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
678                     or not AliHLTMUONUtils::IsTrackerDDL(blocks[n].fSpecification)
679                    )
680                 {
681                         // Log a message indicating that we got a data block that we
682                         // do not know how to handle.
683                         if (fWarnForUnexpecedBlock)
684                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
685                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
686                                 );
687                         else
688                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
689                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
690                                 );
691                         
692                         continue;
693                 }
694                 
695                 if (fDDL != -1)
696                 {
697                         AliHLTInt32_t receivedDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
698                         if (receivedDDL != fDDL)
699                         {
700                                 HLTWarning("Received raw data from DDL %d (ID = %d),"
701                                         " but expect data only from DDL %d (ID = %d).",
702                                         receivedDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(receivedDDL),
703                                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
704                                 );
705                         }
706                 }
707                 
708                 // Create a new output data block and initialise the header.
709                 AliHLTMUONRecHitsBlockWriter block(outputPtr+totalSize, size-totalSize);
710                 if (not block.InitCommonHeader())
711                 {
712                         HLTError("There is not enough space in the output buffer for the new data block."
713                                  " We require at least %u bytes, but have %u bytes left.",
714                                 sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
715                                 block.BufferSize()
716                         );
717                         break;
718                 }
719                 
720                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize / sizeof(AliHLTUInt32_t);
721                 AliHLTUInt32_t ddlRawDataSize = totalDDLSize - fHitRec->GetkDDLHeaderSize();
722                 AliHLTUInt32_t* buffer = reinterpret_cast<AliHLTUInt32_t*>(
723                                 reinterpret_cast<char*>(blocks[n].fPtr) + blocks[n].fOffset
724                         ) + fHitRec->GetkDDLHeaderSize();
725                 AliHLTUInt32_t nofHit = block.MaxNumberOfEntries();
726
727 #ifdef DEBUG
728                 HLTDebug("=========== Dumping DDL payload buffer ==========");
729                 for (AliHLTUInt32_t j = 0; j < totalDDLSize; j++)
730                         HLTDebug("buffer[%d] : %x",j,buffer[j]);
731                 HLTDebug("================== End of dump =================");
732 #endif // DEBUG
733
734                 if (not fHitRec->Run(buffer, ddlRawDataSize, block.GetArray(), nofHit))
735                 {
736                         HLTError("Error while processing the hit reconstruction algorithm.");
737                         size = totalSize; // Must tell the framework how much buffer space was used.
738                         return -EIO;
739                 }
740                 
741                 // nofHit should now contain the number of reconstructed hits actually found
742                 // and filled into the output data block, so we can set this number.
743                 assert( nofHit <= block.MaxNumberOfEntries() );
744                 block.SetNumberOfEntries(nofHit);
745                 
746                 HLTDebug("Number of reconstructed hits found is %d", nofHit);
747
748                 // Fill a block data structure for our output block.
749                 AliHLTComponentBlockData bd;
750                 FillBlockData(bd);
751                 bd.fPtr = outputPtr;
752                 // This block's start (offset) is after all other blocks written so far.
753                 bd.fOffset = totalSize;
754                 bd.fSize = block.BytesUsed();
755                 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
756                 bd.fSpecification = blocks[n].fSpecification;
757                 outputBlocks.push_back(bd);
758
759                 // Increase the total amount of data written so far to our output memory
760                 totalSize += block.BytesUsed();
761         }
762         // Finally we set the total size of output memory we consumed.
763         size = totalSize;
764
765         return 0;
766 }
767
768
769 void AliHLTMUONHitReconstructorComponent::FreeMemory()
770 {
771         /// Deletes any allocated objects if they are allocated else nothing is
772         /// done for objects not yet allocated.
773         /// This is used as a helper method to make sure the corresponding pointers
774         /// are NULL and we get back to a well defined state.
775
776         if (fHitRec != NULL)
777         {
778                 delete fHitRec;
779                 fHitRec = NULL;
780         }
781         if (fLut != NULL)
782         {
783                 delete [] fLut;
784                 fLut = NULL;
785                 fLutSize = 0;
786         }
787         
788         fIdToEntry.clear();
789 }
790
791
792 int AliHLTMUONHitReconstructorComponent::ReadLookUpTable(const char* lutFileName)
793 {
794         /// Read in the lookup table from a text file.
795         /// Note that this method could leave fLut allocated which is cleaned up
796         /// by DoInit with a call to FreeMemory().
797         
798         assert( fLut == NULL );
799         assert( fLutSize == 0 );
800         assert( fIdToEntry.empty() );
801         
802         std::ifstream file(lutFileName);
803         if (not file.good())
804         {
805                 HLTError("Could not open the LUT file %s", lutFileName);
806                 return -ENOENT;
807         }
808         
809         // First count the number of lines of text in the LUT file before decoding.
810         // This is not the most optimal. It would be better to read and decode at the
811         // same time but we are not allowed to use STL and ROOT containers are too
812         // heavy for this task. At least this is done only at the start of run.
813         std::string str;
814         AliHLTUInt32_t lineCount = 0;
815         while (std::getline(file, str)) lineCount++;
816         if (not file.eof())
817         {
818                 HLTError("There was a problem reading the LUT file %s", lutFileName);
819                 return -EIO;
820         }
821         if (lineCount == 0)
822         {
823                 HLTWarning("The LUT file %s was empty.", lutFileName);
824         }
825         
826         // Add one extra LUT line for the first element which is used as a sentinel value.
827         lineCount++;
828         
829         try
830         {
831                 fLut = new AliHLTMUONHitRecoLutRow[lineCount];
832                 fLutSize = lineCount;
833         }
834         catch (const std::bad_alloc&)
835         {
836                 HLTError("Could not allocate more memory for the lookuptable.");
837                 return -ENOMEM;
838         }
839         
840         // Initialise the sentinel value.
841         fLut[0].fDetElemId = 0;
842         fLut[0].fIX = 0;
843         fLut[0].fIY = 0;
844         fLut[0].fRealX = 0.0;
845         fLut[0].fRealY = 0.0;
846         fLut[0].fRealZ = 0.0;
847         fLut[0].fHalfPadSize = 0.0;
848         fLut[0].fPlane = -1;
849         fLut[0].fPed = -1;
850         fLut[0].fSigma = -1;
851         fLut[0].fA0 = -1;
852         fLut[0].fA1 = -1;
853         fLut[0].fThres = -1;
854         fLut[0].fSat = -1;
855         
856         // Clear the eof flag and start reading from the beginning of the file again.
857         file.clear();
858         file.seekg(0, std::ios::beg);
859         if (not file.good())
860         {
861                 HLTError("There was a problem seeking in the LUT file %s", lutFileName);
862                 return -EIO;
863         }
864         
865         AliHLTInt32_t idManuChannel;
866         for (AliHLTUInt32_t i = 1; i < fLutSize; i++)
867         {
868                 if (std::getline(file, str).fail())
869                 {
870                         HLTError("There was a problem reading line %d of LUT file %s", i, lutFileName);
871                         return -EIO;
872                 }
873                 
874                 int result = sscanf(
875                         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",
876                         &idManuChannel, &fLut[i].fDetElemId, &fLut[i].fIX,
877                         &fLut[i].fIY, &fLut[i].fRealX,
878                         &fLut[i].fRealY, &fLut[i].fRealZ,
879                         &fLut[i].fHalfPadSize, &fLut[i].fPlane,
880                         &fLut[i].fPed, &fLut[i].fSigma, &fLut[i].fA0,
881                         &fLut[i].fA1, &fLut[i].fThres, &fLut[i].fSat
882                 );
883                 
884                 if (result != 15)
885                 {
886                         HLTError("Line %d in LUT file %s does not contain 15 elements.", i, lutFileName);
887                         return -EIO;
888                 }
889                 
890                 fIdToEntry[idManuChannel] = i;
891         }
892         
893         return 0;
894 }
895
896
897 int AliHLTMUONHitReconstructorComponent::ReadLutFromCDB()
898 {
899         /// Reads LUT from CDB.
900         /// To override the default CDB path and / or run number the
901         /// SetCDBPathAndRunNo(cdbPath, run) method should be called before this
902         /// method.
903
904         assert( fLut == NULL );
905         assert( fLutSize == 0 );
906         assert( fIdToEntry.empty() );
907         
908         if (fDDL == -1)
909         {
910                 HLTError("No DDL number specified for which to load LUT data from CDB.");
911                 return -EINVAL;
912         }
913         
914         std::vector<AliHLTMUONHitRecoLutRow> lutList;
915         AliHLTMUONHitRecoLutRow lut;
916         AliHLTUInt32_t iEntry = 0;
917         
918         int result = FetchMappingStores();
919         // Error message already generated in FetchMappingStores.
920         if (result != 0) return result;
921         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
922         
923         AliMpSegmentation* mpSegFactory = AliMpSegmentation::Instance();
924         if (mpSegFactory == NULL)
925         {
926                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
927                 return -EIO;
928         }
929         
930         // Only load geometry if not already loaded.
931         if (AliGeomManager::GetGeometry() == NULL)
932         {
933                 AliGeomManager::LoadGeometry();
934         }
935         AliMUONGeometryTransformer chamberGeometryTransformer;
936         if (not chamberGeometryTransformer.LoadGeometryData())
937         {
938                 HLTError("Failed to load geomerty data.");
939                 return -ENOENT;
940         }
941         
942         AliMUONCalibrationData calibData(AliCDBManager::Instance()->GetRun());
943         
944         Int_t chamberId;
945         
946         for(Int_t iCh = 6; iCh < 10; iCh++)
947         {
948                 chamberId = iCh;
949                 
950                 AliMpDEIterator it;
951                 for ( it.First(chamberId); ! it.IsDone(); it.Next() )
952                 {
953                         Int_t detElemId = it.CurrentDEId();
954                         int iDDL = ddlStore->GetDetElement(detElemId)->GetDdlId();
955                         if (iDDL != fDDL) continue;
956                 
957                         for (Int_t iCath = 0 ; iCath <= 1 ; iCath++)
958                         {
959                                 AliMp::CathodType cath;
960                                 
961                                 if(iCath == 0)
962                                         cath = AliMp::kCath0;
963                                 else
964                                         cath = AliMp::kCath1;
965                                 
966                                 const AliMpVSegmentation* seg = mpSegFactory->GetMpSegmentation(detElemId, cath);
967                                 AliMp::PlaneType plane = seg->PlaneType();
968                                 Int_t maxIX = seg->MaxPadIndexX();
969                                 Int_t maxIY = seg->MaxPadIndexY();
970                                 
971                                 Int_t idManuChannel, manuId, channelId, buspatchId;
972                                 AliHLTFloat32_t padSizeX, padSizeY;
973                                 AliHLTFloat32_t halfPadSize;
974                                 Double_t realX, realY, realZ;
975                                 Double_t localX, localY, localZ;
976                                 Float_t calibA0Coeff,calibA1Coeff,pedestal,sigma;
977                                 Int_t thresold,saturation;
978                                 
979                                 // Pad Info of a slat to print in lookuptable
980                                 for (Int_t iX = 0; iX<= maxIX ; iX++)
981                                 for (Int_t iY = 0; iY<= maxIY ; iY++)
982                                 {
983                                         if (not seg->HasPad(AliMpIntPair(iX,iY))) continue;
984
985                                         AliMpPad pad = seg->PadByIndices(AliMpIntPair(iX,iY), kFALSE);
986                                         
987                                         // Getting Manu id
988                                         manuId = pad.GetLocation().GetFirst();
989                                         manuId &= 0x7FF; // 11 bits 
990                         
991                                         buspatchId = ddlStore->GetBusPatchId(detElemId,manuId);
992                                         
993                                         // Getting channel id
994                                         channelId =  pad.GetLocation().GetSecond();
995                                         channelId &= 0x3F; // 6 bits
996                                         
997                                         idManuChannel = buspatchId << 11;
998                                         idManuChannel = (idManuChannel | manuId) << 6;
999                                         idManuChannel |= channelId;
1000                                         
1001                                         localX = pad.Position().X();
1002                                         localY = pad.Position().Y();
1003                                         localZ = 0.0;
1004                                         
1005                                         chamberGeometryTransformer.Local2Global(
1006                                                 detElemId,localX,localY,localZ,
1007                                                 realX,realY,realZ
1008                                         );
1009                                         
1010                                         padSizeX = pad.Dimensions().X();
1011                                         padSizeY = pad.Dimensions().Y();
1012                                         
1013                                         calibA0Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 0);
1014                                         calibA1Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 1);
1015                                         thresold = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 2);
1016                                         saturation = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 4);
1017                                         
1018                                         pedestal = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 0);
1019                                         sigma = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 1);
1020                                         
1021                                         if (plane == 0)
1022                                                 halfPadSize = padSizeX;
1023                                         else
1024                                                 halfPadSize = padSizeY;
1025                                         
1026                                         fIdToEntry[idManuChannel] = iEntry+1;
1027                         
1028                                         lut.fDetElemId = detElemId;
1029                                         lut.fIX = iX;
1030                                         lut.fIY = iY;
1031                                         lut.fRealX = realX;
1032                                         lut.fRealY = realY;
1033                                         lut.fRealZ = realZ;
1034                                         lut.fHalfPadSize = halfPadSize;
1035                                         lut.fPlane = plane;
1036                                         lut.fPed = pedestal;
1037                                         lut.fSigma = sigma;
1038                                         lut.fA0 = calibA0Coeff;
1039                                         lut.fA1 = calibA1Coeff;
1040                                         lut.fThres = thresold;
1041                                         lut.fSat = saturation;
1042                                         
1043                                         lutList.push_back(lut);
1044                                         iEntry++;
1045                                 } // iX, iY loop
1046                         } // iCath loop
1047                 } // detElemId loop
1048         } // ichamber loop
1049
1050         try
1051         {
1052                 // Use iEntry+1 since we add one extra LUT line for the first element
1053                 // which is used as a sentinel value.
1054                 fLut = new AliHLTMUONHitRecoLutRow[iEntry+1];
1055                 fLutSize = iEntry+1;
1056         }
1057         catch (const std::bad_alloc&)
1058         {
1059                 HLTError("Could not allocate more memory for the lookuptable.");
1060                 return -ENOMEM;
1061         }
1062         
1063         // Initialise the sentinel value.
1064         fLut[0].fDetElemId = 0;
1065         fLut[0].fIX = 0;
1066         fLut[0].fIY = 0;
1067         fLut[0].fRealX = 0.0;
1068         fLut[0].fRealY = 0.0;
1069         fLut[0].fRealZ = 0.0;
1070         fLut[0].fHalfPadSize = 0.0;
1071         fLut[0].fPlane = -1;
1072         fLut[0].fPed = -1;
1073         fLut[0].fSigma = -1;
1074         fLut[0].fA0 = -1;
1075         fLut[0].fA1 = -1;
1076         fLut[0].fThres = -1;
1077         fLut[0].fSat = -1;
1078         
1079         for (AliHLTUInt32_t i = 0; i < iEntry; i++)
1080                 fLut[i+1] = lutList[i];
1081         
1082         return 0;
1083 }
1084
1085
1086 int AliHLTMUONHitReconstructorComponent::ReadDCCutFromCDB()
1087 {
1088         /// Reads the DC cut parameter from the CDB.
1089
1090         const char* pathToEntry = AliHLTMUONConstants::HitReconstructorCDBPath();
1091         
1092         TMap* map = NULL;
1093         int result = FetchTMapFromCDB(pathToEntry, map);
1094         if (result != 0) return result;
1095         
1096         Int_t value = 0;
1097         result = GetPositiveIntFromTMap(map, "dccut", value, pathToEntry, "DC cut");
1098         if (result != 0) return result;
1099         
1100         assert(fHitRec != NULL);
1101         fHitRec->SetDCCut(value);
1102         
1103         HLTDebug("Using DC cut parameter of %d ADC channels.", fHitRec->GetDCCut());
1104         
1105         return 0;
1106 }
1107
1108
1109 bool AliHLTMUONHitReconstructorComponent::GenerateLookupTable(
1110                 AliHLTInt32_t ddl, const char* filename,
1111                 const char* cdbPath, Int_t run
1112         )
1113 {
1114         /// Generates a ASCII text file containing the lookup table (LUT) from
1115         /// the CDB, which can be used for the hit reconstructor component later.
1116         /// @param ddl  Must be the DDL for which to generate the DDL,
1117         ///             in the range [13..20].
1118         /// @param filename  The name of the LUT file to generate.
1119         /// @param cdbPath  The CDB path to use.
1120         /// @param run  The run number to use for the CDB.
1121         /// @return  True if the generation of the LUT file succeeded.
1122         
1123         AliHLTMUONHitReconstructorComponent comp;
1124         
1125         if (ddl < 12 or 19 < ddl)
1126         {
1127                 std::cerr << "ERROR: the DDL number must be in the range [12..19]." << std::endl;
1128                 return false;
1129         }
1130         
1131         comp.fDDL = ddl;
1132         if (comp.SetCDBPathAndRunNo(cdbPath, run) != 0) return false;
1133         if (comp.ReadLutFromCDB() != 0) return false;
1134         
1135         char str[1024*4];
1136         std::fstream file(filename, std::ios::out);
1137         if (not file)
1138         {
1139                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
1140                 return false;
1141         }
1142         
1143         assert( comp.fLut != NULL );
1144         
1145         for (IdManuChannelToEntry::iterator id = comp.fIdToEntry.begin();
1146              id != comp.fIdToEntry.end();
1147              id++
1148             )
1149         {
1150                 AliHLTInt32_t idManuChannel = id->first;
1151                 AliHLTInt32_t row = id->second;
1152                 
1153                 assert( AliHLTUInt32_t(row) < comp.fLutSize );
1154                 
1155                 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",
1156                         idManuChannel, comp.fLut[row].fDetElemId, comp.fLut[row].fIX,
1157                         comp.fLut[row].fIY, comp.fLut[row].fRealX,
1158                         comp.fLut[row].fRealY, comp.fLut[row].fRealZ,
1159                         comp.fLut[row].fHalfPadSize, comp.fLut[row].fPlane,
1160                         comp.fLut[row].fPed, comp.fLut[row].fSigma, comp.fLut[row].fA0,
1161                         comp.fLut[row].fA1, comp.fLut[row].fThres, comp.fLut[row].fSat
1162                 );
1163                 
1164                 file << str << endl;
1165                 if (file.fail())
1166                 {
1167                         std::cerr << "ERROR: There was an I/O error when writing to the file: "
1168                                 << filename << std::endl;
1169                         return false;
1170                 }
1171         }
1172         
1173         return true;
1174 }