Fixing treatment of fOffset value in input data blocks.
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONTriggerReconstructorComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Indranil Das <indra.das@saha.ac.in>                                  *
7  *   Artur Szostak <artursz@iafrica.com>                                  *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 /* $Id$ */
19
20 ///
21 /// @file   AliHLTMUONTriggerReconstructorComponent.cxx
22 /// @author Indranil Das <indra.das@saha.ac.in>, Artur Szostak <artursz@iafrica.com>
23 /// @date   18 Sep 2007
24 /// @brief  Implementation of the trigger DDL reconstructor component.
25 ///
26
27 #include "AliHLTMUONTriggerReconstructorComponent.h"
28 #include "AliHLTMUONTriggerReconstructor.h"
29 #include "AliHLTMUONHitReconstructor.h"
30 #include "AliHLTMUONConstants.h"
31 #include "AliHLTMUONCalculations.h"
32 #include "AliHLTMUONUtils.h"
33 #include "AliHLTMUONDataBlockWriter.h"
34 #include "AliRawDataHeader.h"
35 #include "AliCDBManager.h"
36 #include "AliCDBStorage.h"
37 #include "AliGeomManager.h"
38 #include "AliMUONGeometryTransformer.h"
39 #include "AliMUONGeometryDetElement.h"
40 #include "AliMpCDB.h"
41 #include "AliMpDDLStore.h"
42 #include "AliMpPad.h"
43 #include "AliMpSegmentation.h"
44 #include "AliMpDEIterator.h"
45 #include "AliMpVSegmentation.h"
46 #include "AliMpDEManager.h"
47 #include "AliMpLocalBoard.h"
48 #include "AliMpTriggerCrate.h"
49 #include <cstdlib>
50 #include <cerrno>
51 #include <cassert>
52 #include <fstream>
53
54
55 ClassImp(AliHLTMUONTriggerReconstructorComponent)
56
57
58 AliHLTMUONTriggerReconstructorComponent::AliHLTMUONTriggerReconstructorComponent() :
59         AliHLTMUONProcessor(),
60         fTrigRec(NULL),
61         fDDL(-1),
62         fWarnForUnexpecedBlock(false),
63         fStopOnOverflow(false),
64         fUseCrateId(true),
65         fDelaySetup(false),
66         fZmiddleSpecified(false),
67         fBLSpecified(false),
68         fLutInitialised(false)
69 {
70         ///
71         /// Default constructor.
72         ///
73 }
74
75
76 AliHLTMUONTriggerReconstructorComponent::~AliHLTMUONTriggerReconstructorComponent()
77 {
78         ///
79         /// Default destructor.
80         ///
81         
82         if (fTrigRec != NULL) delete fTrigRec;
83 }
84
85
86 const char* AliHLTMUONTriggerReconstructorComponent::GetComponentID()
87 {
88         ///
89         /// Inherited from AliHLTComponent. Returns the component ID.
90         ///
91         
92         return AliHLTMUONConstants::TriggerReconstructorId();
93 }
94
95
96 void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
97 {
98         ///
99         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
100         ///
101         
102         list.clear();
103         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
104 }
105
106
107 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
108 {
109         ///
110         /// Inherited from AliHLTComponent. Returns the output data type.
111         ///
112         
113         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
114 }
115
116
117 void AliHLTMUONTriggerReconstructorComponent::GetOutputDataSize(
118                 unsigned long& constBase, double& inputMultiplier
119         )
120 {
121         ///
122         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
123         ///
124         
125         constBase = sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType);
126         inputMultiplier = 4;
127 }
128
129
130 AliHLTComponent* AliHLTMUONTriggerReconstructorComponent::Spawn()
131 {
132         ///
133         /// Inherited from AliHLTComponent. Creates a new object instance.
134         ///
135         
136         return new AliHLTMUONTriggerReconstructorComponent;
137 }
138
139
140 int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
141 {
142         ///
143         /// Inherited from AliHLTComponent.
144         /// Parses the command line parameters and initialises the component.
145         ///
146         
147         // perform initialization.
148         
149         HLTInfo("Initialising dHLT trigger reconstructor component.");
150         
151         // Make sure to cleanup fTrigRec if it is still there for some reason.
152         if (fTrigRec != NULL)
153         {
154                 delete fTrigRec;
155                 fTrigRec = NULL;
156         }
157         
158         try
159         {
160                 fTrigRec = new AliHLTMUONTriggerReconstructor();
161         }
162         catch (const std::bad_alloc&)
163         {
164                 HLTError("Could not allocate more memory for the trigger reconstructor component.");
165                 return -ENOMEM;
166         }
167         
168         fDDL = -1;
169         fWarnForUnexpecedBlock = false;
170         fStopOnOverflow = false;
171         fUseCrateId = true;
172         fDelaySetup = false;
173         fZmiddleSpecified = false;
174         fBLSpecified = false;
175         fLutInitialised = false;
176         
177         const char* lutFileName = NULL;
178         const char* cdbPath = NULL;
179         Int_t run = -1;
180         bool useCDB = false;
181         bool suppressPartialTrigs = true;
182         bool tryRecover = false;
183         bool useLocalId = true;
184         double zmiddle = 0;
185         double bfieldintegral = 0;
186         
187         for (int i = 0; i < argc; i++)
188         {
189                 if (strcmp( argv[i], "-lut" ) == 0)
190                 {
191                         if (lutFileName != NULL)
192                         {
193                                 HLTWarning("LUT path was already specified."
194                                         " Will replace previous value given by -lut."
195                                 );
196                         }
197                         
198                         if ( argc <= i+1 )
199                         {
200                                 HLTError("The lookup table filename was not specified." );
201                                 // Make sure to delete fTrigRec to avoid partial initialisation.
202                                 delete fTrigRec;
203                                 fTrigRec = NULL;
204                                 return -EINVAL;
205                         }
206                         
207                         lutFileName = argv[i+1];
208                         
209                         i++;
210                         continue;
211                 }
212                 
213                 if (strcmp( argv[i], "-ddl" ) == 0)
214                 {
215                         if (fDDL != -1)
216                         {
217                                 HLTWarning("DDL number was already specified."
218                                         " Will replace previous value given by -ddl or -ddlid."
219                                 );
220                         }
221                         
222                         if ( argc <= i+1 )
223                         {
224                                 HLTError("DDL number not specified. It must be in the range [21..22]" );
225                                 // Make sure to delete fTrigRec to avoid partial initialisation.
226                                 delete fTrigRec;
227                                 fTrigRec = NULL;
228                                 return -EINVAL;
229                         }
230                 
231                         char* cpErr = NULL;
232                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
233                         if (cpErr == NULL or *cpErr != '\0')
234                         {
235                                 HLTError("Cannot convert '%s' to a DDL Number.", argv[i+1]);
236                                 // Make sure to delete fTrigRec to avoid partial initialisation.
237                                 delete fTrigRec;
238                                 fTrigRec = NULL;
239                                 return -EINVAL;
240                         }
241                         if (num < 21 or 22 < num)
242                         {
243                                 HLTError("The DDL number must be in the range [21..22].");
244                                 // Make sure to delete fTrigRec to avoid partial initialisation.
245                                 delete fTrigRec;
246                                 fTrigRec = NULL;
247                                 return -EINVAL;
248                         }
249                         fDDL = num - 1; // Convert to DDL number in the range 0..21
250                         
251                         i++;
252                         continue;
253                 }
254                 
255                 if (strcmp( argv[i], "-ddlid" ) == 0)
256                 {
257                         if (fDDL != -1)
258                         {
259                                 HLTWarning("DDL number was already specified."
260                                         " Will replace previous value given by -ddl or -ddlid."
261                                 );
262                         }
263                         
264                         if ( argc <= i+1 )
265                         {
266                                 HLTError("DDL equipment ID number not specified. It must be in the range [2816..2817]" );
267                                 // Make sure to delete fTrigRec to avoid partial initialisation.
268                                 delete fTrigRec;
269                                 fTrigRec = NULL;
270                                 return -EINVAL;
271                         }
272                 
273                         char* cpErr = NULL;
274                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
275                         if (cpErr == NULL or *cpErr != '\0')
276                         {
277                                 HLTError("Cannot convert '%s' to a DDL equipment ID Number.", argv[i+1]);
278                                 // Make sure to delete fTrigRec to avoid partial initialisation.
279                                 delete fTrigRec;
280                                 fTrigRec = NULL;
281                                 return -EINVAL;
282                         }
283                         fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
284                         if (fDDL < 20 or 21 < fDDL)
285                         {
286                                 HLTError("The DDL equipment ID number must be in the range [2816..2817].");
287                                 // Make sure to delete fTrigRec to avoid partial initialisation.
288                                 delete fTrigRec;
289                                 fTrigRec = NULL;
290                                 return -EINVAL;
291                         }
292                         
293                         i++;
294                         continue;
295                 }
296                 
297                 if (strcmp( argv[i], "-cdb" ) == 0)
298                 {
299                         useCDB = true;
300                         continue;
301                 }
302                 
303                 if (strcmp( argv[i], "-cdbpath" ) == 0)
304                 {
305                         if (cdbPath != NULL)
306                         {
307                                 HLTWarning("CDB path was already specified."
308                                         " Will replace previous value given by -cdbpath."
309                                 );
310                         }
311                         
312                         if ( argc <= i+1 )
313                         {
314                                 HLTError("The CDB path was not specified." );
315                                 // Make sure to delete fTrigRec to avoid partial initialisation.
316                                 delete fTrigRec;
317                                 fTrigRec = NULL;
318                                 return -EINVAL;
319                         }
320                         cdbPath = argv[i+1];
321                         useCDB = true;
322                         i++;
323                         continue;
324                 }
325         
326                 if (strcmp( argv[i], "-run" ) == 0)
327                 {
328                         if (run != -1)
329                         {
330                                 HLTWarning("Run number was already specified."
331                                         " Will replace previous value given by -run."
332                                 );
333                         }
334                         
335                         if ( argc <= i+1 )
336                         {
337                                 HLTError("The run number was not specified." );
338                                 // Make sure to delete fTrigRec to avoid partial initialisation.
339                                 delete fTrigRec;
340                                 fTrigRec = NULL;
341                                 return -EINVAL;
342                         }
343                         
344                         char* cpErr = NULL;
345                         run = Int_t( strtoul(argv[i+1], &cpErr, 0) );
346                         if (cpErr == NULL or *cpErr != '\0')
347                         {
348                                 HLTError("Cannot convert '%s' to a valid run number."
349                                         " Expected a positive integer value.", argv[i+1]
350                                 );
351                                 // Make sure to delete fTrigRec to avoid partial initialisation.
352                                 delete fTrigRec;
353                                 fTrigRec = NULL;
354                                 return -EINVAL;
355                         }
356                         
357                         i++;
358                         continue;
359                 }
360         
361                 if (strcmp( argv[i], "-zmiddle" ) == 0)
362                 {
363                         if (fZmiddleSpecified)
364                         {
365                                 HLTWarning("The Z coordinate for the middle of the dipole was already specified."
366                                         " Will replace previous value given by -zmiddle."
367                                 );
368                         }
369                         
370                         if ( argc <= i+1 )
371                         {
372                                 HLTError("The Z coordinate for the middle of the dipole was not specified." );
373                                 // Make sure to delete fTrigRec to avoid partial initialisation.
374                                 delete fTrigRec;
375                                 fTrigRec = NULL;
376                                 return -EINVAL;
377                         }
378                         
379                         char* cpErr = NULL;
380                         zmiddle = strtod(argv[i+1], &cpErr);
381                         if (cpErr == NULL or *cpErr != '\0')
382                         {
383                                 HLTError("Cannot convert '%s' to a valid floating point number.",
384                                         argv[i+1]
385                                 );
386                                 // Make sure to delete fTrigRec to avoid partial initialisation.
387                                 delete fTrigRec;
388                                 fTrigRec = NULL;
389                                 return -EINVAL;
390                         }
391                         
392                         fZmiddleSpecified = true;
393                         i++;
394                         continue;
395                 }
396         
397                 if (strcmp( argv[i], "-bfieldintegral" ) == 0)
398                 {
399                         if (fBLSpecified)
400                         {
401                                 HLTWarning("The magnetic field integral was already specified."
402                                         " Will replace previous value given by -bfieldintegral."
403                                 );
404                         }
405                         
406                         if ( argc <= i+1 )
407                         {
408                                 HLTError("The magnetic field integral was not specified." );
409                                 // Make sure to delete fTrigRec to avoid partial initialisation.
410                                 delete fTrigRec;
411                                 fTrigRec = NULL;
412                                 return -EINVAL;
413                         }
414                         
415                         char* cpErr = NULL;
416                         bfieldintegral = strtod(argv[i+1], &cpErr);
417                         if (cpErr == NULL or *cpErr != '\0')
418                         {
419                                 HLTError("Cannot convert '%s' to a valid floating point number.",
420                                         argv[i+1]
421                                 );
422                                 // Make sure to delete fTrigRec to avoid partial initialisation.
423                                 delete fTrigRec;
424                                 fTrigRec = NULL;
425                                 return -EINVAL;
426                         }
427                         
428                         fBLSpecified = true;
429                         i++;
430                         continue;
431                 }
432                 
433                 if (strcmp( argv[i], "-delaysetup" ) == 0)
434                 {
435                         fDelaySetup = true;
436                         continue;
437                 }
438                 
439                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
440                 {
441                         fWarnForUnexpecedBlock = true;
442                         continue;
443                 }
444                 
445                 if (strcmp( argv[i], "-suppress_partial_triggers" ) == 0)
446                 {
447                         suppressPartialTrigs = true;
448                         continue;
449                 }
450                 
451                 if (strcmp( argv[i], "-generate_partial_triggers" ) == 0)
452                 {
453                         suppressPartialTrigs = false;
454                         continue;
455                 }
456                 
457                 if (strcmp( argv[i], "-stop_on_buffer_overflow" ) == 0)
458                 {
459                         fStopOnOverflow = true;
460                         continue;
461                 }
462                 
463                 if (strcmp( argv[i], "-tryrecover" ) == 0)
464                 {
465                         tryRecover = true;
466                         continue;
467                 }
468                 
469                 if (strcmp( argv[i], "-dont_use_crateid" ) == 0)
470                 {
471                         fUseCrateId = false;
472                         continue;
473                 }
474                 
475                 if (strcmp( argv[i], "-dont_use_localid" ) == 0)
476                 {
477                         useLocalId = false;
478                         continue;
479                 }
480                 
481                 HLTError("Unknown option '%s'.", argv[i] );
482                 // Make sure to delete fTrigRec to avoid partial initialisation.
483                 delete fTrigRec;
484                 fTrigRec = NULL;
485                 return -EINVAL;
486                 
487         } // for loop
488         
489         if (fZmiddleSpecified and useCDB)
490         {
491                 HLTWarning("The -cdb or -cdbpath parameter was specified, which indicates that"
492                         " this component should read from the CDB, but then the -zmiddle argument"
493                         " was also used. Will override the value from CDB with the command"
494                         " line parameter given."
495                 );
496         }
497         if (fBLSpecified and useCDB)
498         {
499                 HLTWarning("The -cdb or -cdbpath parameter was specified, which indicates that"
500                         " this component should read from the CDB, but then the -bfieldintegral"
501                         " argument was also used. Will override the value from CDB with the"
502                         " command line parameter given."
503                 );
504         }
505         
506         if (lutFileName != NULL and useCDB == true)
507         {
508                 HLTWarning("The -cdb or -cdbpath parameter was specified, which indicates that"
509                         " this component should read from the CDB, but then the -lut argument"
510                         " was also used. Will ignore the -lut option and load from CDB anyway."
511                 );
512         }
513         
514         if (lutFileName == NULL) useCDB = true;
515         
516         if (fDDL == -1 and not fDelaySetup)
517         {
518                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
519         }
520         
521         if (cdbPath != NULL or run != -1)
522         {
523                 int result = SetCDBPathAndRunNo(cdbPath, run);
524                 if (result != 0)
525                 {
526                         // Error messages already generated in SetCDBPathAndRunNo.
527                         delete fTrigRec; // Make sure to delete fTrigRec to avoid partial initialisation.
528                         fTrigRec = NULL;
529                         return result;
530                 }
531         }
532         
533         if (useCDB)
534         {
535                 if (not fDelaySetup)
536                 {
537                         HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
538                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
539                         );
540                         int result = ReadLutFromCDB();
541                         if (result != 0)
542                         {
543                                 // Error messages already generated in ReadLutFromCDB.
544                                 delete fTrigRec; // Make sure to delete fTrigRec to avoid partial initialisation.
545                                 fTrigRec = NULL;
546                                 return result;
547                         }
548                         fLutInitialised = true;
549                 }
550         }
551         else
552         {
553                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
554                 int result = ReadLookUpTable(lutFileName);
555                 if (result != 0)
556                 {
557                         // Error messages already generated in ReadLookUpTable.
558                         delete fTrigRec; // Make sure to delete fTrigRec to avoid partial initialisation.
559                         fTrigRec = NULL;
560                         return result;
561                 }
562                 fLutInitialised = true;
563         }
564         
565         if (fZmiddleSpecified) AliHLTMUONCalculations::Zf(zmiddle);
566         if (fBLSpecified) AliHLTMUONCalculations::QBL(bfieldintegral);
567         
568         if (not fDelaySetup)
569         {
570                 if (not fZmiddleSpecified or not fBLSpecified)
571                 {
572                         HLTInfo("Loading configuration parameters from CDB for DDL %d (ID = %d).",
573                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
574                         );
575                         
576                         int result = ReadConfigFromCDB(not fZmiddleSpecified, not fBLSpecified);
577                         if (result != 0)
578                         {
579                                 // Error messages already generated in ReadConfigFromCDB.
580                                 delete fTrigRec; // Make sure to delete fTrigRec to avoid partial initialisation.
581                                 fTrigRec = NULL;
582                                 return result;
583                         }
584                 }
585                 else
586                 {
587                         // Print the debug messages here since ReadConfigFromCDB does not get called,
588                         // in-which the debug messages would have been printed.
589                         HLTDebug("Using the following configuration parameters:");
590                         HLTDebug("  Middle of dipole Z coordinate = %f cm", AliHLTMUONCalculations::Zf());
591                         HLTDebug("        Magnetic field integral = %f T.m", AliHLTMUONCalculations::QBL());
592                 }
593         }
594         
595         fTrigRec->SuppressPartialTriggers(suppressPartialTrigs);
596         fTrigRec->TryRecover(tryRecover);
597         fTrigRec->UseCrateId(fUseCrateId);
598         fTrigRec->UseLocalId(useLocalId);
599         
600         return 0;
601 }
602
603
604 int AliHLTMUONTriggerReconstructorComponent::DoDeinit()
605 {
606         ///
607         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
608         ///
609         
610         HLTInfo("Deinitialising dHLT trigger reconstructor component.");
611
612         if (fTrigRec != NULL)
613         {
614                 delete fTrigRec;
615                 fTrigRec = NULL;
616         }
617         return 0;
618 }
619
620
621 int AliHLTMUONTriggerReconstructorComponent::DoEvent(
622                 const AliHLTComponentEventData& evtData,
623                 const AliHLTComponentBlockData* blocks,
624                 AliHLTComponentTriggerData& /*trigData*/,
625                 AliHLTUInt8_t* outputPtr,
626                 AliHLTUInt32_t& size,
627                 std::vector<AliHLTComponentBlockData>& outputBlocks
628         )
629 {
630         ///
631         /// Inherited from AliHLTProcessor. Processes the new event data.
632         ///
633         
634         // Initialise the LUT and configuration parameters from CDB if we were
635         // requested to initialise only when the first event was received.
636         if (fDelaySetup)
637         {
638                 // Use the specification given by the first data block if we
639                 // have not been given a DDL number on the command line.
640                 if (fDDL == -1)
641                 {
642                         bool blockFound = false;
643                         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt and not blockFound; n++)
644                         {
645                                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()) continue;
646                                 blockFound = true;
647
648                                 fDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
649                         
650                                 if (fDDL == -1)
651                                 {
652                                         HLTError("Received a data block with a specification (0x%8.8X)"
653                                                 " indicating multiple DDL data sources, but we must only"
654                                                 " receive raw DDL data from one trigger station DDL.",
655                                                 blocks[n].fSpecification
656                                         );
657                                         return -EPROTO;
658                                 }
659                         }
660
661                         if (not blockFound)
662                         {
663                                 HLTError("The initialisation from CDB of the component has"
664                                         " been delayed to the first received event. However,"
665                                         " no raw DDL data blocks have been found in the first event."
666                                 );
667                                 return -ENOENT;
668                         }
669                 }
670                 
671                 // Check that the LUT was not already loaded in DoInit.
672                 if (not fLutInitialised)
673                 {
674                         HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
675                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
676                         );
677                         int result = ReadLutFromCDB();
678                         if (result != 0) return result;
679                         fLutInitialised = true;
680                 }
681                 
682                 // Load the configuration paramters from CDB if they have not been given
683                 // on the command line.
684                 if (not fZmiddleSpecified or not fBLSpecified)
685                 {
686                         HLTInfo("Loading configuration parameters from CDB for DDL %d (ID = %d).",
687                                 fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
688                         );
689                         int result = ReadConfigFromCDB(not fZmiddleSpecified, not fBLSpecified);
690                         if (result != 0) return result;
691                 }
692                 
693                 fDelaySetup = false;
694         }
695         
696         // Process an event
697         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
698
699         HLTDebug("Processing event %llu with %u input data blocks.",
700                 evtData.fEventID, evtData.fBlockCnt
701         );
702         
703         // Loop over all input blocks in the event and run the trigger DDL
704         // reconstruction algorithm on the raw data.
705         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
706         {
707                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
708                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
709                 );
710
711                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
712                     or not AliHLTMUONUtils::IsTriggerDDL(blocks[n].fSpecification)
713                    )
714                 {
715                         // Log a message indicating that we got a data block that we
716                         // do not know how to handle.
717                         if (fWarnForUnexpecedBlock)
718                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
719                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
720                                 );
721                         else
722                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
723                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
724                                 );
725                         
726                         continue;
727                 }
728                 
729                 AliHLTInt32_t receivedDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
730                 if (fDDL != -1)
731                 {
732                         if (receivedDDL != fDDL)
733                         {
734                                 HLTWarning("Received raw data from DDL %d (ID = %d),"
735                                         " but expect data only from DDL %d (ID = %d).",
736                                         receivedDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(receivedDDL),
737                                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
738                                 );
739                         }
740                 }
741                 
742                 // Create a new output data block and initialise the header.
743                 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr+totalSize, size-totalSize);
744                 if (not block.InitCommonHeader())
745                 {
746                         HLTError("There is not enough space in the output buffer for the new data block."
747                                  " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
748                                 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
749                                 block.BufferSize()
750                         );
751                         break;
752                 }
753
754                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize;
755                 if (totalDDLSize < sizeof(AliRawDataHeader))
756                 {
757                         HLTError("Raw data block %d is %d bytes in size and is too short to"
758                                  " possibly contain valid DDL raw data. We expect it to have"
759                                  " at least %d bytes for the commond data header.",
760                                 n, totalDDLSize, sizeof(AliRawDataHeader)
761                         );
762                         continue;
763                 }
764                 AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(blocks[n].fPtr);
765                 AliHLTUInt32_t payloadSize = totalDDLSize - sizeof(AliRawDataHeader);
766                 AliHLTUInt8_t* buffer = reinterpret_cast<AliHLTUInt8_t*>(header + 1);
767                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
768                 
769                 // Decode if this is a scalar event or not.
770                 bool scalarEvent = ((header->GetL1TriggerMessage() & 0x1) == 0x1);
771                 
772                 // Remember: the following does NOT change the mapping!
773                 // It is just to generate unique trigger record IDs.
774                 fTrigRec->SetDDL(receivedDDL);
775                 
776                 bool runOk = fTrigRec->Run(
777                                 buffer, payloadSize, scalarEvent,
778                                 block.GetArray(), nofTrigRec
779                         );
780                 if (not runOk)
781                 {
782                         HLTError("Error while processing the trigger DDL reconstruction algorithm.");
783                         if (not fTrigRec->OverflowedOutputBuffer()
784                             or (fTrigRec->OverflowedOutputBuffer() and fStopOnOverflow)
785                            )
786                         {
787                                 size = totalSize; // Must tell the framework how much buffer space was used.
788                                 return -EIO;
789                         }
790                 }
791                 
792                 // nofTrigRec should now contain the number of triggers actually found
793                 // and filled into the output data block, so we can set this number.
794                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
795                 block.SetNumberOfEntries(nofTrigRec);
796                 
797                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
798                 
799                 // Fill a block data structure for our output block.
800                 AliHLTComponentBlockData bd;
801                 FillBlockData(bd);
802                 bd.fPtr = outputPtr;
803                 // This block's start (offset) is after all other blocks written so far.
804                 bd.fOffset = totalSize;
805                 bd.fSize = block.BytesUsed();
806                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
807                 bd.fSpecification = blocks[n].fSpecification;
808                 outputBlocks.push_back(bd);
809                 
810                 HLTDebug("Created a new output data block at fPtr = %p,"
811                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
812                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
813                 );
814                 
815                 // Increase the total amount of data written so far to our output memory.
816                 totalSize += block.BytesUsed();
817         }
818         
819         // Finally we set the total size of output memory we consumed.
820         size = totalSize;
821         return 0;
822 }
823
824
825 int AliHLTMUONTriggerReconstructorComponent::Reconfigure(
826                 const char* cdbEntry, const char* componentId
827         )
828 {
829         /// Inherited from AliHLTComponent. This method will reload CDB configuration
830         /// entries for this component from the CDB.
831         /// \param cdbEntry If this is NULL then it is assumed that all CDB entries should
832         ///      be reloaded. Otherwise a particular value for 'cdbEntry' will trigger
833         ///      reloading of the LUT if the path contains 'MUON/', but the other
834         ///      configuration parameters will be loaded if 'cdbEntry' contains
835         ///      "HLT/ConfigMUON/TriggerReconstructor".
836         /// \param componentId  The name of the component in the current chain.
837         
838         bool startsWithMUON = TString(cdbEntry).Index("MUON/", 5, 0, TString::kExact) == 0;
839         bool givenConfigPath = strcmp(cdbEntry, AliHLTMUONConstants::TriggerReconstructorCDBPath()) == 0;
840         
841         if (cdbEntry == NULL or startsWithMUON or givenConfigPath)
842         {
843                 HLTInfo("Reading new configuration entries from CDB for component '%s'.", componentId);
844         }
845         
846         if (cdbEntry == NULL or startsWithMUON)
847         {
848                 int result = ReadLutFromCDB();
849                 if (result != 0) return result;
850         }
851         
852         if (cdbEntry == NULL or givenConfigPath)
853         {
854                 int result = ReadConfigFromCDB();
855                 if (result != 0) return result;
856         }
857         
858         return 0;
859 }
860
861
862 int AliHLTMUONTriggerReconstructorComponent::ReadPreprocessorValues(const char* modules)
863 {
864         /// Inherited from AliHLTComponent. 
865         /// Updates the configuration of this component if either HLT or MUON have
866         /// been specified in the 'modules' list.
867
868         TString mods = modules;
869         if (mods.Contains("ALL") or (mods.Contains("HLT") and mods.Contains("MUON")))
870         {
871                 return Reconfigure(NULL, GetComponentID());
872         }
873         if (mods.Contains("HLT"))
874         {
875                 return Reconfigure(AliHLTMUONConstants::TriggerReconstructorCDBPath(), GetComponentID());
876         }
877         if (mods.Contains("MUON"))
878         {
879                 return Reconfigure("MUON/*", GetComponentID());
880         }
881         return 0;
882 }
883
884
885 int AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
886 {
887         ///
888         /// Read in the lookup table from file.
889         ///
890         
891         assert(fTrigRec != NULL);
892
893         fstream file;
894         file.open(lutpath, fstream::binary | fstream::in);
895         if (not file)
896         {
897                 HLTError("Could not open file: %s", lutpath);
898                 return -ENOENT;
899         }
900         
901         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
902         if (file.eof())
903         {
904                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
905                 file.close();
906                 return -EIO;
907         }
908         if (file.fail())
909         {
910                 HLTError("Could not read from file: %s", lutpath);
911                 file.close();
912                 return -EIO;
913         }
914         
915         file.close();
916         return 0;
917 }
918
919
920 int AliHLTMUONTriggerReconstructorComponent::ReadConfigFromCDB(
921                 bool setZmiddle, bool setBL
922         )
923 {
924         /// Reads this component's configuration parameters from the CDB.
925         /// These include the middle of the dipole Z coordinate (zmiddle) and the
926         /// integrated magnetic field of the dipole.
927         /// \param setZmiddle Indicates if the zmiddle parameter should be set
928         ///       (default true).
929         /// \param setBL Indicates if the integrated magnetic field parameter should
930         ///       be set (default true).
931         /// \return 0 if no errors occured and negative error code compatible with
932         ///       the HLT framework on errors.
933
934         const char* pathToEntry = AliHLTMUONConstants::TriggerReconstructorCDBPath();
935         
936         TMap* map = NULL;
937         int result = FetchTMapFromCDB(pathToEntry, map);
938         if (result != 0) return result;
939         
940         Double_t value = 0;
941         if (setZmiddle)
942         {
943                 result = GetFloatFromTMap(map, "zmiddle", value, pathToEntry, "dipole middle Z coordinate");
944                 if (result != 0) return result;
945                 AliHLTMUONCalculations::Zf(value);
946         }
947         
948         if (setBL)
949         {
950                 result = GetFloatFromTMap(map, "bfieldintegral", value, pathToEntry, "integrated magnetic field");
951                 if (result != 0) return result;
952                 AliHLTMUONCalculations::QBL(value);
953         }
954         
955         HLTDebug("Using the following configuration parameters:");
956         HLTDebug("  Middle of dipole Z coordinate = %f cm", AliHLTMUONCalculations::Zf());
957         HLTDebug("        Magnetic field integral = %f T.m", AliHLTMUONCalculations::QBL());
958         
959         return 0;
960 }
961
962
963 int AliHLTMUONTriggerReconstructorComponent::ReadLutFromCDB()
964 {
965         /// Loads the lookup table containing channel and geometrical position
966         /// information about trigger strips from CDB.
967         ///
968         /// \note To override the default CDB path and / or run number the
969         /// SetCDBPathAndRunNo(cdbPath, run) method should be called before this
970         /// method.
971         ///
972         /// \return 0 on success and non zero codes for errors.
973
974         if (fDDL == -1)
975         {
976                 HLTError("No DDL number specified for which to load LUT data from CDB.");
977                 return -EINVAL;
978         }
979
980         int result = FetchMappingStores();
981         // Error message already generated in FetchMappingStores.
982         if (result != 0) return result;
983         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
984         
985         AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
986         if (segmentation == NULL)
987         {
988                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
989                 return -EIO;
990         }
991         
992         // Only load geometry if not already loaded.
993         if (AliGeomManager::GetGeometry() == NULL)
994         {
995                 AliGeomManager::LoadGeometry();
996         }
997         AliMUONGeometryTransformer transformer;
998         if (not transformer.LoadGeometryData())
999         {
1000                 HLTError("Could not load geometry into transformer.");
1001                 return -ENOENT;
1002         }
1003         
1004         AliHLTMUONTriggerRecoLookupTable* lookupTable = fTrigRec->LookupTableBuffer();
1005         
1006         for (Int_t i = 0; i < 16; i++)
1007         for (Int_t j = 0; j < 16; j++)
1008         for (Int_t k = 0; k < 4; k++)
1009         for (Int_t n = 0; n < 2; n++)
1010         for (Int_t m = 0; m < 16; m++)
1011         {
1012                 lookupTable->fRow[i][j][k][n][m].fIdFlags = 0x0;
1013                 lookupTable->fRow[i][j][k][n][m].fX = 0;
1014                 lookupTable->fRow[i][j][k][n][m].fY = 0;
1015                 lookupTable->fRow[i][j][k][n][m].fZ = 0;
1016         }
1017         
1018         AliMpDEIterator detElemIter;
1019         for (Int_t iReg = 0; iReg < 8; iReg++)
1020         {
1021                 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(fDDL, iReg);
1022                 if (crate == NULL)
1023                 {
1024                         HLTError("Could not get crate mapping for regional header = %d"
1025                                 " and DDL %d (ID = %d).",
1026                                 iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
1027                         );
1028                         continue;
1029                 }
1030                 // Depending on the value of fUseCrateId, use either the crate ID as would
1031                 // be found in the regional header structures or the sequencial index number
1032                 // of the structure.
1033                 UInt_t crateId = (fUseCrateId ? crate->GetId() : iReg);
1034                 if (crateId >= 16)
1035                 {
1036                         HLTError("The crate ID number (%d) for regional header = %d and"
1037                                 " DDL %d (ID = %d) is too big. It should be in the range [0..15]",
1038                                 crateId, iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
1039                         );
1040                         continue;
1041                 }
1042                 
1043                 for (Int_t iLocBoard = 0; iLocBoard < 16; iLocBoard++)
1044                 {
1045                         Int_t boardId = crate->GetLocalBoardId(iLocBoard);
1046                         if (boardId == 0) continue;
1047                         
1048                         AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(boardId);
1049                         if (localBoard == NULL)
1050                         {
1051                                 HLTError("Could not get local board: %d.", boardId);
1052                                 continue;
1053                         }
1054
1055                         // skip copy cards
1056                         if (! localBoard->IsNotified()) continue;
1057                 
1058                         for (Int_t iChamber = 0; iChamber < 4; iChamber++)
1059                         {
1060                                 Int_t detElemId = ddlStore->GetDEfromLocalBoard(boardId, iChamber);
1061                                 
1062                                 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(iChamber+10, detElemId);
1063                                 
1064                                 const AliMUONGeometryDetElement* detElemTransform = transformer.GetDetElement(detElemId);
1065                                 if (detElemTransform == NULL)
1066                                 {
1067                                         HLTError("Got NULL pointer for geometry transformer"
1068                                                 " for detection element ID = %d.",
1069                                                 detElemId
1070                                         );
1071                                         continue;
1072                                 }
1073                                 
1074                                 for (Int_t iCathode = 0; iCathode <= 1; iCathode++)
1075                                 {
1076                                         const AliMpVSegmentation* seg = segmentation->GetMpSegmentation(
1077                                                         detElemId, AliMp::GetCathodType(iCathode)
1078                                                 );
1079                                         
1080                                         for (Int_t bitxy = 0; bitxy < 16; bitxy++)
1081                                         {
1082                                                 Int_t offset = 0;
1083                                                 if (iCathode && localBoard->GetSwitch(6)) offset = -8;
1084                                                 
1085                                                 AliMpPad pad = seg->PadByLocation(AliMpIntPair(boardId, bitxy+offset), kFALSE);
1086                                         
1087                                                 if (! pad.IsValid())
1088                                                 {
1089                                                         // There is no pad associated with the given local board and bit pattern.
1090                                                         continue;
1091                                                 }
1092                                                 
1093                                                 // Get the global coodinates of the pad.
1094                                                 Float_t lx = pad.Position().X();
1095                                                 Float_t ly = pad.Position().Y();
1096                                                 Float_t gx, gy, gz;
1097                                                 detElemTransform->Local2Global(lx, ly, 0, gx, gy, gz);
1098                                                 
1099                                                 // Fill the LUT
1100                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fIdFlags = idflags;
1101                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fX = gx;
1102                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fY = gy;
1103                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fZ = gz;
1104                                         }
1105                                 }
1106                         }
1107                 }
1108         }
1109         
1110         return 0;
1111 }
1112
1113
1114 bool AliHLTMUONTriggerReconstructorComponent::GenerateLookupTable(
1115                 AliHLTInt32_t ddl, const char* filename,
1116                 const char* cdbPath, Int_t run, bool useCrateId
1117         )
1118 {
1119         /// Generates a binary file containing the lookup table (LUT) from the
1120         /// CDB, which can be used for the trigger reconstructor component later.
1121         /// @param ddl  Must be the DDL for which to generate the DDL,
1122         ///             in the range [20..21].
1123         /// @param filename  The name of the LUT file to generate.
1124         /// @param cdbPath  The CDB path to use.
1125         /// @param run  The run number to use for the CDB.
1126         /// @param useCrateId  Indicates that the crate ID should be used rather
1127         ///             than a sequencial number.
1128         /// @return  True if the generation of the LUT file succeeded.
1129         
1130         AliHLTMUONTriggerReconstructorComponent comp;
1131         
1132         if (ddl < 20 or 21 < ddl)
1133         {
1134                 std::cerr << "ERROR: the DDL number must be in the range [20..21]." << std::endl;
1135                 return false;
1136         }
1137         
1138         char ddlNum[32];
1139         char runNum[32];
1140         sprintf(ddlNum, "%d", ddl+1);
1141         sprintf(runNum, "%d", run);
1142         int argc = 7;
1143         const char* argv[8] = {"-ddl", ddlNum, "-cdbpath", cdbPath, "-run", runNum, "-dont_use_crateid", NULL};
1144         if (useCrateId)
1145         {
1146                 argv[6] = NULL;
1147                 argc--;
1148         }
1149         int result = comp.DoInit(argc, argv);
1150         if (result != 0)
1151         {
1152                 // Error message already generated in DoInit.
1153                 return false;
1154         }
1155         
1156         std::fstream file(filename, std::ios::out);
1157         if (not file)
1158         {
1159                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
1160                 return false;
1161         }
1162         
1163         file.write(
1164                         reinterpret_cast<char*>(comp.fTrigRec->LookupTableBuffer()),
1165                         comp.fTrigRec->LookupTableSize()
1166                 );
1167         if (not file)
1168         {
1169                 std::cerr << "ERROR: There was a problem writing to the file: " << filename << std::endl;
1170                 return false;
1171         }
1172         file.close();
1173         
1174         comp.DoDeinit();
1175         
1176         return true;
1177 }