c9ba1587db65ce4f6d88fc4c5ae1fa0e0b73bd4d
[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*>(
765                                 reinterpret_cast<char*>(blocks[n].fPtr) + blocks[n].fOffset
766                         );
767                 AliHLTUInt32_t payloadSize = totalDDLSize - sizeof(AliRawDataHeader);
768                 AliHLTUInt8_t* buffer = reinterpret_cast<AliHLTUInt8_t*>(header + 1);
769                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
770                 
771                 // Decode if this is a scalar event or not.
772                 bool scalarEvent = ((header->GetL1TriggerMessage() & 0x1) == 0x1);
773                 
774                 // Remember: the following does NOT change the mapping!
775                 // It is just to generate unique trigger record IDs.
776                 fTrigRec->SetDDL(receivedDDL);
777                 
778                 bool runOk = fTrigRec->Run(
779                                 buffer, payloadSize, scalarEvent,
780                                 block.GetArray(), nofTrigRec
781                         );
782                 if (not runOk)
783                 {
784                         HLTError("Error while processing the trigger DDL reconstruction algorithm.");
785                         if (not fTrigRec->OverflowedOutputBuffer()
786                             or (fTrigRec->OverflowedOutputBuffer() and fStopOnOverflow)
787                            )
788                         {
789                                 size = totalSize; // Must tell the framework how much buffer space was used.
790                                 return -EIO;
791                         }
792                 }
793                 
794                 // nofTrigRec should now contain the number of triggers actually found
795                 // and filled into the output data block, so we can set this number.
796                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
797                 block.SetNumberOfEntries(nofTrigRec);
798                 
799                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
800                 
801                 // Fill a block data structure for our output block.
802                 AliHLTComponentBlockData bd;
803                 FillBlockData(bd);
804                 bd.fPtr = outputPtr;
805                 // This block's start (offset) is after all other blocks written so far.
806                 bd.fOffset = totalSize;
807                 bd.fSize = block.BytesUsed();
808                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
809                 bd.fSpecification = blocks[n].fSpecification;
810                 outputBlocks.push_back(bd);
811                 
812                 HLTDebug("Created a new output data block at fPtr = %p,"
813                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
814                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
815                 );
816                 
817                 // Increase the total amount of data written so far to our output memory.
818                 totalSize += block.BytesUsed();
819         }
820         
821         // Finally we set the total size of output memory we consumed.
822         size = totalSize;
823         return 0;
824 }
825
826
827 int AliHLTMUONTriggerReconstructorComponent::Reconfigure(
828                 const char* cdbEntry, const char* componentId
829         )
830 {
831         /// Inherited from AliHLTComponent. This method will reload CDB configuration
832         /// entries for this component from the CDB.
833         /// \param cdbEntry If this is NULL then it is assumed that all CDB entries should
834         ///      be reloaded. Otherwise a particular value for 'cdbEntry' will trigger
835         ///      reloading of the LUT if the path contains 'MUON/', but the other
836         ///      configuration parameters will be loaded if 'cdbEntry' contains
837         ///      "HLT/ConfigMUON/TriggerReconstructor".
838         /// \param componentId  The name of the component in the current chain.
839         
840         bool startsWithMUON = TString(cdbEntry).Index("MUON/", 5, 0, TString::kExact) == 0;
841         bool givenConfigPath = strcmp(cdbEntry, AliHLTMUONConstants::TriggerReconstructorCDBPath()) == 0;
842         
843         if (cdbEntry == NULL or startsWithMUON or givenConfigPath)
844         {
845                 HLTInfo("Reading new configuration entries from CDB for component '%s'.", componentId);
846         }
847         
848         if (cdbEntry == NULL or startsWithMUON)
849         {
850                 int result = ReadLutFromCDB();
851                 if (result != 0) return result;
852         }
853         
854         if (cdbEntry == NULL or givenConfigPath)
855         {
856                 int result = ReadConfigFromCDB();
857                 if (result != 0) return result;
858         }
859         
860         return 0;
861 }
862
863
864 int AliHLTMUONTriggerReconstructorComponent::ReadPreprocessorValues(const char* modules)
865 {
866         /// Inherited from AliHLTComponent. 
867         /// Updates the configuration of this component if either HLT or MUON have
868         /// been specified in the 'modules' list.
869
870         TString mods = modules;
871         if (mods.Contains("ALL") or (mods.Contains("HLT") and mods.Contains("MUON")))
872         {
873                 return Reconfigure(NULL, GetComponentID());
874         }
875         if (mods.Contains("HLT"))
876         {
877                 return Reconfigure(AliHLTMUONConstants::TriggerReconstructorCDBPath(), GetComponentID());
878         }
879         if (mods.Contains("MUON"))
880         {
881                 return Reconfigure("MUON/*", GetComponentID());
882         }
883         return 0;
884 }
885
886
887 int AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
888 {
889         ///
890         /// Read in the lookup table from file.
891         ///
892         
893         assert(fTrigRec != NULL);
894
895         fstream file;
896         file.open(lutpath, fstream::binary | fstream::in);
897         if (not file)
898         {
899                 HLTError("Could not open file: %s", lutpath);
900                 return -ENOENT;
901         }
902         
903         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
904         if (file.eof())
905         {
906                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
907                 file.close();
908                 return -EIO;
909         }
910         if (file.fail())
911         {
912                 HLTError("Could not read from file: %s", lutpath);
913                 file.close();
914                 return -EIO;
915         }
916         
917         file.close();
918         return 0;
919 }
920
921
922 int AliHLTMUONTriggerReconstructorComponent::ReadConfigFromCDB(
923                 bool setZmiddle, bool setBL
924         )
925 {
926         /// Reads this component's configuration parameters from the CDB.
927         /// These include the middle of the dipole Z coordinate (zmiddle) and the
928         /// integrated magnetic field of the dipole.
929         /// \param setZmiddle Indicates if the zmiddle parameter should be set
930         ///       (default true).
931         /// \param setBL Indicates if the integrated magnetic field parameter should
932         ///       be set (default true).
933         /// \return 0 if no errors occured and negative error code compatible with
934         ///       the HLT framework on errors.
935
936         const char* pathToEntry = AliHLTMUONConstants::TriggerReconstructorCDBPath();
937         
938         TMap* map = NULL;
939         int result = FetchTMapFromCDB(pathToEntry, map);
940         if (result != 0) return result;
941         
942         Double_t value = 0;
943         if (setZmiddle)
944         {
945                 result = GetFloatFromTMap(map, "zmiddle", value, pathToEntry, "dipole middle Z coordinate");
946                 if (result != 0) return result;
947                 AliHLTMUONCalculations::Zf(value);
948         }
949         
950         if (setBL)
951         {
952                 result = GetFloatFromTMap(map, "bfieldintegral", value, pathToEntry, "integrated magnetic field");
953                 if (result != 0) return result;
954                 AliHLTMUONCalculations::QBL(value);
955         }
956         
957         HLTDebug("Using the following configuration parameters:");
958         HLTDebug("  Middle of dipole Z coordinate = %f cm", AliHLTMUONCalculations::Zf());
959         HLTDebug("        Magnetic field integral = %f T.m", AliHLTMUONCalculations::QBL());
960         
961         return 0;
962 }
963
964
965 int AliHLTMUONTriggerReconstructorComponent::ReadLutFromCDB()
966 {
967         /// Loads the lookup table containing channel and geometrical position
968         /// information about trigger strips from CDB.
969         ///
970         /// \note To override the default CDB path and / or run number the
971         /// SetCDBPathAndRunNo(cdbPath, run) method should be called before this
972         /// method.
973         ///
974         /// \return 0 on success and non zero codes for errors.
975
976         if (fDDL == -1)
977         {
978                 HLTError("No DDL number specified for which to load LUT data from CDB.");
979                 return -EINVAL;
980         }
981
982         int result = FetchMappingStores();
983         // Error message already generated in FetchMappingStores.
984         if (result != 0) return result;
985         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
986         
987         AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
988         if (segmentation == NULL)
989         {
990                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
991                 return -EIO;
992         }
993         
994         // Only load geometry if not already loaded.
995         if (AliGeomManager::GetGeometry() == NULL)
996         {
997                 AliGeomManager::LoadGeometry();
998         }
999         AliMUONGeometryTransformer transformer;
1000         if (not transformer.LoadGeometryData())
1001         {
1002                 HLTError("Could not load geometry into transformer.");
1003                 return -ENOENT;
1004         }
1005         
1006         AliHLTMUONTriggerRecoLookupTable* lookupTable = fTrigRec->LookupTableBuffer();
1007         
1008         for (Int_t i = 0; i < 16; i++)
1009         for (Int_t j = 0; j < 16; j++)
1010         for (Int_t k = 0; k < 4; k++)
1011         for (Int_t n = 0; n < 2; n++)
1012         for (Int_t m = 0; m < 16; m++)
1013         {
1014                 lookupTable->fRow[i][j][k][n][m].fIdFlags = 0x0;
1015                 lookupTable->fRow[i][j][k][n][m].fX = 0;
1016                 lookupTable->fRow[i][j][k][n][m].fY = 0;
1017                 lookupTable->fRow[i][j][k][n][m].fZ = 0;
1018         }
1019         
1020         AliMpDEIterator detElemIter;
1021         for (Int_t iReg = 0; iReg < 8; iReg++)
1022         {
1023                 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(fDDL, iReg);
1024                 if (crate == NULL)
1025                 {
1026                         HLTError("Could not get crate mapping for regional header = %d"
1027                                 " and DDL %d (ID = %d).",
1028                                 iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
1029                         );
1030                         continue;
1031                 }
1032                 // Depending on the value of fUseCrateId, use either the crate ID as would
1033                 // be found in the regional header structures or the sequencial index number
1034                 // of the structure.
1035                 UInt_t crateId = (fUseCrateId ? crate->GetId() : iReg);
1036                 if (crateId >= 16)
1037                 {
1038                         HLTError("The crate ID number (%d) for regional header = %d and"
1039                                 " DDL %d (ID = %d) is too big. It should be in the range [0..15]",
1040                                 crateId, iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
1041                         );
1042                         continue;
1043                 }
1044                 
1045                 for (Int_t iLocBoard = 0; iLocBoard < 16; iLocBoard++)
1046                 {
1047                         Int_t boardId = crate->GetLocalBoardId(iLocBoard);
1048                         if (boardId == 0) continue;
1049                         
1050                         AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(boardId);
1051                         if (localBoard == NULL)
1052                         {
1053                                 HLTError("Could not get local board: %d.", boardId);
1054                                 continue;
1055                         }
1056
1057                         // skip copy cards
1058                         if (! localBoard->IsNotified()) continue;
1059                 
1060                         for (Int_t iChamber = 0; iChamber < 4; iChamber++)
1061                         {
1062                                 Int_t detElemId = ddlStore->GetDEfromLocalBoard(boardId, iChamber);
1063                                 
1064                                 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(iChamber+10, detElemId);
1065                                 
1066                                 const AliMUONGeometryDetElement* detElemTransform = transformer.GetDetElement(detElemId);
1067                                 if (detElemTransform == NULL)
1068                                 {
1069                                         HLTError("Got NULL pointer for geometry transformer"
1070                                                 " for detection element ID = %d.",
1071                                                 detElemId
1072                                         );
1073                                         continue;
1074                                 }
1075                                 
1076                                 for (Int_t iCathode = 0; iCathode <= 1; iCathode++)
1077                                 {
1078                                         const AliMpVSegmentation* seg = segmentation->GetMpSegmentation(
1079                                                         detElemId, AliMp::GetCathodType(iCathode)
1080                                                 );
1081                                         
1082                                         for (Int_t bitxy = 0; bitxy < 16; bitxy++)
1083                                         {
1084                                                 Int_t offset = 0;
1085                                                 if (iCathode && localBoard->GetSwitch(6)) offset = -8;
1086                                                 
1087                                                 AliMpPad pad = seg->PadByLocation(AliMpIntPair(boardId, bitxy+offset), kFALSE);
1088                                         
1089                                                 if (! pad.IsValid())
1090                                                 {
1091                                                         // There is no pad associated with the given local board and bit pattern.
1092                                                         continue;
1093                                                 }
1094                                                 
1095                                                 // Get the global coodinates of the pad.
1096                                                 Float_t lx = pad.Position().X();
1097                                                 Float_t ly = pad.Position().Y();
1098                                                 Float_t gx, gy, gz;
1099                                                 detElemTransform->Local2Global(lx, ly, 0, gx, gy, gz);
1100                                                 
1101                                                 // Fill the LUT
1102                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fIdFlags = idflags;
1103                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fX = gx;
1104                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fY = gy;
1105                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fZ = gz;
1106                                         }
1107                                 }
1108                         }
1109                 }
1110         }
1111         
1112         return 0;
1113 }
1114
1115
1116 bool AliHLTMUONTriggerReconstructorComponent::GenerateLookupTable(
1117                 AliHLTInt32_t ddl, const char* filename,
1118                 const char* cdbPath, Int_t run, bool useCrateId
1119         )
1120 {
1121         /// Generates a binary file containing the lookup table (LUT) from the
1122         /// CDB, which can be used for the trigger reconstructor component later.
1123         /// @param ddl  Must be the DDL for which to generate the DDL,
1124         ///             in the range [20..21].
1125         /// @param filename  The name of the LUT file to generate.
1126         /// @param cdbPath  The CDB path to use.
1127         /// @param run  The run number to use for the CDB.
1128         /// @param useCrateId  Indicates that the crate ID should be used rather
1129         ///             than a sequencial number.
1130         /// @return  True if the generation of the LUT file succeeded.
1131         
1132         AliHLTMUONTriggerReconstructorComponent comp;
1133         
1134         if (ddl < 20 or 21 < ddl)
1135         {
1136                 std::cerr << "ERROR: the DDL number must be in the range [20..21]." << std::endl;
1137                 return false;
1138         }
1139         
1140         char ddlNum[32];
1141         char runNum[32];
1142         sprintf(ddlNum, "%d", ddl+1);
1143         sprintf(runNum, "%d", run);
1144         int argc = 7;
1145         const char* argv[8] = {"-ddl", ddlNum, "-cdbpath", cdbPath, "-run", runNum, "-dont_use_crateid", NULL};
1146         if (useCrateId)
1147         {
1148                 argv[6] = NULL;
1149                 argc--;
1150         }
1151         int result = comp.DoInit(argc, argv);
1152         if (result != 0)
1153         {
1154                 // Error message already generated in DoInit.
1155                 return false;
1156         }
1157         
1158         std::fstream file(filename, std::ios::out);
1159         if (not file)
1160         {
1161                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
1162                 return false;
1163         }
1164         
1165         file.write(
1166                         reinterpret_cast<char*>(comp.fTrigRec->LookupTableBuffer()),
1167                         comp.fTrigRec->LookupTableSize()
1168                 );
1169         if (not file)
1170         {
1171                 std::cerr << "ERROR: There was a problem writing to the file: " << filename << std::endl;
1172                 return false;
1173         }
1174         file.close();
1175         
1176         comp.DoDeinit();
1177         
1178         return true;
1179 }