Fixing treatment of fOffset value in input data blocks.
[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*>(blocks[n].fPtr)
723                         + fHitRec->GetkDDLHeaderSize();
724                 AliHLTUInt32_t nofHit = block.MaxNumberOfEntries();
725
726 #ifdef DEBUG
727                 HLTDebug("=========== Dumping DDL payload buffer ==========");
728                 for (AliHLTUInt32_t j = 0; j < totalDDLSize; j++)
729                         HLTDebug("buffer[%d] : %x",j,buffer[j]);
730                 HLTDebug("================== End of dump =================");
731 #endif // DEBUG
732
733                 if (not fHitRec->Run(buffer, ddlRawDataSize, block.GetArray(), nofHit))
734                 {
735                         HLTError("Error while processing the hit reconstruction algorithm.");
736                         size = totalSize; // Must tell the framework how much buffer space was used.
737                         return -EIO;
738                 }
739                 
740                 // nofHit should now contain the number of reconstructed hits actually found
741                 // and filled into the output data block, so we can set this number.
742                 assert( nofHit <= block.MaxNumberOfEntries() );
743                 block.SetNumberOfEntries(nofHit);
744                 
745                 HLTDebug("Number of reconstructed hits found is %d", nofHit);
746
747                 // Fill a block data structure for our output block.
748                 AliHLTComponentBlockData bd;
749                 FillBlockData(bd);
750                 bd.fPtr = outputPtr;
751                 // This block's start (offset) is after all other blocks written so far.
752                 bd.fOffset = totalSize;
753                 bd.fSize = block.BytesUsed();
754                 bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
755                 bd.fSpecification = blocks[n].fSpecification;
756                 outputBlocks.push_back(bd);
757
758                 // Increase the total amount of data written so far to our output memory
759                 totalSize += block.BytesUsed();
760         }
761         // Finally we set the total size of output memory we consumed.
762         size = totalSize;
763
764         return 0;
765 }
766
767
768 void AliHLTMUONHitReconstructorComponent::FreeMemory()
769 {
770         /// Deletes any allocated objects if they are allocated else nothing is
771         /// done for objects not yet allocated.
772         /// This is used as a helper method to make sure the corresponding pointers
773         /// are NULL and we get back to a well defined state.
774
775         if (fHitRec != NULL)
776         {
777                 delete fHitRec;
778                 fHitRec = NULL;
779         }
780         if (fLut != NULL)
781         {
782                 delete [] fLut;
783                 fLut = NULL;
784                 fLutSize = 0;
785         }
786         
787         fIdToEntry.clear();
788 }
789
790
791 int AliHLTMUONHitReconstructorComponent::ReadLookUpTable(const char* lutFileName)
792 {
793         /// Read in the lookup table from a text file.
794         /// Note that this method could leave fLut allocated which is cleaned up
795         /// by DoInit with a call to FreeMemory().
796         
797         assert( fLut == NULL );
798         assert( fLutSize == 0 );
799         assert( fIdToEntry.empty() );
800         
801         std::ifstream file(lutFileName);
802         if (not file.good())
803         {
804                 HLTError("Could not open the LUT file %s", lutFileName);
805                 return -ENOENT;
806         }
807         
808         // First count the number of lines of text in the LUT file before decoding.
809         // This is not the most optimal. It would be better to read and decode at the
810         // same time but we are not allowed to use STL and ROOT containers are too
811         // heavy for this task. At least this is done only at the start of run.
812         std::string str;
813         AliHLTUInt32_t lineCount = 0;
814         while (std::getline(file, str)) lineCount++;
815         if (not file.eof())
816         {
817                 HLTError("There was a problem reading the LUT file %s", lutFileName);
818                 return -EIO;
819         }
820         if (lineCount == 0)
821         {
822                 HLTWarning("The LUT file %s was empty.", lutFileName);
823         }
824         
825         // Add one extra LUT line for the first element which is used as a sentinel value.
826         lineCount++;
827         
828         try
829         {
830                 fLut = new AliHLTMUONHitRecoLutRow[lineCount];
831                 fLutSize = lineCount;
832         }
833         catch (const std::bad_alloc&)
834         {
835                 HLTError("Could not allocate more memory for the lookuptable.");
836                 return -ENOMEM;
837         }
838         
839         // Initialise the sentinel value.
840         fLut[0].fDetElemId = 0;
841         fLut[0].fIX = 0;
842         fLut[0].fIY = 0;
843         fLut[0].fRealX = 0.0;
844         fLut[0].fRealY = 0.0;
845         fLut[0].fRealZ = 0.0;
846         fLut[0].fHalfPadSize = 0.0;
847         fLut[0].fPlane = -1;
848         fLut[0].fPed = -1;
849         fLut[0].fSigma = -1;
850         fLut[0].fA0 = -1;
851         fLut[0].fA1 = -1;
852         fLut[0].fThres = -1;
853         fLut[0].fSat = -1;
854         
855         // Clear the eof flag and start reading from the beginning of the file again.
856         file.clear();
857         file.seekg(0, std::ios::beg);
858         if (not file.good())
859         {
860                 HLTError("There was a problem seeking in the LUT file %s", lutFileName);
861                 return -EIO;
862         }
863         
864         AliHLTInt32_t idManuChannel;
865         for (AliHLTUInt32_t i = 1; i < fLutSize; i++)
866         {
867                 if (std::getline(file, str).fail())
868                 {
869                         HLTError("There was a problem reading line %d of LUT file %s", i, lutFileName);
870                         return -EIO;
871                 }
872                 
873                 int result = sscanf(
874                         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",
875                         &idManuChannel, &fLut[i].fDetElemId, &fLut[i].fIX,
876                         &fLut[i].fIY, &fLut[i].fRealX,
877                         &fLut[i].fRealY, &fLut[i].fRealZ,
878                         &fLut[i].fHalfPadSize, &fLut[i].fPlane,
879                         &fLut[i].fPed, &fLut[i].fSigma, &fLut[i].fA0,
880                         &fLut[i].fA1, &fLut[i].fThres, &fLut[i].fSat
881                 );
882                 
883                 if (result != 15)
884                 {
885                         HLTError("Line %d in LUT file %s does not contain 15 elements.", i, lutFileName);
886                         return -EIO;
887                 }
888                 
889                 fIdToEntry[idManuChannel] = i;
890         }
891         
892         return 0;
893 }
894
895
896 int AliHLTMUONHitReconstructorComponent::ReadLutFromCDB()
897 {
898         /// Reads LUT from CDB.
899         /// To override the default CDB path and / or run number the
900         /// SetCDBPathAndRunNo(cdbPath, run) method should be called before this
901         /// method.
902
903         assert( fLut == NULL );
904         assert( fLutSize == 0 );
905         assert( fIdToEntry.empty() );
906         
907         if (fDDL == -1)
908         {
909                 HLTError("No DDL number specified for which to load LUT data from CDB.");
910                 return -EINVAL;
911         }
912         
913         std::vector<AliHLTMUONHitRecoLutRow> lutList;
914         AliHLTMUONHitRecoLutRow lut;
915         AliHLTUInt32_t iEntry = 0;
916         
917         int result = FetchMappingStores();
918         // Error message already generated in FetchMappingStores.
919         if (result != 0) return result;
920         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
921         
922         AliMpSegmentation* mpSegFactory = AliMpSegmentation::Instance();
923         if (mpSegFactory == NULL)
924         {
925                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
926                 return -EIO;
927         }
928         
929         // Only load geometry if not already loaded.
930         if (AliGeomManager::GetGeometry() == NULL)
931         {
932                 AliGeomManager::LoadGeometry();
933         }
934         AliMUONGeometryTransformer chamberGeometryTransformer;
935         if (not chamberGeometryTransformer.LoadGeometryData())
936         {
937                 HLTError("Failed to load geomerty data.");
938                 return -ENOENT;
939         }
940         
941         AliMUONCalibrationData calibData(AliCDBManager::Instance()->GetRun());
942         
943         Int_t chamberId;
944         
945         for(Int_t iCh = 6; iCh < 10; iCh++)
946         {
947                 chamberId = iCh;
948                 
949                 AliMpDEIterator it;
950                 for ( it.First(chamberId); ! it.IsDone(); it.Next() )
951                 {
952                         Int_t detElemId = it.CurrentDEId();
953                         int iDDL = ddlStore->GetDetElement(detElemId)->GetDdlId();
954                         if (iDDL != fDDL) continue;
955                 
956                         for (Int_t iCath = 0 ; iCath <= 1 ; iCath++)
957                         {
958                                 AliMp::CathodType cath;
959                                 
960                                 if(iCath == 0)
961                                         cath = AliMp::kCath0;
962                                 else
963                                         cath = AliMp::kCath1;
964                                 
965                                 const AliMpVSegmentation* seg = mpSegFactory->GetMpSegmentation(detElemId, cath);
966                                 AliMp::PlaneType plane = seg->PlaneType();
967                                 Int_t maxIX = seg->MaxPadIndexX();
968                                 Int_t maxIY = seg->MaxPadIndexY();
969                                 
970                                 Int_t idManuChannel, manuId, channelId, buspatchId;
971                                 AliHLTFloat32_t padSizeX, padSizeY;
972                                 AliHLTFloat32_t halfPadSize;
973                                 Double_t realX, realY, realZ;
974                                 Double_t localX, localY, localZ;
975                                 Float_t calibA0Coeff,calibA1Coeff,pedestal,sigma;
976                                 Int_t thresold,saturation;
977                                 
978                                 // Pad Info of a slat to print in lookuptable
979                                 for (Int_t iX = 0; iX<= maxIX ; iX++)
980                                 for (Int_t iY = 0; iY<= maxIY ; iY++)
981                                 {
982                                         if (not seg->HasPad(AliMpIntPair(iX,iY))) continue;
983
984                                         AliMpPad pad = seg->PadByIndices(AliMpIntPair(iX,iY), kFALSE);
985                                         
986                                         // Getting Manu id
987                                         manuId = pad.GetLocation().GetFirst();
988                                         manuId &= 0x7FF; // 11 bits 
989                         
990                                         buspatchId = ddlStore->GetBusPatchId(detElemId,manuId);
991                                         
992                                         // Getting channel id
993                                         channelId =  pad.GetLocation().GetSecond();
994                                         channelId &= 0x3F; // 6 bits
995                                         
996                                         idManuChannel = buspatchId << 11;
997                                         idManuChannel = (idManuChannel | manuId) << 6;
998                                         idManuChannel |= channelId;
999                                         
1000                                         localX = pad.Position().X();
1001                                         localY = pad.Position().Y();
1002                                         localZ = 0.0;
1003                                         
1004                                         chamberGeometryTransformer.Local2Global(
1005                                                 detElemId,localX,localY,localZ,
1006                                                 realX,realY,realZ
1007                                         );
1008                                         
1009                                         padSizeX = pad.Dimensions().X();
1010                                         padSizeY = pad.Dimensions().Y();
1011                                         
1012                                         calibA0Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 0);
1013                                         calibA1Coeff = (calibData.Gains(detElemId, manuId))->ValueAsFloat(channelId, 1);
1014                                         thresold = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 2);
1015                                         saturation = (calibData.Gains(detElemId, manuId))->ValueAsInt(channelId, 4);
1016                                         
1017                                         pedestal = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 0);
1018                                         sigma = (calibData.Pedestals(detElemId, manuId))->ValueAsFloat(channelId, 1);
1019                                         
1020                                         if (plane == 0)
1021                                                 halfPadSize = padSizeX;
1022                                         else
1023                                                 halfPadSize = padSizeY;
1024                                         
1025                                         fIdToEntry[idManuChannel] = iEntry+1;
1026                         
1027                                         lut.fDetElemId = detElemId;
1028                                         lut.fIX = iX;
1029                                         lut.fIY = iY;
1030                                         lut.fRealX = realX;
1031                                         lut.fRealY = realY;
1032                                         lut.fRealZ = realZ;
1033                                         lut.fHalfPadSize = halfPadSize;
1034                                         lut.fPlane = plane;
1035                                         lut.fPed = pedestal;
1036                                         lut.fSigma = sigma;
1037                                         lut.fA0 = calibA0Coeff;
1038                                         lut.fA1 = calibA1Coeff;
1039                                         lut.fThres = thresold;
1040                                         lut.fSat = saturation;
1041                                         
1042                                         lutList.push_back(lut);
1043                                         iEntry++;
1044                                 } // iX, iY loop
1045                         } // iCath loop
1046                 } // detElemId loop
1047         } // ichamber loop
1048
1049         try
1050         {
1051                 // Use iEntry+1 since we add one extra LUT line for the first element
1052                 // which is used as a sentinel value.
1053                 fLut = new AliHLTMUONHitRecoLutRow[iEntry+1];
1054                 fLutSize = iEntry+1;
1055         }
1056         catch (const std::bad_alloc&)
1057         {
1058                 HLTError("Could not allocate more memory for the lookuptable.");
1059                 return -ENOMEM;
1060         }
1061         
1062         // Initialise the sentinel value.
1063         fLut[0].fDetElemId = 0;
1064         fLut[0].fIX = 0;
1065         fLut[0].fIY = 0;
1066         fLut[0].fRealX = 0.0;
1067         fLut[0].fRealY = 0.0;
1068         fLut[0].fRealZ = 0.0;
1069         fLut[0].fHalfPadSize = 0.0;
1070         fLut[0].fPlane = -1;
1071         fLut[0].fPed = -1;
1072         fLut[0].fSigma = -1;
1073         fLut[0].fA0 = -1;
1074         fLut[0].fA1 = -1;
1075         fLut[0].fThres = -1;
1076         fLut[0].fSat = -1;
1077         
1078         for (AliHLTUInt32_t i = 0; i < iEntry; i++)
1079                 fLut[i+1] = lutList[i];
1080         
1081         return 0;
1082 }
1083
1084
1085 int AliHLTMUONHitReconstructorComponent::ReadDCCutFromCDB()
1086 {
1087         /// Reads the DC cut parameter from the CDB.
1088
1089         const char* pathToEntry = AliHLTMUONConstants::HitReconstructorCDBPath();
1090         
1091         TMap* map = NULL;
1092         int result = FetchTMapFromCDB(pathToEntry, map);
1093         if (result != 0) return result;
1094         
1095         Int_t value = 0;
1096         result = GetPositiveIntFromTMap(map, "dccut", value, pathToEntry, "DC cut");
1097         if (result != 0) return result;
1098         
1099         assert(fHitRec != NULL);
1100         fHitRec->SetDCCut(value);
1101         
1102         HLTDebug("Using DC cut parameter of %d ADC channels.", fHitRec->GetDCCut());
1103         
1104         return 0;
1105 }
1106
1107
1108 bool AliHLTMUONHitReconstructorComponent::GenerateLookupTable(
1109                 AliHLTInt32_t ddl, const char* filename,
1110                 const char* cdbPath, Int_t run
1111         )
1112 {
1113         /// Generates a ASCII text file containing the lookup table (LUT) from
1114         /// the CDB, which can be used for the hit reconstructor component later.
1115         /// @param ddl  Must be the DDL for which to generate the DDL,
1116         ///             in the range [13..20].
1117         /// @param filename  The name of the LUT file to generate.
1118         /// @param cdbPath  The CDB path to use.
1119         /// @param run  The run number to use for the CDB.
1120         /// @return  True if the generation of the LUT file succeeded.
1121         
1122         AliHLTMUONHitReconstructorComponent comp;
1123         
1124         if (ddl < 12 or 19 < ddl)
1125         {
1126                 std::cerr << "ERROR: the DDL number must be in the range [12..19]." << std::endl;
1127                 return false;
1128         }
1129         
1130         comp.fDDL = ddl;
1131         if (comp.SetCDBPathAndRunNo(cdbPath, run) != 0) return false;
1132         if (comp.ReadLutFromCDB() != 0) return false;
1133         
1134         char str[1024*4];
1135         std::fstream file(filename, std::ios::out);
1136         if (not file)
1137         {
1138                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
1139                 return false;
1140         }
1141         
1142         assert( comp.fLut != NULL );
1143         
1144         for (IdManuChannelToEntry::iterator id = comp.fIdToEntry.begin();
1145              id != comp.fIdToEntry.end();
1146              id++
1147             )
1148         {
1149                 AliHLTInt32_t idManuChannel = id->first;
1150                 AliHLTInt32_t row = id->second;
1151                 
1152                 assert( AliHLTUInt32_t(row) < comp.fLutSize );
1153                 
1154                 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",
1155                         idManuChannel, comp.fLut[row].fDetElemId, comp.fLut[row].fIX,
1156                         comp.fLut[row].fIY, comp.fLut[row].fRealX,
1157                         comp.fLut[row].fRealY, comp.fLut[row].fRealZ,
1158                         comp.fLut[row].fHalfPadSize, comp.fLut[row].fPlane,
1159                         comp.fLut[row].fPed, comp.fLut[row].fSigma, comp.fLut[row].fA0,
1160                         comp.fLut[row].fA1, comp.fLut[row].fThres, comp.fLut[row].fSat
1161                 );
1162                 
1163                 file << str << endl;
1164                 if (file.fail())
1165                 {
1166                         std::cerr << "ERROR: There was an I/O error when writing to the file: "
1167                                 << filename << std::endl;
1168                         return false;
1169                 }
1170         }
1171         
1172         return true;
1173 }