]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.cxx
Refactoring code to pull common functionality for loading CDB configuration entries...
[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 "AliHLTMUONUtils.h"
32 #include "AliHLTMUONDataBlockWriter.h"
33 #include "AliRawDataHeader.h"
34 #include "AliCDBManager.h"
35 #include "AliCDBStorage.h"
36 #include "AliGeomManager.h"
37 #include "AliMUONGeometryTransformer.h"
38 #include "AliMUONGeometryDetElement.h"
39 #include "AliMpCDB.h"
40 #include "AliMpDDLStore.h"
41 #include "AliMpPad.h"
42 #include "AliMpSegmentation.h"
43 #include "AliMpDEIterator.h"
44 #include "AliMpVSegmentation.h"
45 #include "AliMpDEManager.h"
46 #include "AliMpLocalBoard.h"
47 #include "AliMpTriggerCrate.h"
48 #include <cstdlib>
49 #include <cerrno>
50 #include <cassert>
51 #include <fstream>
52
53
54 ClassImp(AliHLTMUONTriggerReconstructorComponent)
55
56
57 AliHLTMUONTriggerReconstructorComponent::AliHLTMUONTriggerReconstructorComponent() :
58         AliHLTMUONProcessor(),
59         fTrigRec(NULL),
60         fDDL(-1),
61         fWarnForUnexpecedBlock(false),
62         fStopOnOverflow(false),
63         fUseCrateId(true)
64 {
65         ///
66         /// Default constructor.
67         ///
68 }
69
70
71 AliHLTMUONTriggerReconstructorComponent::~AliHLTMUONTriggerReconstructorComponent()
72 {
73         ///
74         /// Default destructor.
75         ///
76         
77         if (fTrigRec != NULL) delete fTrigRec;
78 }
79
80
81 const char* AliHLTMUONTriggerReconstructorComponent::GetComponentID()
82 {
83         ///
84         /// Inherited from AliHLTComponent. Returns the component ID.
85         ///
86         
87         return AliHLTMUONConstants::TriggerReconstructorId();
88 }
89
90
91 void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
92 {
93         ///
94         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
95         ///
96         
97         list.clear();
98         list.push_back( AliHLTMUONConstants::DDLRawDataType() );
99 }
100
101
102 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
103 {
104         ///
105         /// Inherited from AliHLTComponent. Returns the output data type.
106         ///
107         
108         return AliHLTMUONConstants::TriggerRecordsBlockDataType();
109 }
110
111
112 void AliHLTMUONTriggerReconstructorComponent::GetOutputDataSize(
113                 unsigned long& constBase, double& inputMultiplier
114         )
115 {
116         ///
117         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
118         ///
119         
120         constBase = sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType);
121         inputMultiplier = 4;
122 }
123
124
125 AliHLTComponent* AliHLTMUONTriggerReconstructorComponent::Spawn()
126 {
127         ///
128         /// Inherited from AliHLTComponent. Creates a new object instance.
129         ///
130         
131         return new AliHLTMUONTriggerReconstructorComponent;
132 }
133
134
135 int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
136 {
137         ///
138         /// Inherited from AliHLTComponent.
139         /// Parses the command line parameters and initialises the component.
140         ///
141         
142         // perform initialization.
143         
144         HLTInfo("Initialising dHLT trigger reconstructor component.");
145         
146         // Make sure to cleanup fTrigRec if it is still there for some reason.
147         if (fTrigRec != NULL)
148         {
149                 delete fTrigRec;
150                 fTrigRec = NULL;
151         }
152         
153         try
154         {
155                 fTrigRec = new AliHLTMUONTriggerReconstructor();
156         }
157         catch (const std::bad_alloc&)
158         {
159                 HLTError("Could not allocate more memory for the trigger reconstructor component.");
160                 return -ENOMEM;
161         }
162         
163         fDDL = -1;
164         fWarnForUnexpecedBlock = false;
165         fStopOnOverflow = false;
166         fUseCrateId = true;
167         
168         const char* lutFileName = NULL;
169         const char* cdbPath = NULL;
170         Int_t run = -1;
171         bool useCDB = false;
172         bool suppressPartialTrigs = true;
173         bool tryRecover = false;
174         
175         for (int i = 0; i < argc; i++)
176         {
177                 if (strcmp( argv[i], "-lut" ) == 0)
178                 {
179                         if ( argc <= i+1 )
180                         {
181                                 HLTError("LookupTable filename not specified." );
182                                 // Make sure to delete fTrigRec to avoid partial initialisation.
183                                 delete fTrigRec;
184                                 fTrigRec = NULL;
185                                 return -EINVAL;
186                         }
187                         
188                         lutFileName = argv[i+1];
189                         
190                         i++;
191                         continue;
192                 }
193                 
194                 if (strcmp( argv[i], "-ddl" ) == 0)
195                 {
196                         if ( argc <= i+1 )
197                         {
198                                 HLTError("DDL number not specified. It must be in the range [21..22]" );
199                                 // Make sure to delete fTrigRec to avoid partial initialisation.
200                                 delete fTrigRec;
201                                 fTrigRec = NULL;
202                                 return -EINVAL;
203                         }
204                 
205                         char* cpErr = NULL;
206                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
207                         if (cpErr == NULL or *cpErr != '\0')
208                         {
209                                 HLTError("Cannot convert '%s' to a DDL Number.", argv[i+1]);
210                                 // Make sure to delete fTrigRec to avoid partial initialisation.
211                                 delete fTrigRec;
212                                 fTrigRec = NULL;
213                                 return -EINVAL;
214                         }
215                         if (num < 21 or 22 < num)
216                         {
217                                 HLTError("The DDL number must be in the range [21..22].");
218                                 // Make sure to delete fTrigRec to avoid partial initialisation.
219                                 delete fTrigRec;
220                                 fTrigRec = NULL;
221                                 return -EINVAL;
222                         }
223                         fDDL = num - 1; // Convert to DDL number in the range 0..21
224                         
225                         i++;
226                         continue;
227                 }
228                 
229                 if (strcmp( argv[i], "-ddlid" ) == 0)
230                 {
231                         if ( argc <= i+1 )
232                         {
233                                 HLTError("DDL equipment ID number not specified. It must be in the range [2816..2817]" );
234                                 // Make sure to delete fTrigRec to avoid partial initialisation.
235                                 delete fTrigRec;
236                                 fTrigRec = NULL;
237                                 return -EINVAL;
238                         }
239                 
240                         char* cpErr = NULL;
241                         unsigned long num = strtoul(argv[i+1], &cpErr, 0);
242                         if (cpErr == NULL or *cpErr != '\0')
243                         {
244                                 HLTError("Cannot convert '%s' to a DDL equipment ID Number.", argv[i+1]);
245                                 // Make sure to delete fTrigRec to avoid partial initialisation.
246                                 delete fTrigRec;
247                                 fTrigRec = NULL;
248                                 return -EINVAL;
249                         }
250                         fDDL = AliHLTMUONUtils::EquipIdToDDLNumber(num); // Convert to DDL number in the range 0..21
251                         if (fDDL < 20 or 21 < fDDL)
252                         {
253                                 HLTError("The DDL equipment ID number must be in the range [2816..2817].");
254                                 // Make sure to delete fTrigRec to avoid partial initialisation.
255                                 delete fTrigRec;
256                                 fTrigRec = NULL;
257                                 return -EINVAL;
258                         }
259                         
260                         i++;
261                         continue;
262                 }
263                 
264                 if (strcmp( argv[i], "-cdb" ) == 0)
265                 {
266                         useCDB = true;
267                         continue;
268                 }
269                 
270                 if (strcmp( argv[i], "-cdbpath" ) == 0)
271                 {
272                         if ( argc <= i+1 )
273                         {
274                                 HLTError("The CDB path was not specified." );
275                                 // Make sure to delete fTrigRec to avoid partial initialisation.
276                                 delete fTrigRec;
277                                 fTrigRec = NULL;
278                                 return -EINVAL;
279                         }
280                         cdbPath = argv[i+1];
281                         useCDB = true;
282                         i++;
283                         continue;
284                 }
285         
286                 if (strcmp( argv[i], "-run" ) == 0)
287                 {
288                         if ( argc <= i+1 )
289                         {
290                                 HLTError("The run number was not specified." );
291                                 // Make sure to delete fTrigRec to avoid partial initialisation.
292                                 delete fTrigRec;
293                                 fTrigRec = NULL;
294                                 return -EINVAL;
295                         }
296                         
297                         char* cpErr = NULL;
298                         run = Int_t( strtoul(argv[i+1], &cpErr, 0) );
299                         if (cpErr == NULL or *cpErr != '\0')
300                         {
301                                 HLTError("Cannot convert '%s' to a valid run number."
302                                         " Expected a positive integer value.", argv[i+1]
303                                 );
304                                 // Make sure to delete fTrigRec to avoid partial initialisation.
305                                 delete fTrigRec;
306                                 fTrigRec = NULL;
307                                 return -EINVAL;
308                         }
309                         
310                         i++;
311                         continue;
312                 }
313                 
314                 if (strcmp( argv[i], "-warn_on_unexpected_block" ) == 0)
315                 {
316                         fWarnForUnexpecedBlock = true;
317                         continue;
318                 }
319                 
320                 if (strcmp( argv[i], "-suppress_partial_triggers" ) == 0)
321                 {
322                         suppressPartialTrigs = true;
323                         continue;
324                 }
325                 
326                 if (strcmp( argv[i], "-generate_partial_triggers" ) == 0)
327                 {
328                         suppressPartialTrigs = false;
329                         continue;
330                 }
331                 
332                 if (strcmp( argv[i], "-stop_on_buffer_overflow" ) == 0)
333                 {
334                         fStopOnOverflow = true;
335                         continue;
336                 }
337                 
338                 if (strcmp( argv[i], "-tryrecover" ) == 0)
339                 {
340                         tryRecover = true;
341                         continue;
342                 }
343                 
344                 if (strcmp( argv[i], "-dont_use_crateid" ) == 0)
345                 {
346                         fUseCrateId = false;
347                         continue;
348                 }
349                 
350                 HLTError("Unknown option '%s'.", argv[i] );
351                 // Make sure to delete fTrigRec to avoid partial initialisation.
352                 delete fTrigRec;
353                 fTrigRec = NULL;
354                 return -EINVAL;
355                 
356         } // for loop
357         
358         if (lutFileName == NULL) useCDB = true;
359         
360         if (fDDL == -1)
361         {
362                 HLTWarning("DDL number not specified. Cannot check if incomming data is valid.");
363         }
364         
365         int result = 0;
366         if (cdbPath != NULL or run != -1)
367         {
368                 result = SetCDBPathAndRunNo(cdbPath, run);
369         }
370         
371         if (result == 0 and useCDB)
372         {
373                 HLTInfo("Loading lookup table information from CDB for DDL %d (ID = %d).",
374                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
375                 );
376                 if (fDDL == -1)
377                         HLTWarning("DDL number not specified. The lookup table loaded from CDB will be empty!");
378                 result = ReadLutFromCDB();
379         }
380         else if (result == 0)
381         {
382                 HLTInfo("Loading lookup table information from file %s.", lutFileName);
383                 result = ReadLookUpTable(lutFileName);
384         }
385         if (result != 0)
386         {
387                 // Error messages already generated in ReadLutFromCDB or ReadLookUpTable.
388                 
389                 // Make sure to delete fTrigRec to avoid partial initialisation.
390                 delete fTrigRec;
391                 fTrigRec = NULL;
392                 return result;
393         }
394         
395         fTrigRec->SuppressPartialTriggers(suppressPartialTrigs);
396         fTrigRec->TryRecover(tryRecover);
397         fTrigRec->UseCrateId(fUseCrateId);
398         
399         return 0;
400 }
401
402
403 int AliHLTMUONTriggerReconstructorComponent::DoDeinit()
404 {
405         ///
406         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
407         ///
408         
409         HLTInfo("Deinitialising dHLT trigger reconstructor component.");
410
411         if (fTrigRec != NULL)
412         {
413                 delete fTrigRec;
414                 fTrigRec = NULL;
415         }
416         return 0;
417 }
418
419
420 int AliHLTMUONTriggerReconstructorComponent::DoEvent(
421                 const AliHLTComponentEventData& evtData,
422                 const AliHLTComponentBlockData* blocks,
423                 AliHLTComponentTriggerData& /*trigData*/,
424                 AliHLTUInt8_t* outputPtr,
425                 AliHLTUInt32_t& size,
426                 std::vector<AliHLTComponentBlockData>& outputBlocks
427         )
428 {
429         ///
430         /// Inherited from AliHLTProcessor. Processes the new event data.
431         ///
432         
433         // Process an event
434         unsigned long totalSize = 0; // Amount of memory currently consumed in bytes.
435
436         HLTDebug("Processing event %llu with %u input data blocks.",
437                 evtData.fEventID, evtData.fBlockCnt
438         );
439         
440         // Loop over all input blocks in the event and run the trigger DDL
441         // reconstruction algorithm on the raw data.
442         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
443         {
444                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
445                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
446                 );
447
448                 if (blocks[n].fDataType != AliHLTMUONConstants::DDLRawDataType()
449                     or not AliHLTMUONUtils::IsTriggerDDL(blocks[n].fSpecification)
450                    )
451                 {
452                         // Log a message indicating that we got a data block that we
453                         // do not know how to handle.
454                         if (fWarnForUnexpecedBlock)
455                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
456                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
457                                 );
458                         else
459                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
460                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
461                                 );
462                         
463                         continue;
464                 }
465                 
466                 AliHLTInt32_t receivedDDL = AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification);
467                 if (fDDL != -1)
468                 {
469                         if (receivedDDL != fDDL)
470                         {
471                                 HLTWarning("Received raw data from DDL %d (ID = %d),"
472                                         " but expect data only from DDL %d (ID = %d).",
473                                         receivedDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(receivedDDL),
474                                         fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
475                                 );
476                         }
477                 }
478                 
479                 // Create a new output data block and initialise the header.
480                 AliHLTMUONTriggerRecordsBlockWriter block(outputPtr+totalSize, size-totalSize);
481                 if (not block.InitCommonHeader())
482                 {
483                         HLTError("There is not enough space in the output buffer for the new data block."
484                                  " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
485                                 sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
486                                 block.BufferSize()
487                         );
488                         break;
489                 }
490
491                 AliHLTUInt32_t totalDDLSize = blocks[n].fSize;
492                 if (totalDDLSize < sizeof(AliRawDataHeader))
493                 {
494                         HLTError("Raw data block %d is %d bytes in size and is too short to"
495                                  " possibly contain valid DDL raw data. We expect it to have"
496                                  " at least %d bytes for the commond data header.",
497                                 n, totalDDLSize, sizeof(AliRawDataHeader)
498                         );
499                         continue;
500                 }
501                 AliRawDataHeader* header = reinterpret_cast<AliRawDataHeader*>(
502                                 reinterpret_cast<char*>(blocks[n].fPtr) + blocks[n].fOffset
503                         );
504                 AliHLTUInt32_t payloadSize = totalDDLSize - sizeof(AliRawDataHeader);
505                 AliHLTUInt8_t* buffer = reinterpret_cast<AliHLTUInt8_t*>(header + 1);
506                 AliHLTUInt32_t nofTrigRec = block.MaxNumberOfEntries();
507                 
508                 // Decode if this is a scalar event or not.
509                 bool scalarEvent = ((header->GetL1TriggerMessage() & 0x1) == 0x1);
510                 
511                 // Remember: the following does NOT change the mapping!
512                 // It is just to generate unique trigger record IDs.
513                 fTrigRec->SetDDL(receivedDDL);
514                 
515                 bool runOk = fTrigRec->Run(
516                                 buffer, payloadSize, scalarEvent,
517                                 block.GetArray(), nofTrigRec
518                         );
519                 if (not runOk)
520                 {
521                         HLTError("Error while processing the trigger DDL reconstruction algorithm.");
522                         if (not fTrigRec->OverflowedOutputBuffer()
523                             or (fTrigRec->OverflowedOutputBuffer() and fStopOnOverflow)
524                            )
525                         {
526                                 size = totalSize; // Must tell the framework how much buffer space was used.
527                                 return -EIO;
528                         }
529                 }
530                 
531                 // nofTrigRec should now contain the number of triggers actually found
532                 // and filled into the output data block, so we can set this number.
533                 assert( nofTrigRec <= block.MaxNumberOfEntries() );
534                 block.SetNumberOfEntries(nofTrigRec);
535                 
536                 HLTDebug("Number of trigger records found is %d", nofTrigRec);
537                 
538                 // Fill a block data structure for our output block.
539                 AliHLTComponentBlockData bd;
540                 FillBlockData(bd);
541                 bd.fPtr = outputPtr;
542                 // This block's start (offset) is after all other blocks written so far.
543                 bd.fOffset = totalSize;
544                 bd.fSize = block.BytesUsed();
545                 bd.fDataType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
546                 bd.fSpecification = blocks[n].fSpecification;
547                 outputBlocks.push_back(bd);
548                 
549                 HLTDebug("Created a new output data block at fPtr = %p,"
550                           " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
551                         bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
552                 );
553                 
554                 // Increase the total amount of data written so far to our output memory.
555                 totalSize += block.BytesUsed();
556         }
557         
558         // Finally we set the total size of output memory we consumed.
559         size = totalSize;
560         return 0;
561 }
562
563
564 int AliHLTMUONTriggerReconstructorComponent::ReadLookUpTable(const char* lutpath)
565 {
566         ///
567         /// Read in the lookup table from file.
568         ///
569         
570         assert(fTrigRec != NULL);
571
572         fstream file;
573         file.open(lutpath, fstream::binary | fstream::in);
574         if (not file)
575         {
576                 HLTError("Could not open file: %s", lutpath);
577                 return -ENOENT;
578         }
579         
580         file.read(reinterpret_cast<char*>(fTrigRec->LookupTableBuffer()), fTrigRec->LookupTableSize());
581         if (file.eof())
582         {
583                 HLTError("The file %s was too short to contain a valid lookup table for this component.", lutpath);
584                 file.close();
585                 return -EIO;
586         }
587         if (file.fail())
588         {
589                 HLTError("Could not read from file: %s", lutpath);
590                 file.close();
591                 return -EIO;
592         }
593         
594         file.close();
595         return 0;
596 }
597
598
599 int AliHLTMUONTriggerReconstructorComponent::ReadLutFromCDB()
600 {
601         /// Loads the lookup table containing channel and geometrical position
602         /// information about trigger strips from CDB.
603         ///
604         /// \note To override the default CDB path and / or run number the
605         /// SetCDBPathAndRunNo(cdbPath, run) method should be called before this
606         /// method.
607         ///
608         /// \return 0 on success and non zero codes for errors.
609
610         if (fDDL == -1)
611         {
612                 HLTError("No DDL number specified for which to load LUT data from CDB.");
613                 return -EINVAL;
614         }
615
616         int result = FetchMappingStores();
617         // Error message already generated in FetchMappingStores.
618         if (result != 0) return result;
619         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
620         
621         AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
622         if (segmentation == NULL)
623         {
624                 HLTError("Could not find segmentation mapping (AliMpSegmentation) instance.");
625                 return -EIO;
626         }
627         
628         // Only load geometry if not already loaded.
629         if (AliGeomManager::GetGeometry() == NULL)
630         {
631                 AliGeomManager::LoadGeometry();
632         }
633         AliMUONGeometryTransformer transformer;
634         if (not transformer.LoadGeometryData())
635         {
636                 HLTError("Could not load geometry into transformer.");
637                 return -ENOENT;
638         }
639         
640         AliHLTMUONTriggerRecoLookupTable* lookupTable = fTrigRec->LookupTableBuffer();
641         
642         for (Int_t i = 0; i < 16; i++)
643         for (Int_t j = 0; j < 16; j++)
644         for (Int_t k = 0; k < 4; k++)
645         for (Int_t n = 0; n < 2; n++)
646         for (Int_t m = 0; m < 16; m++)
647         {
648                 lookupTable->fRow[i][j][k][n][m].fIdFlags = 0x0;
649                 lookupTable->fRow[i][j][k][n][m].fX = 0;
650                 lookupTable->fRow[i][j][k][n][m].fY = 0;
651                 lookupTable->fRow[i][j][k][n][m].fZ = 0;
652         }
653         
654         AliMpDEIterator detElemIter;
655         for (Int_t iReg = 0; iReg < 8; iReg++)
656         {
657                 AliMpTriggerCrate* crate = ddlStore->GetTriggerCrate(fDDL, iReg);
658                 if (crate == NULL)
659                 {
660                         HLTError("Could not get crate mapping for regional header = %d"
661                                 " and DDL %d (ID = %d).",
662                                 iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
663                         );
664                         continue;
665                 }
666                 // Depending on the value of fUseCrateId, use either the crate ID as would
667                 // be found in the regional header structures or the sequencial index number
668                 // of the structure.
669                 UInt_t crateId = (fUseCrateId ? crate->GetId() : iReg);
670                 if (crateId >= 16)
671                 {
672                         HLTError("The crate ID number (%d) for regional header = %d and"
673                                 " DDL %d (ID = %d) is too big. It should be in the range [0..15]",
674                                 crateId, iReg, fDDL+1, AliHLTMUONUtils::DDLNumberToEquipId(fDDL)
675                         );
676                         continue;
677                 }
678                 
679                 for (Int_t iLocBoard = 0; iLocBoard < 16; iLocBoard++)
680                 {
681                         Int_t boardId = crate->GetLocalBoardId(iLocBoard);
682                         if (boardId == 0) continue;
683                         
684                         AliMpLocalBoard* localBoard = ddlStore->GetLocalBoard(boardId);
685                         if (localBoard == NULL)
686                         {
687                                 HLTError("Could not get local board: %d.", boardId);
688                                 continue;
689                         }
690
691                         // skip copy cards
692                         if (! localBoard->IsNotified()) continue;
693                 
694                         for (Int_t iChamber = 0; iChamber < 4; iChamber++)
695                         {
696                                 Int_t detElemId = ddlStore->GetDEfromLocalBoard(boardId, iChamber);
697                                 
698                                 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(iChamber+10, detElemId);
699                                 
700                                 const AliMUONGeometryDetElement* detElemTransform = transformer.GetDetElement(detElemId);
701                                 if (detElemTransform == NULL)
702                                 {
703                                         HLTError("Got NULL pointer for geometry transformer"
704                                                 " for detection element ID = %d.",
705                                                 detElemId
706                                         );
707                                         continue;
708                                 }
709                                 
710                                 for (Int_t iCathode = 0; iCathode <= 1; iCathode++)
711                                 {
712                                         const AliMpVSegmentation* seg = segmentation->GetMpSegmentation(
713                                                         detElemId, AliMp::GetCathodType(iCathode)
714                                                 );
715                                         
716                                         for (Int_t bitxy = 0; bitxy < 16; bitxy++)
717                                         {
718                                                 Int_t offset = 0;
719                                                 if (iCathode && localBoard->GetSwitch(6)) offset = -8;
720                                                 
721                                                 AliMpPad pad = seg->PadByLocation(AliMpIntPair(boardId, bitxy+offset), kFALSE);
722                                         
723                                                 if (! pad.IsValid())
724                                                 {
725                                                         // There is no pad associated with the given local board and bit pattern.
726                                                         continue;
727                                                 }
728                                                 
729                                                 // Get the global coodinates of the pad.
730                                                 Float_t lx = pad.Position().X();
731                                                 Float_t ly = pad.Position().Y();
732                                                 Float_t gx, gy, gz;
733                                                 detElemTransform->Local2Global(lx, ly, 0, gx, gy, gz);
734                                                 
735                                                 // Fill the LUT
736                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fIdFlags = idflags;
737                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fX = gx;
738                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fY = gy;
739                                                 lookupTable->fRow[crateId][iLocBoard][iChamber][iCathode][bitxy].fZ = gz;
740                                         }
741                                 }
742                         }
743                 }
744         }
745         
746         return 0;
747 }
748
749
750 bool AliHLTMUONTriggerReconstructorComponent::GenerateLookupTable(
751                 AliHLTInt32_t ddl, const char* filename,
752                 const char* cdbPath, Int_t run
753                 //TODO add option fCrateId
754         )
755 {
756         /// Generates a binary file containing the lookup table (LUT) from the
757         /// CDB, which can be used for the trigger reconstructor component later.
758         /// @param ddl  Must be the DDL for which to generate the DDL,
759         ///             in the range [20..21].
760         /// @param filename  The name of the LUT file to generate.
761         /// @param cdbPath  The CDB path to use.
762         /// @param run  The run number to use for the CDB.
763         /// @return  True if the generation of the LUT file succeeded.
764         
765         AliHLTMUONTriggerReconstructorComponent comp;
766         
767         if (ddl < 20 or 21 < ddl)
768         {
769                 std::cerr << "ERROR: the DDL number must be in the range [20..21]." << std::endl;
770                 return false;
771         }
772         
773         char ddlNum[32];
774         char runNum[32];
775         sprintf(ddlNum, "%d", ddl+1);
776         sprintf(runNum, "%d", run);
777         const char* argv[7] = {"-ddl", ddlNum, "-cdbpath", cdbPath, "-run", runNum, NULL};
778         int result = comp.DoInit(6, argv);
779         if (result != 0)
780         {
781                 // Error message already generated in DoInit.
782                 return false;
783         }
784         
785         std::fstream file(filename, std::ios::out);
786         if (not file)
787         {
788                 std::cerr << "ERROR: could not open file: " << filename << std::endl;
789                 return false;
790         }
791         
792         file.write(
793                         reinterpret_cast<char*>(comp.fTrigRec->LookupTableBuffer()),
794                         comp.fTrigRec->LookupTableSize()
795                 );
796         if (not file)
797         {
798                 std::cerr << "ERROR: There was a problem writing to the file: " << filename << std::endl;
799                 return false;
800         }
801         file.close();
802         
803         comp.DoDeinit();
804         
805         return true;
806 }