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