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