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