6cf07cdd4a16d638c0c79cf9e0274653f11efaf5
[u/mrichter/AliRoot.git] / HLT / MUON / utils / AliHLTMUONDataCheckerComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 // $Id: AliHLTMUONDataCheckerComponent.cxx 26179 2008-05-29 22:27:27Z aszostak $
18
19 ///
20 /// @file   AliHLTMUONDataCheckerComponent.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
22 /// @date   27 May 2008
23 /// @brief  Implementation of the dHLT data integrity checker component.
24 ///
25 /// This component is used to check the data integrity of dHLT raw internal data
26 /// blocks. If there are any problems found then an appropriate error message is
27 /// logged.
28 ///
29
30 #include "AliHLTMUONDataCheckerComponent.h"
31 #include "AliHLTMUONConstants.h"
32 #include "AliHLTLogging.h"
33 #include "AliHLTSystem.h"
34 #include "AliHLTDefinitions.h"
35 #include "AliRawDataHeader.h"
36 #include "AliMUONConstants.h"
37 #include "AliMUONTrackerDDLDecoder.h"
38 #include "AliMUONTrackerDDLDecoderEventHandler.h"
39 #include "AliMUONTriggerDDLDecoder.h"
40 #include "AliMUONTriggerDDLDecoderEventHandler.h"
41 #include "AliMpDDLStore.h"
42 #include "AliMpDEStore.h"
43 #include "AliMpDEManager.h"
44 #include "AliMpBusPatch.h"
45 #include "AliMpDetElement.h"
46 #include "AliMpSegmentation.h"
47 #include "AliMpVSegmentation.h"
48 #include "AliMpPad.h"
49 #include <cstring>
50 #include <cstdlib>
51 #include <cmath>
52 #include <cerrno>
53 #include <cassert>
54
55
56 namespace
57 {
58         /**
59          * Routine to check if at least one corresponding DDL has been marked
60          * for a particular chamber.
61          */
62         bool ChamberMarkedInDDLList(AliHLTInt32_t chamber, bool ddl[22])
63         {
64                 if (chamber < 0 or chamber > 21) return false;
65                 switch (chamber)
66                 {
67                 case 0:  return ddl[0] or ddl[1];
68                 case 1:  return ddl[2] or ddl[3];
69                 case 2:  return ddl[4] or ddl[5];
70                 case 3:  return ddl[6] or ddl[7];
71                 case 4:  return ddl[8] or ddl[9] or ddl[10] or ddl[11];
72                 case 5:  return ddl[8] or ddl[9] or ddl[10] or ddl[11];
73                 case 6:  return ddl[12] or ddl[13];
74                 case 7:  return ddl[14] or ddl[15];
75                 case 8:  return ddl[16] or ddl[17];
76                 case 9:  return ddl[18] or ddl[19];
77                 case 10: return ddl[20] or ddl[21];
78                 case 11: return ddl[20] or ddl[21];
79                 case 12: return ddl[20] or ddl[21];
80                 case 13: return ddl[20] or ddl[21];
81                 default: return false;
82                 }
83         }
84
85 } // end of namespace
86
87
88 ClassImp(AliHLTMUONDataCheckerComponent)
89
90
91 AliHLTMUONDataCheckerComponent::AliHLTMUONDataCheckerComponent() :
92         AliHLTMUONProcessor(),
93         fIgnoreType(false),
94         fIgnoreSpec(false),
95         fDontForward(false),
96         fFilterBadBlocks(false),
97         fNoGlobalChecks(false),
98         fWarnForUnexpecedBlock(false),
99         fReturnError(false)
100 {
101         /// Default constructor.
102 }
103
104
105 AliHLTMUONDataCheckerComponent::~AliHLTMUONDataCheckerComponent()
106 {
107         /// Default destructor.
108 }
109
110 const char* AliHLTMUONDataCheckerComponent::GetComponentID()
111 {
112         /// Inherited from AliHLTComponent. Returns the component ID.
113         
114         return AliHLTMUONConstants::DataCheckerComponentId();
115 }
116
117
118 void AliHLTMUONDataCheckerComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
119 {
120         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
121         /// At the moment this list is "any data type" origin MUON since it is not known
122         /// before hand what kind of input blocks we will get.
123         
124         assert( list.empty() );
125         list.push_back( kAliHLTAnyDataType | kAliHLTDataOriginMUON );
126 }
127
128
129 AliHLTComponentDataType AliHLTMUONDataCheckerComponent::GetOutputDataType()
130 {
131         /// Inherited from AliHLTComponent. Returns the output data type of
132         /// "any data type" with MUON origin.
133         
134         return kAliHLTAnyDataType | kAliHLTDataOriginMUON;
135 }
136
137
138 void AliHLTMUONDataCheckerComponent::GetOutputDataSize(
139                 unsigned long& constBase, double& inputMultiplier
140         )
141 {
142         /// Inherited from AliHLTComponent.
143         /// Returns an estimate of the expected output data size.
144         
145         // Both of these are zero because we will only ever pass on input data blocks
146         // and never generate data in this component.
147         constBase = 0;
148         inputMultiplier = 0;
149 }
150
151
152 AliHLTComponent* AliHLTMUONDataCheckerComponent::Spawn()
153 {
154         /// Inherited from AliHLTComponent. Creates a new object instance.
155         
156         return new AliHLTMUONDataCheckerComponent;
157 }
158
159
160 bool AliHLTMUONDataCheckerComponent::IgnoreArgument(const char* arg) const
161 {
162         /// Return true if the argument is -delaysetup
163         /// to prevent the parent class from parsing these arguments in DoInit.
164         
165         if (strcmp(arg, "-delaysetup") == 0)
166         {
167                 return true;
168         }
169         else
170         {
171                 return false;
172         }
173 }
174
175
176 int AliHLTMUONDataCheckerComponent::DoInit(int argc, const char** argv)
177 {
178         /// Inherited from AliHLTComponent.
179         /// Parses the command line parameters and initialises the component.
180         
181         HLTInfo("Initialising dHLT data checker component.");
182         
183         // Inherit the parents functionality.
184         int result = AliHLTMUONProcessor::DoInit(argc, argv);
185         if (result != 0) return result;
186
187         // Initialise flags with default values.
188         fIgnoreType = false;
189         fIgnoreSpec = false;
190         fDontForward = false;
191         fFilterBadBlocks = false;
192         fNoGlobalChecks = false;
193         fWarnForUnexpecedBlock = false;
194         fReturnError = false;
195
196         for (int i = 0; i < argc; i++)
197         {
198                 if (ArgumentAlreadyHandled(i, argv[i])) continue;
199
200                 if (strcmp(argv[i], "-ignoretype") == 0)
201                 {
202                         fIgnoreType = true;
203                         HLTInfo("Ignoring data type of data blocks as given by framework.");
204                         continue;
205                 }
206                 if (strcmp(argv[i], "-ignorespec") == 0)
207                 {
208                         fIgnoreSpec = true;
209                         HLTInfo("Ignoring data specification of data blocks as given by framework.");
210                         continue;
211                 }
212                 if (strcmp(argv[i], "-dontforward") == 0)
213                 {
214                         fDontForward = true;
215                         HLTInfo("Not forwarding input data blocks.");
216                         continue;
217                 }
218                 if (strcmp(argv[i], "-filter") == 0)
219                 {
220                         fFilterBadBlocks = true;
221                         HLTInfo("Passing only bad blocks to output.");
222                         continue;
223                 }
224                 if (strcmp(argv[i], "-no_global_check") == 0)
225                 {
226                         fNoGlobalChecks = true;
227                         HLTInfo("Only per block data consistancy checks will be applied,"
228                                 " but no global checks will be made."
229                         );
230                         continue;
231                 }
232                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
233                 {
234                         fWarnForUnexpecedBlock = true;
235                         continue;
236                 }
237                 if (strcmp(argv[i], "-return_error") == 0)
238                 {
239                         fReturnError = true;
240                         continue;
241                 }
242                 
243                 HLTError("Unknown option '%s'.", argv[i]);
244                 return -EINVAL;
245         }
246
247         return 0;
248 }
249
250
251 int AliHLTMUONDataCheckerComponent::DoDeinit()
252 {
253         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
254         
255         HLTInfo("Deinitialising dHLT data checker component.");
256         return 0;
257 }
258
259
260 int AliHLTMUONDataCheckerComponent::DoEvent(
261                 const AliHLTComponentEventData& evtData,
262                 const AliHLTComponentBlockData* blocks,
263                 AliHLTComponentTriggerData& trigData,
264                 AliHLTUInt8_t* /*outputPtr*/,
265                 AliHLTUInt32_t& size,
266                 AliHLTComponentBlockDataList& outputBlocks
267         )
268 {
269         /// Inherited from AliHLTProcessor. Processes the new event data.
270         /// Here we go through the list of input data blocks and apply extensive
271         /// data integrity checking on the data found.
272         
273         if (not IsDataEvent()) return 0;
274         
275         HLTDebug("Processing event %llu with %u input data blocks.",
276                 evtData.fEventID, evtData.fBlockCnt
277         );
278         
279         // Allocate an array of flags indicating if the data block is OK or not,
280         // also arrays to store specific.
281         bool dataProblems = false;
282         bool* blockOk = NULL;
283         typedef const AliHLTComponentBlockData* PAliHLTComponentBlockData;
284         PAliHLTComponentBlockData* trigRecBlocks = NULL;
285         PAliHLTComponentBlockData* trigRecDebugBlocks = NULL;
286         PAliHLTComponentBlockData* hitBlocks = NULL;
287         PAliHLTComponentBlockData* clusterBlocks = NULL;
288         PAliHLTComponentBlockData* channelBlocks = NULL;
289         PAliHLTComponentBlockData* mansoTrackBlocks = NULL;
290         PAliHLTComponentBlockData* mansoCandidateBlocks = NULL;
291         PAliHLTComponentBlockData* trackBlocks = NULL;
292         PAliHLTComponentBlockData* singleDecisionBlocks = NULL;
293         PAliHLTComponentBlockData* pairDecisionBlocks = NULL;
294         AliHLTUInt32_t trigRecBlocksCount = 0;
295         AliHLTUInt32_t trigRecDebugBlocksCount = 0;
296         AliHLTUInt32_t hitBlocksCount = 0;
297         AliHLTUInt32_t clusterBlocksCount = 0;
298         AliHLTUInt32_t channelBlocksCount = 0;
299         AliHLTUInt32_t mansoTrackBlocksCount = 0;
300         AliHLTUInt32_t mansoCandidateBlocksCount = 0;
301         AliHLTUInt32_t trackBlocksCount = 0;
302         AliHLTUInt32_t singleDecisionBlocksCount = 0;
303         AliHLTUInt32_t pairDecisionBlocksCount = 0;
304         try
305         {
306                 blockOk = new bool[evtData.fBlockCnt];
307                 trigRecBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
308                 trigRecDebugBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
309                 hitBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
310                 clusterBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
311                 channelBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
312                 mansoTrackBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
313                 mansoCandidateBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
314                 trackBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
315                 singleDecisionBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
316                 pairDecisionBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
317         }
318         catch (const std::bad_alloc&)
319         {
320                 HLTError("Could not allocate more memory for internal arrays.");
321                 // Make sure to clean up if partially allocated memory.
322                 if (blockOk != NULL) delete [] blockOk;
323                 if (trigRecBlocks != NULL) delete [] trigRecBlocks;
324                 if (trigRecDebugBlocks != NULL) delete [] trigRecDebugBlocks;
325                 if (hitBlocks != NULL) delete [] hitBlocks;
326                 if (clusterBlocks != NULL) delete [] clusterBlocks;
327                 if (channelBlocks != NULL) delete [] channelBlocks;
328                 if (mansoTrackBlocks != NULL) delete [] mansoTrackBlocks;
329                 if (mansoCandidateBlocks != NULL) delete [] mansoCandidateBlocks;
330                 if (trackBlocks != NULL) delete [] trackBlocks;
331                 if (singleDecisionBlocks != NULL) delete [] singleDecisionBlocks;
332                 if (pairDecisionBlocks != NULL) delete [] pairDecisionBlocks;
333                 return -ENOMEM;
334         }
335         
336         AliHLTComponentDataType anyPrivateType = AliHLTComponentDataTypeInitializer(
337                         kAliHLTAnyDataType, kAliHLTDataOriginPrivate
338                 );
339         
340         try
341         {
342                 // Clear all the flags indicating if the blocks are ok.
343                 for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
344                 {
345                         blockOk[n] = false;
346                 }
347         
348                 for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
349                 {
350                         HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
351                                 n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
352                         );
353                         
354                         AliHLTMUONDataBlockType blockType = kUnknownDataBlock;
355                         
356                         if (fIgnoreType)
357                         {
358                                 // Decode the block type if we must ignore the block type
359                                 // as given by the HLT framework.
360                                 if (blocks[n].fSize >= sizeof(AliHLTMUONDataBlockHeader))
361                                 {
362                                         const AliHLTMUONDataBlockHeader* header =
363                                                 reinterpret_cast<const AliHLTMUONDataBlockHeader*>(blocks[n].fPtr);
364                                         blockType = AliHLTMUONDataBlockType(header->fType);
365                                 }
366                         }
367                         else
368                         {
369                                 if (blocks[n].fDataType == anyPrivateType)
370                                 {
371                                         // Completely ignore any private HLT internal block types.
372                                         blockOk[n] = true;
373                                         continue;
374                                 }
375                                 else if (blocks[n].fDataType == AliHLTMUONConstants::DDLRawDataType())
376                                 {
377                                         blockOk[n] = CheckRawDataBlock(blocks[n], n);
378                                         continue;
379                                 }
380                                 else if (blocks[n].fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
381                                 {
382                                         blockType = kTriggerRecordsDataBlock;
383                                 }
384                                 else if (blocks[n].fDataType == AliHLTMUONConstants::TrigRecsDebugBlockDataType())
385                                 {
386                                         blockType = kTrigRecsDebugDataBlock;
387                                 }
388                                 else if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
389                                 {
390                                         blockType = kRecHitsDataBlock;
391                                 }
392                                 else if (blocks[n].fDataType == AliHLTMUONConstants::ClusterBlockDataType())
393                                 {
394                                         blockType = kClustersDataBlock;
395                                 }
396                                 else if (blocks[n].fDataType == AliHLTMUONConstants::ChannelBlockDataType())
397                                 {
398                                         blockType = kChannelsDataBlock;
399                                 }
400                                 else if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
401                                 {
402                                         blockType = kMansoTracksDataBlock;
403                                 }
404                                 else if (blocks[n].fDataType == AliHLTMUONConstants::MansoCandidatesBlockDataType())
405                                 {
406                                         blockType = kMansoCandidatesDataBlock;
407                                 }
408                                 else if (blocks[n].fDataType == AliHLTMUONConstants::TracksBlockDataType())
409                                 {
410                                         blockType = kTracksDataBlock;
411                                 }
412                                 else if (blocks[n].fDataType == AliHLTMUONConstants::SinglesDecisionBlockDataType())
413                                 {
414                                         blockType = kSinglesDecisionDataBlock;
415                                 }
416                                 else if (blocks[n].fDataType == AliHLTMUONConstants::PairsDecisionBlockDataType())
417                                 {
418                                         blockType = kPairsDecisionDataBlock;
419                                 }
420                                 else
421                                 {
422                                         // Log a message indicating that we got a data block that we
423                                         // do not know how to handle.
424                                         if (fWarnForUnexpecedBlock)
425                                                 HLTWarning("Received a data block of a type we cannot"
426                                                         " handle: '%s', spec: 0x%8.8X",
427                                                         DataType2Text(blocks[n].fDataType).c_str(),
428                                                         blocks[n].fSpecification
429                                                 );
430 #ifdef __DEBUG
431                                         else
432                                                 HLTDebug("Received a data block of a type we cannot"
433                                                         " handle: '%s', spec: 0x%8.8X",
434                                                         DataType2Text(blocks[n].fDataType).c_str(),
435                                                         blocks[n].fSpecification
436                                                 );
437 #endif
438                                 }
439                         }
440                         
441                         switch (blockType)
442                         {
443                         case kTriggerRecordsDataBlock:
444                                 blockOk[n] = CheckTriggerRecordsBlock(blocks[n], n);
445                                 trigRecBlocks[trigRecBlocksCount++] = &blocks[n];
446                                 break;
447                         case kTrigRecsDebugDataBlock:
448                                 blockOk[n] = CheckTrigRecsDebugBlock(blocks[n], n);
449                                 trigRecDebugBlocks[trigRecDebugBlocksCount++] = &blocks[n];
450                                 break;
451                         case kRecHitsDataBlock:
452                                 blockOk[n] = CheckRecHitsBlock(blocks[n], n);
453                                 hitBlocks[hitBlocksCount++] = &blocks[n];
454                                 break;
455                         case kClustersDataBlock:
456                                 blockOk[n] = CheckClustersBlock(blocks[n], n);
457                                 clusterBlocks[clusterBlocksCount++] = &blocks[n];
458                                 break;
459                         case kChannelsDataBlock:
460                                 blockOk[n] = CheckChannelsBlock(blocks[n], n);
461                                 channelBlocks[channelBlocksCount++] = &blocks[n];
462                                 break;
463                         case kMansoTracksDataBlock:
464                                 blockOk[n] = CheckMansoTracksBlock(blocks[n], n);
465                                 mansoTrackBlocks[mansoTrackBlocksCount++] = &blocks[n];
466                                 break;
467                         case kMansoCandidatesDataBlock:
468                                 blockOk[n] = CheckMansoCandidatesBlock(blocks[n], n);
469                                 mansoCandidateBlocks[mansoCandidateBlocksCount++] = &blocks[n];
470                                 break;
471                         case kTracksDataBlock:
472                                 blockOk[n] = CheckTracksBlock(blocks[n], n);
473                                 trackBlocks[trackBlocksCount++] = &blocks[n];
474                                 break;
475                         case kSinglesDecisionDataBlock:
476                                 blockOk[n] = CheckSinglesDecisionBlock(blocks[n], n);
477                                 singleDecisionBlocks[singleDecisionBlocksCount++] = &blocks[n];
478                                 break;
479                         case kPairsDecisionDataBlock:
480                                 blockOk[n] = CheckPairsDecisionBlock(blocks[n], n);
481                                 pairDecisionBlocks[pairDecisionBlocksCount++] = &blocks[n];
482                                 break;
483                         default:
484                                 HLTDebug("Received a data block for which we could not decode the data type."
485                                         " fDataType = '%s', fSpecification = 0x%8.8X, fSize = %u bytes.",
486                                         DataType2Text(blocks[n].fDataType).c_str(),
487                                         blocks[n].fSpecification,
488                                         blocks[n].fSize
489                                 );
490                                 break;
491                         }
492                 }
493                 
494                 // Apply the global data consistancy checks if not suppressed by the user.
495                 if (not fNoGlobalChecks)
496                 {
497                         MakeGlobalChecks(
498                                 blocks, blockOk, evtData.fBlockCnt,
499                                 trigRecBlocks, trigRecBlocksCount,
500                                 trigRecDebugBlocks, trigRecDebugBlocksCount,
501                                 hitBlocks, hitBlocksCount,
502                                 clusterBlocks, clusterBlocksCount,
503                                 channelBlocks, channelBlocksCount,
504                                 mansoTrackBlocks, mansoTrackBlocksCount,
505                                 mansoCandidateBlocks, mansoCandidateBlocksCount,
506                                 trackBlocks, trackBlocksCount,
507                                 singleDecisionBlocks, singleDecisionBlocksCount,
508                                 pairDecisionBlocks, pairDecisionBlocksCount
509                         );
510                 }
511                 
512                 // Forward the input data blocks if we have not been asked to drop them.
513                 // Also remember to filter for bad blocks if so specified.
514                 if (not fDontForward)
515                 {
516                         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
517                         {
518                                 if (fFilterBadBlocks and blockOk[n]) continue;
519                                 outputBlocks.push_back(blocks[n]);
520                         }
521                 }
522                 
523                 // Set dataProblems flag is there was at least one block with problems.
524                 for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
525                 {
526                         if (not blockOk[n]) dataProblems = true;
527                 }
528         }
529         finally
530         (
531                 // make sure to cleanup memory
532                 delete [] blockOk;
533                 delete [] trigRecBlocks;
534                 delete [] trigRecDebugBlocks;
535                 delete [] hitBlocks;
536                 delete [] clusterBlocks;
537                 delete [] channelBlocks;
538                 delete [] mansoTrackBlocks;
539                 delete [] mansoCandidateBlocks;
540                 delete [] trackBlocks;
541                 delete [] singleDecisionBlocks;
542                 delete [] pairDecisionBlocks;
543         )
544         
545         // Finally we set the total size of output memory we consumed, which is
546         // zero since we just copied the input descriptors to output if anything.
547         size = 0;
548
549         if (dataProblems and DumpDataOnError()) DumpEvent(evtData, trigData);
550         
551         if (fReturnError)
552         {
553                 // If we were requested to return errors if there were integrity
554                 // problems then check if any data blocks had problems and return
555                 // an error code.
556                 if (dataProblems) return -EFAULT;
557         }
558         return 0;
559 }
560
561
562 bool AliHLTMUONDataCheckerComponent::IsSpecificationValid(
563                 const AliHLTComponentBlockData& block,
564                 AliHLTUInt32_t blockNumber,
565                 const char* name
566         ) const
567 {
568         /// Checks if the specification bits are valid.
569         /// \param  block The block whose specification should be checked.
570         /// \param  blockNumber The block index number being checked.
571         /// \param  name The name of the type of block being checked.
572         /// \returns true if the specification is valid and false otherwise.
573
574         if (AliHLTMUONUtils::IsSpecValid(block.fSpecification))
575                 return true;
576         
577         HLTError("Problem found with data block %d, fDataType = '%s',"
578                  " fPtr = %p and fSize = %u bytes."
579                  " Assuming this is a %s data block."
580                  " Problem: The specification does not contain a valid pattern,"
581                  " received 0x%8.8X for the specification.",
582                 blockNumber,
583                 DataType2Text(block.fDataType).c_str(),
584                 block.fPtr,
585                 block.fSize,
586                 name,
587                 block.fSpecification
588         );
589         return false;
590 }
591
592
593 bool AliHLTMUONDataCheckerComponent::IsFromTrackerOnly(
594                 const AliHLTComponentBlockData& block,
595                 AliHLTUInt32_t blockNumber,
596                 const char* name
597         ) const
598 {
599         /// Checks if the specification bits are valid and indicate the block
600         /// contains data or information only from the tracker DDLs.
601         /// \param  block The block whose specification should be checked.
602         /// \param  blockNumber The block index number being checked.
603         /// \param  name The name of the type of block being checked.
604         /// \returns true if the specification indicates data is only from tracker.
605         
606         bool result = IsSpecificationValid(block, blockNumber, name);
607         
608         if (AliHLTMUONUtils::ContainsDataFromTracker(block.fSpecification) and
609             not AliHLTMUONUtils::ContainsDataFromTrigger(block.fSpecification)
610            )
611         {
612                 return result;
613         }
614         
615         HLTError("Problem found with data block %d, fDataType = '%s',"
616                  " fPtr = %p and fSize = %u bytes."
617                  " Assuming this is a %s data block."
618                  " Problem: The data block does not contain data only from the"
619                  " tracker DDLs as expected."
620                  " Received 0x%8.8X for the specification.",
621                 blockNumber,
622                 DataType2Text(block.fDataType).c_str(),
623                 block.fPtr,
624                 block.fSize,
625                 name,
626                 block.fSpecification
627         );
628         return false;
629 }
630
631
632 bool AliHLTMUONDataCheckerComponent::IsFromTriggerOnly(
633                 const AliHLTComponentBlockData& block,
634                 AliHLTUInt32_t blockNumber,
635                 const char* name
636         ) const
637 {
638         /// Checks if the specification bits are valid and indicate the block
639         /// contains data or information only from the trigger DDLs.
640         /// \param  block The block whose specification should be checked.
641         /// \param  blockNumber The block index number being checked.
642         /// \param  name The name of the type of block being checked.
643         /// \returns true if the specification indicates data is only from trigger.
644         
645         bool result = IsSpecificationValid(block, blockNumber, name);
646         
647         if (AliHLTMUONUtils::ContainsDataFromTrigger(block.fSpecification) and
648             not AliHLTMUONUtils::ContainsDataFromTracker(block.fSpecification)
649            )
650         {
651                 return result;
652         }
653         
654         HLTError("Problem found with data block %d, fDataType = '%s',"
655                  " fPtr = %p and fSize = %u bytes."
656                  " Assuming this is a %s data block."
657                  " Problem: The data block does not contain data only from the"
658                  " trigger DDLs as expected."
659                  " Received 0x%8.8X for the specification.",
660                 blockNumber,
661                 DataType2Text(block.fDataType).c_str(),
662                 block.fPtr,
663                 block.fSize,
664                 name,
665                 block.fSpecification
666         );
667         return false;
668 }
669
670
671 bool AliHLTMUONDataCheckerComponent::IsMomentumVectorOk(
672                 const AliHLTComponentBlockData& block,
673                 AliHLTUInt32_t blockNumber,
674                 const char* name,
675                 AliHLTUInt32_t entryNumber,
676                 AliHLTFloat32_t px,
677                 AliHLTFloat32_t py,
678                 AliHLTFloat32_t pz
679         ) const
680 {
681         /// Checks if the momentum vector is reasonable.
682         /// \param  block The block from which the momentum vector data comes from.
683         /// \param  blockNumber The block index number.
684         /// \param  name The name of the type of block.
685         /// \param  entryNumber The entry index number of the structure holding
686         ///      the momentum vector data.
687         /// \param  px The X coordinate of the momentum vector (GeV/c).
688         /// \param  py The Y coordinate of the momentum vector (GeV/c).
689         /// \param  pz The Z coordinate of the momentum vector (GeV/c).
690         /// \returns true if the momentum vector is valid and false otherwise.
691         
692         // If the momentum vector is nil then ignore it.
693         if (px == 0 and py == 0 and pz == 0) return true;
694         
695         bool result = true;
696         
697         // If the momentum vector is sane then we should not have a particle with
698         // more energy than 14 TeV and momentum should be in the negative direction.
699         double momentum = sqrt(px*px + py*py + pz*pz);
700         if (momentum > 14e3)
701         {
702                 // Just warn since this is a data sanity problem rather
703                 // than a data integrity problem.
704                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
705                         " fPtr = %p and fSize = %u bytes."
706                         " Assuming this is a %s data block."
707                         " Problem with entry %d in block: The momentum vector"
708                         " p = {%f, %f, %f}, |p| = %f looks too big.",
709                         blockNumber,
710                         DataType2Text(block.fDataType).c_str(),
711                         block.fPtr,
712                         block.fSize,
713                         name,
714                         entryNumber,
715                         px, py, pz,
716                         momentum
717                 );
718                 result = false;
719         }
720         
721         if (pz > 0.)
722         {
723                 // Just warn since this is a data sanity problem rather
724                 // than a data integrity problem.
725                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
726                         " fPtr = %p and fSize = %u bytes."
727                         " Assuming this is a %s data block."
728                         " Problem with entry %d in block: The momentum vector"
729                         " p = {%f, %f, %f} points away from the dimuon"
730                         " spectrometer (p_z > 0).",
731                         blockNumber,
732                         DataType2Text(block.fDataType).c_str(),
733                         block.fPtr,
734                         block.fSize,
735                         name,
736                         entryNumber,
737                         px, py, pz
738                 );
739                 result = false;
740         }
741         
742         return result;
743 }
744
745
746 bool AliHLTMUONDataCheckerComponent::AreMomentumCalcParamsOk(
747                 const AliHLTComponentBlockData& block,
748                 AliHLTUInt32_t blockNumber,
749                 const char* name,
750                 AliHLTUInt32_t entryNumber,
751                 AliHLTFloat32_t zmiddle,
752                 AliHLTFloat32_t bl
753         ) const
754 {
755         /// Checks if the parameters for the momentum calculation are reasonable.
756         /// \param  block The block from which the parameter data comes from.
757         /// \param  blockNumber The block index number.
758         /// \param  name The name of the type of block.
759         /// \param  entryNumber The entry index number of the structure holding
760         ///      the parameter data data.
761         /// \param  zmiddle The z-coordinate of the middle of the magnetic field (cm).
762         /// \param  bl The integrated magnetic field (T.m).
763         /// \returns true if the parameters are valid and false otherwise.
764         
765         bool result = true;
766         
767         // Check that the value of the fZmiddle value is somewhere
768         // within the tracking / dipole magnetic field area.
769         if (zmiddle < AliMUONConstants::AbsZEnd() or
770                 zmiddle < AliMUONConstants::MuonFilterZBeg()
771                 )
772         {
773                 // Just warn since this is a data sanity problem rather
774                 // than a data integrity problem.
775                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
776                         " fPtr = %p and fSize = %u bytes."
777                         " Assuming this is a %s data block."
778                         " Problem with entry %d in block: The Z coordinate %f cm"
779                         " used as the middle of the magnetic field in the momentum"
780                         " calculation is outside the dimuon spectrometers dipole"
781                         " magnetic field volume.",
782                         blockNumber,
783                         DataType2Text(block.fDataType).c_str(),
784                         block.fPtr,
785                         block.fSize,
786                         name,
787                         entryNumber,
788                         zmiddle
789                 );
790                 result = false;
791         }
792         
793         // Also check that the value of the 'bl' value is within a
794         // reasonable range: |bl| < Lmax * Bmax, where
795         // Lmax = max length from vertex to end of spectrometer, and
796         // Bmax = max magnetic field of dipole, taken as 1 tesla.
797         // Approximating Lmax * Bmax as 20 T.m
798         if (fabs(bl) > 20.)
799         {
800                 // Just warn since this is a data sanity problem rather
801                 // than a data integrity problem.
802                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
803                         " fPtr = %p and fSize = %u bytes."
804                         " Assuming this is a %s data block."
805                         " Problem with entry %d in block: The integrated magnetic"
806                         " field value %f T.m used in the momentum calculation"
807                         " has an unreasonably large absolute value.",
808                         blockNumber,
809                         DataType2Text(block.fDataType).c_str(),
810                         block.fPtr,
811                         block.fSize,
812                         name,
813                         entryNumber,
814                         bl
815                 );
816                 result = false;
817         }
818         
819         return result;
820 }
821
822
823 bool AliHLTMUONDataCheckerComponent::IsHitCoordinateOk(
824                 const AliHLTComponentBlockData& block,
825                 AliHLTUInt32_t blockNumber,
826                 const char* name,
827                 AliHLTUInt32_t entryNumber,
828                 const AliHLTMUONRecHitStruct& hit,
829                 AliHLTInt32_t minChamber,
830                 AliHLTInt32_t maxChamber,
831                 AliHLTInt32_t expectedChamber,
832                 bool ddl[22]
833         ) const
834 {
835         /// Checks if the hit coordinate is compatible with a the location of a
836         /// dimuon spectrometer chamber. Also, if expectedChamber is not -1, then
837         /// the hit coordinate is checked if to comes from that chamber.
838         /// We also check if the fFlags containing the chamber number and detector
839         /// element ID are correct.
840         /// \param  block The block from which the hit data comes from.
841         /// \param  blockNumber The block index number.
842         /// \param  name The name of the type of block.
843         /// \param  entryNumber The entry index number of the hit.
844         /// \param  hit The hit data being checked.
845         /// \param  minChamber The minimum valid chamber number to check for.
846         /// \param  maxChamber The maximum valid chamber number to check for.
847         /// \param  expectedChamber If not -1 then this is the chamber number to
848         ///      check against.
849         /// \param  ddl  The array decoded by AliHLTMUONUtils::UnpackSpecBits.
850         /// \returns true if the hit is valid and false otherwise.
851         
852         assert( 0 <= minChamber and minChamber < 14 );
853         assert( 0 <= maxChamber and maxChamber < 14 );
854         
855         bool result = true;
856         
857         AliHLTUInt8_t chNum = 0xFF;
858         AliHLTUInt16_t detElemId = 0xFFFF;
859         AliHLTMUONUtils::UnpackRecHitFlags(hit.fFlags, chNum, detElemId);
860         
861         Int_t chamber = AliMUONConstants::ChamberNumber(hit.fZ, false); // false = do not warn.
862         if (chamber < minChamber or maxChamber < chamber)
863         {
864                 HLTError("Problem found with data block %d, fDataType = '%s',"
865                         " fPtr = %p and fSize = %u bytes."
866                         " Assuming this is a %s data block."
867                         " Problem with entry %d in block: The hit {x = %f, y = %f,"
868                         " z = %f} cm has a z-coordinate that does not correspond"
869                         " to the nominal position of any chambers in the range"
870                         " [%d..%d].",
871                         blockNumber,
872                         DataType2Text(block.fDataType).c_str(),
873                         block.fPtr,
874                         block.fSize,
875                         name,
876                         entryNumber,
877                         hit.fX, hit.fY, hit.fZ,
878                         minChamber+1,
879                         maxChamber+1
880                 );
881                 return false;
882         }
883         
884         if (chNum != chamber)
885         {
886                 HLTError("Problem found with data block %d, fDataType = '%s',"
887                         " fPtr = %p and fSize = %u bytes."
888                         " Assuming this is a %s data block."
889                         " Problem with entry %d in block: The hit {x = %f, y = %f,"
890                         " z = %f} cm has a chamber number %d that does not correspond"
891                         " to the expected chamber %d given by the z-coordinate.",
892                         blockNumber,
893                         DataType2Text(block.fDataType).c_str(),
894                         block.fPtr,
895                         block.fSize,
896                         name,
897                         entryNumber,
898                         hit.fX, hit.fY, hit.fZ,
899                         chNum+1,
900                         chamber+1
901                 );
902                 result = false;
903                 if (minChamber <= Int_t(chNum) and Int_t(chNum) <= maxChamber)
904                 {
905                         // Rather use the explicit value in the data if it
906                         // is in range.
907                         chamber = chNum;
908                 }
909         }
910         
911         if (expectedChamber != -1 and chamber != expectedChamber)
912         {
913                 HLTError("Problem found with data block %d, fDataType = '%s',"
914                         " fPtr = %p and fSize = %u bytes."
915                         " Assuming this is a %s data block."
916                         " Problem with entry %d in block: The hit {x = %f, y = %f,"
917                         " z = %f} cm has a position that corresponds to chamber %d,"
918                         " but expected it to be on chamber %d.",
919                         blockNumber,
920                         DataType2Text(block.fDataType).c_str(),
921                         block.fPtr,
922                         block.fSize,
923                         name,
924                         entryNumber,
925                         hit.fX, hit.fY, hit.fZ,
926                         chamber+1,
927                         expectedChamber+1
928                 );
929                 result = false;
930         }
931         
932         AliHLTFloat32_t rmin = AliMUONConstants::Rmin(chamber / 2);
933         AliHLTFloat32_t rmax = AliMUONConstants::Rmax(chamber / 2);
934         AliHLTFloat32_t radius = sqrt(hit.fX*hit.fX + hit.fY*hit.fY);
935         if (radius < rmin or rmax < radius)
936         {
937                 HLTError("Problem found with data block %d, fDataType = '%s',"
938                         " fPtr = %p and fSize = %u bytes."
939                         " Assuming this is a %s data block."
940                         " Problem with entry %d in block: The hit {x = %f, y = %f,"
941                         " z = %f} cm has a position in the X-Y plane that does not"
942                         " correspond to the nominal position of chamber %d.",
943                         blockNumber,
944                         DataType2Text(block.fDataType).c_str(),
945                         block.fPtr,
946                         block.fSize,
947                         name,
948                         entryNumber,
949                         hit.fX, hit.fY, hit.fZ,
950                         chamber+1
951                 );
952                 result = false;
953         }
954         
955         if (not fIgnoreSpec and not ChamberMarkedInDDLList(chamber, ddl))
956         {
957                 HLTError("Problem found with data block %d, fDataType = '%s',"
958                         " fPtr = %p and fSize = %u bytes."
959                         " Assuming this is a %s data block."
960                         " Problem with entry %d in block: The hit {x = %f, y = %f,"
961                         " z = %f} cm has a position that corresponds to chamber %d"
962                         " but the data block specification 0x%8.8X does have a"
963                         " corresponding DDL bit set.",
964                         blockNumber,
965                         DataType2Text(block.fDataType).c_str(),
966                         block.fPtr,
967                         block.fSize,
968                         name,
969                         entryNumber,
970                         hit.fX, hit.fY, hit.fZ,
971                         chamber+1,
972                         block.fSpecification
973                 );
974                 result = false;
975         }
976         
977         // Check that the detector element ID is valid and it corresponds to
978         // the chamber number.
979         if (FetchMappingStores() == 0)  // are stores loaded?
980         {
981                 Bool_t warn = kFALSE;
982                 AliMpDEStore* store = AliMpDEStore::Instance(warn);
983                 AliMpDetElement* de = store->GetDetElement(Int_t(detElemId), warn);
984                 if (de == NULL)
985                 {
986                         HLTError("Problem found with data block %d, fDataType = '%s',"
987                                 " fPtr = %p and fSize = %u bytes."
988                                 " Assuming this is a %s data block."
989                                 " Problem with entry %d in block: The hit {x = %f, y = %f,"
990                                 " z = %f} cm has a detector element ID %d,"
991                                 " which is not valid.",
992                                 blockNumber,
993                                 DataType2Text(block.fDataType).c_str(),
994                                 block.fPtr,
995                                 block.fSize,
996                                 name,
997                                 entryNumber,
998                                 hit.fX, hit.fY, hit.fZ,
999                                 detElemId
1000                         );
1001                         result = false;
1002                 }
1003                         
1004                 // Check that the chamber number from the detector element number
1005                 // has the expected value.
1006                 Int_t ch = AliMpDEManager::GetChamberId(Int_t(detElemId), warn);
1007                 if (ch != chamber)
1008                 {
1009                         HLTError("Problem found with data block %d, fDataType = '%s',"
1010                                 " fPtr = %p and fSize = %u bytes."
1011                                 " Assuming this is a %s data block."
1012                                 " Problem with entry %d in block: The hit {x = %f, y = %f,"
1013                                 " z = %f} cm has a detector element ID %d,"
1014                                 " which does not correspond to the chamber %d.",
1015                                 blockNumber,
1016                                 DataType2Text(block.fDataType).c_str(),
1017                                 block.fPtr,
1018                                 block.fSize,
1019                                 name,
1020                                 entryNumber,
1021                                 hit.fX, hit.fY, hit.fZ,
1022                                 detElemId,
1023                                 chamber+1
1024                         );
1025                         result = false;
1026                 }
1027         }
1028         else
1029         {
1030                 HLTWarning("Cannot check a hit's detector element ID information"
1031                         " without being able to load the mapping from CDB."
1032                 );
1033                 result = false;
1034         }
1035         
1036         return result;
1037 }
1038
1039
1040 bool AliHLTMUONDataCheckerComponent::IsMansoTrackOk(
1041                 const AliHLTComponentBlockData& block,
1042                 AliHLTUInt32_t blockNumber,
1043                 const char* name,
1044                 AliHLTUInt32_t entryNumber,
1045                 const AliHLTMUONMansoTrackStruct& track,
1046                 bool ddl[22]
1047         ) const
1048 {
1049         /// Checks if the Manso track structure is Ok.
1050         /// \param  block The block from which the track data comes from.
1051         /// \param  blockNumber The block index number.
1052         /// \param  name The name of the type of block.
1053         /// \param  entryNumber The entry index number of the structure in the
1054         ///      block being checked.
1055         /// \param  track The Manso track data being checked.
1056         /// \param  ddl  The array decoded by AliHLTMUONUtils::UnpackSpecBits.
1057         /// \returns true if the Manso track is valid and false otherwise.
1058         
1059         bool result = true;
1060         
1061         // Chi^2 should not be greater than the worst fit possible, estimated
1062         // as the diameter of largest chamber times the number of points
1063         // findable in a track. Max points is 10 tracker chambers times
1064         // 2 cathodes + 4 trigger chambers.
1065         if (track.fChi2 > AliMUONConstants::Dmax(6)*AliMUONConstants::Dmax(6)*(10*2+4))
1066         {
1067                 // Just a warning since this is not technically an
1068                 // integrity problem.
1069                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
1070                         " fPtr = %p and fSize = %u bytes."
1071                         " Assuming this is a %s data block."
1072                         " Problem with entry %d in block: The Manso track has"
1073                         " the chi squared value of %f that is unreasonably big.",
1074                         blockNumber,
1075                         DataType2Text(block.fDataType).c_str(),
1076                         block.fPtr,
1077                         block.fSize,
1078                         name,
1079                         entryNumber,
1080                         track.fChi2
1081                 );
1082                 result = false;
1083         }
1084         
1085         // Check if the momentum vector is reasonable.
1086         bool momOk = IsMomentumVectorOk(
1087                         block, blockNumber, name, entryNumber,
1088                         track.fPx, track.fPy, track.fPz
1089                 );
1090         if (not momOk) result = false;
1091         
1092         AliHLTMUONParticleSign sign;
1093         bool hitset[4];
1094         AliHLTMUONUtils::UnpackMansoTrackFlags(track.fFlags, sign, hitset);
1095         
1096         // Min and max allowed chamber numbers for hits:
1097         Int_t minCh = 0;
1098         Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
1099         
1100         // Check that this hit coordinates are OK.
1101         for (AliHLTUInt32_t i = 0; i < 4; i++)
1102         {
1103                 if (not hitset[i]) continue; // ignore hits that are not initialised.
1104                 bool hitOk = IsHitCoordinateOk(
1105                                 block, blockNumber, name, entryNumber, track.fHit[i],
1106                                 minCh, maxCh, i+6, ddl
1107                         );
1108                 if (not hitOk) result = false;
1109         }
1110         
1111         return result;
1112 }
1113
1114
1115 bool AliHLTMUONDataCheckerComponent::IsTrackOk(
1116                 const AliHLTComponentBlockData& block,
1117                 AliHLTUInt32_t blockNumber,
1118                 const char* name,
1119                 AliHLTUInt32_t entryNumber,
1120                 const AliHLTMUONTrackStruct& track,
1121                 bool ddl[22]
1122         ) const
1123 {
1124         /// Checks if the full track structure is Ok.
1125         /// \param  block The block from which the track data comes from.
1126         /// \param  blockNumber The block index number.
1127         /// \param  name The name of the type of block.
1128         /// \param  entryNumber The entry index number of the structure in the
1129         ///      block being checked.
1130         /// \param  track The track data being checked.
1131         /// \param  ddl  The array decoded by AliHLTMUONUtils::UnpackSpecBits.
1132         /// \returns true if the full track structure is valid and false otherwise.
1133         
1134         bool result = true;
1135         
1136         // Chi^2 should not be greater than the worst fit possible, estimated
1137         // as the diameter of largest chamber times the number of points
1138         // findable in a track. Max points is 10 tracker chambers times
1139         // 2 cathodes + 4 trigger chambers.
1140         if (track.fChi2 > AliMUONConstants::Dmax(6)*AliMUONConstants::Dmax(6)*(10*2+4))
1141         {
1142                 // Just a warning since this is not technically an
1143                 // integrity problem.
1144                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
1145                         " fPtr = %p and fSize = %u bytes."
1146                         " Assuming this is a %s data block."
1147                         " Problem with entry %d in block: The track has"
1148                         " the chi squared value of %f that is unreasonably big.",
1149                         blockNumber,
1150                         DataType2Text(block.fDataType).c_str(),
1151                         block.fPtr,
1152                         block.fSize,
1153                         name,
1154                         entryNumber,
1155                         track.fChi2
1156                 );
1157                 result = false;
1158         }
1159         
1160         // Check if the momentum vector is reasonable.
1161         bool momOk = IsMomentumVectorOk(
1162                         block, blockNumber, name, entryNumber,
1163                         track.fPx, track.fPy, track.fPz
1164                 );
1165         if (not momOk) result = false;
1166         
1167         // Check that the momentum parameters correspond to the momentum vector.
1168         double momvalue = sqrt(track.fPy*track.fPy + track.fPz*track.fPz);
1169         double invMom = (momvalue != 0 ? 1. / momvalue : 0);
1170         if (TMath::Abs(invMom - TMath::Abs(track.fInverseBendingMomentum)) > 1e-12)
1171         {
1172                 HLTError("Problem found with data block %d, fDataType = '%s',"
1173                         " fPtr = %p and fSize = %u bytes."
1174                         " Assuming this is a %s data block."
1175                         " Problem with entry %d in block: The track's inverse bending"
1176                         " momentum %f does not correspond to the momentum vector.",
1177                         blockNumber,
1178                         DataType2Text(block.fDataType).c_str(),
1179                         block.fPtr,
1180                         block.fSize,
1181                         name,
1182                         entryNumber,
1183                         track.fInverseBendingMomentum
1184                 );
1185                 result = false;
1186         }
1187         if (track.fPz != 0 and TMath::Abs(track.fPx/track.fPz - track.fThetaX) > 1e-12)
1188         {
1189                 HLTError("Problem found with data block %d, fDataType = '%s',"
1190                         " fPtr = %p and fSize = %u bytes."
1191                         " Assuming this is a %s data block."
1192                         " Problem with entry %d in block: The track's non-bending plane"
1193                         " slope parameter %f does not correspond to the momentum vector.",
1194                         blockNumber,
1195                         DataType2Text(block.fDataType).c_str(),
1196                         block.fPtr,
1197                         block.fSize,
1198                         name,
1199                         entryNumber,
1200                         track.fThetaX
1201                 );
1202                 result = false;
1203         }
1204         if (track.fPz != 0 and TMath::Abs(track.fPy/track.fPz - track.fThetaY) > 1e-12)
1205         {
1206                 HLTError("Problem found with data block %d, fDataType = '%s',"
1207                         " fPtr = %p and fSize = %u bytes."
1208                         " Assuming this is a %s data block."
1209                         " Problem with entry %d in block: The track's bending plane"
1210                         " slope parameter %f does not correspond to the momentum vector.",
1211                         blockNumber,
1212                         DataType2Text(block.fDataType).c_str(),
1213                         block.fPtr,
1214                         block.fSize,
1215                         name,
1216                         entryNumber,
1217                         track.fThetaY
1218                 );
1219                 result = false;
1220         }
1221         
1222         // Check that the DCA vertex is reasonable. i.e. the vertex is within
1223         // a 1 meter cube of the origin.
1224         if (TMath::Abs(track.fX) > 100 or TMath::Abs(track.fY) > 100 or TMath::Abs(track.fZ) > 100)
1225         {
1226                 // Just a warning since this is not technically an integrity problem.
1227                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
1228                         " fPtr = %p and fSize = %u bytes."
1229                         " Assuming this is a %s data block."
1230                         " Problem with entry %d in block: The track's distance of closest"
1231                         " approach (DCA) vertex (x, y, z) = (%f, %f, %f) is not a reasonable value.",
1232                         blockNumber,
1233                         DataType2Text(block.fDataType).c_str(),
1234                         block.fPtr,
1235                         block.fSize,
1236                         name,
1237                         entryNumber,
1238                         track.fX, track.fY, track.fZ
1239                 );
1240                 result = false;
1241         }
1242         
1243         AliHLTMUONParticleSign sign;
1244         bool hitset[16];
1245         AliHLTMUONUtils::UnpackTrackFlags(track.fFlags, sign, hitset);
1246         
1247         // Min and max allowed chamber numbers for hits:
1248         Int_t minCh = 0;
1249         Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
1250         
1251         // Check that this hit coordinates are OK.
1252         for (AliHLTUInt32_t i = 0; i < 16; i++)
1253         {
1254                 if (not hitset[i]) continue; // ignore hits that are not initialised.
1255                 bool hitOk = IsHitCoordinateOk(
1256                                 block, blockNumber, name, entryNumber, track.fHit[i],
1257                                 minCh, maxCh, -1, ddl
1258                         );
1259                 if (not hitOk) result = false;
1260         }
1261         
1262         return result;
1263 }
1264
1265
1266 bool AliHLTMUONDataCheckerComponent::CheckDetElemIds(
1267                 const AliHLTComponentBlockData& infoBlock,
1268                 AliHLTUInt32_t infoBlockNumber,
1269                 AliHLTUInt32_t infoEntryNumber,
1270                 const AliHLTMUONTrigRecInfoStruct& info,
1271                 const AliHLTComponentBlockData& trBlock,
1272                 AliHLTUInt32_t trBlockNumber,
1273                 AliHLTUInt32_t trEntryNumber,
1274                 const AliHLTMUONTriggerRecordStruct& tr
1275         ) const
1276 {
1277         /// Checks if the detector element IDs are the same in the debug
1278         /// information structure and the trigger record structure.
1279         /// \param  infoBlock The debug information block from which the 'info'
1280         ///      data comes from.
1281         /// \param  infoBlockNumber The debug information block index number.
1282         /// \param  infoEntryNumber The entry index number of the 'info'
1283         ///      structure in the debug information data block.
1284         /// \param  info  The debug information structure being checked.
1285         /// \param  trBlock The trigger record block from which the 'tr' data
1286         ///      comes from.
1287         /// \param  trBlockNumber The trigger record block index number.
1288         /// \param  trEntryNumber The entry index number of the 'tr' structure
1289         ///      in the trigger record data block.
1290         /// \param  tr  The trigger record structure being checked.
1291         /// \returns true if the detector element IDs are the same and false
1292         ///      otherwise.
1293         
1294         bool result = true;
1295         
1296         for (int i = 0; i < 4; i++)
1297         {
1298                 AliHLTUInt8_t chamber = 0xFF;
1299                 AliHLTUInt16_t detElemId = 0xFFFF;
1300                 AliHLTMUONUtils::UnpackRecHitFlags(tr.fHit[i].fFlags, chamber, detElemId);
1301                 if (info.fDetElemId[i] == detElemId) continue;
1302                 
1303                 HLTError("Problem found with trigger record debug information %d"
1304                         " in data block %d (fDataType = '%s', fPtr = %p, fSize"
1305                         " = %u bytes) and trigger record %d in data block %d"
1306                         " (fDataType = '%s', fPtr = %p, fSize = %u bytes):"
1307                         " The detection element ID %d for chamber %d in the debug"
1308                         " information, is not the same as %d"
1309                         " found in the trigger record.",
1310                         infoEntryNumber,
1311                         infoBlockNumber,
1312                         DataType2Text(infoBlock.fDataType).c_str(),
1313                         infoBlock.fPtr,
1314                         infoBlock.fSize,
1315                         trEntryNumber,
1316                         trBlockNumber,
1317                         DataType2Text(trBlock.fDataType).c_str(),
1318                         trBlock.fPtr,
1319                         trBlock.fSize,
1320                         info.fDetElemId[i],
1321                         i+11,
1322                         detElemId
1323                 );
1324                 result = false;
1325         }
1326         
1327         return result;
1328 }
1329
1330
1331 bool AliHLTMUONDataCheckerComponent::CheckDetElemIds(
1332                 const AliHLTComponentBlockData& clusterBlock,
1333                 AliHLTUInt32_t clusterBlockNumber,
1334                 AliHLTUInt32_t clusterEntryNumber,
1335                 const AliHLTMUONClusterStruct& cluster,
1336                 const AliHLTComponentBlockData& hitBlock,
1337                 AliHLTUInt32_t hitBlockNumber,
1338                 AliHLTUInt32_t hitEntryNumber,
1339                 const AliHLTMUONRecHitStruct& hit
1340         ) const
1341 {
1342         /// Checks if the detector element IDs are the same in the cluster
1343         /// structure and the reconstructed hit structure.
1344         /// \param  clusterBlock The cluster block from which the 'cluster' data
1345         ///      comes from.
1346         /// \param  clusterBlockNumber The cluster block index number.
1347         /// \param  clusterEntryNumber The entry index number of the 'cluster'
1348         ///      structure in the cluster data block.
1349         /// \param  cluster  The cluster structure being checked.
1350         /// \param  hitBlock The reconstructed hit block from which the 'hit'
1351         ///      data comes from.
1352         /// \param  hitBlockNumber The reconstructed hit block index number.
1353         /// \param  hitEntryNumber The entry index number of the 'hit' structure
1354         ///      in the reconstructed hit data block.
1355         /// \param  hit  The trigger record structure being checked.
1356         /// \returns true if the detector element IDs are the same and false
1357         ///      otherwise.
1358         
1359         bool result = true;
1360         
1361         AliHLTUInt8_t chamber = 0xFF;
1362         AliHLTUInt16_t detElemId = 0xFFFF;
1363         AliHLTMUONUtils::UnpackRecHitFlags(hit.fFlags, chamber, detElemId);
1364         if (cluster.fDetElemId != detElemId)
1365         {
1366                 HLTError("Problem found with cluster %d in data block %d"
1367                         " (fDataType = '%s', fPtr = %p, fSize = %u bytes)"
1368                         " and reconstructed hit %d in data block %d"
1369                         " (fDataType = '%s', fPtr = %p, fSize = %u bytes):"
1370                         " The detection element ID %d in the cluster, is not"
1371                         " the same as %d found in the reconstructed hit.",
1372                         clusterEntryNumber,
1373                         clusterBlockNumber,
1374                         DataType2Text(clusterBlock.fDataType).c_str(),
1375                         clusterBlock.fPtr,
1376                         clusterBlock.fSize,
1377                         hitEntryNumber,
1378                         hitBlockNumber,
1379                         DataType2Text(hitBlock.fDataType).c_str(),
1380                         hitBlock.fPtr,
1381                         hitBlock.fSize,
1382                         cluster.fDetElemId,
1383                         detElemId
1384                 );
1385                 result = false;
1386         }
1387         
1388         return result;
1389 }
1390
1391
1392 namespace
1393 {
1394         /**
1395          * Class for logging errors found in raw DDL data.
1396          */
1397         class AliHLTMUONDecoderHandler : public AliHLTLogging
1398         {
1399         public:
1400         
1401                 /// Default constructor
1402                 AliHLTMUONDecoderHandler() :
1403                         AliHLTLogging(),
1404                         fBufferStart(NULL),
1405                         fDescriptor(NULL),
1406                         fBlockNumber(0)
1407                 {
1408                 }
1409                 
1410                 /// Default destructor.
1411                 virtual ~AliHLTMUONDecoderHandler() {}
1412                 
1413                 /// Sets the DDL raw data block descriptor.
1414                 void SetDescriptor(const AliHLTComponentBlockData* b) { fDescriptor = b; }
1415                 
1416                 /// Sets the block number of the raw data block descriptor.
1417                 void SetBlockNumber(AliHLTUInt32_t n) { fBlockNumber = n; }
1418                 
1419                 /// Logs an error message describing the problem with the DDL raw data.
1420                 template <typename ErrorCode, class DecoderHandler>
1421                 void LogError(ErrorCode code, const void* location, DecoderHandler& handler);
1422         
1423         protected:
1424                 // Do not allow copying of this class.
1425                 /// Not implemented
1426                 AliHLTMUONDecoderHandler(const AliHLTMUONDecoderHandler& rhs); // copy constructor
1427                 /// Not implemented
1428                 AliHLTMUONDecoderHandler& operator = (const AliHLTMUONDecoderHandler& rhs); // assignment operator
1429                 
1430                 const void* fBufferStart; ///< Pointer to the start of the current DDL payload buffer.
1431                 const AliHLTComponentBlockData* fDescriptor; ///< Descriptor for the DDL raw data block corresponding to the buffer.
1432                 AliHLTUInt32_t fBlockNumber;  ///< The number / index of the block descriptor.
1433         };
1434         
1435         
1436         template <typename ErrorCode, class DecoderHandler>
1437         void AliHLTMUONDecoderHandler::LogError(ErrorCode code, const void* location, DecoderHandler& handler)
1438         {
1439                 /// Logs a HLT error message describing the problem with the raw DDL data.
1440                 /// \param code  The error code describing the problem.
1441                 /// \param location  A pointer to the location in the raw data buffer
1442                 ///      where the problem was found.
1443                 /// \param handler  The decoder handler object.
1444                 
1445                 long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
1446                 
1447                 // create data type string.
1448                 char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
1449                 memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
1450                 strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
1451                 strncat( dataType, ":", 1 );
1452                 strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
1453                 
1454                 HLTError("Problem found with data block %d, fDataType = '%s',"
1455                          " fPtr = %p and fSize = %u bytes."
1456                          " Assuming this is a DDL raw data block."
1457                          " Problem: %s (Error code: %d, at byte %d)",
1458                         fBlockNumber,
1459                         &dataType[0],
1460                         fDescriptor->fPtr,
1461                         fDescriptor->fSize,
1462                         handler.ErrorCodeToMessage(code),
1463                         code,
1464                         bytepos
1465                 );
1466         };
1467         
1468         
1469         /**
1470          * Class for logging decoding errors when checking tracker raw DDL data.
1471          * Used in the AliHLTMUONDataCheckerComponent::CheckRawDataBlock method.
1472          */
1473         class AliHLTMUONTrackerDecoderHandler :
1474                 public AliMUONTrackerDDLDecoderEventHandler, public AliHLTMUONDecoderHandler
1475         {
1476         public:
1477                 AliHLTMUONTrackerDecoderHandler() :
1478                         AliMUONTrackerDDLDecoderEventHandler(),
1479                         AliHLTMUONDecoderHandler(),
1480                         fMaxDigits(0),
1481                         fDigitCount(0),
1482                         fDigits(NULL),
1483                         fCurrentBusPatch(0),
1484                         fDataProblems(false)
1485                 {}
1486                 
1487                 virtual ~AliHLTMUONTrackerDecoderHandler()
1488                 {
1489                         if (fDigits != NULL) delete [] fDigits;
1490                 }
1491                 
1492                 /// Structure to store raw data words found in the raw data.
1493                 struct AliDigit
1494                 {
1495                         UInt_t fBusPatchId;  ///< Bus patch ID for the data word.
1496                         UInt_t fDataWord;   ///< Raw data word found in the DDL payload.
1497                 };
1498                 
1499                 /// Returns the number of digits found.
1500                 UInt_t DigitCount() const { return fDigitCount; }
1501                 
1502                 /// Returns the array of digits found.
1503                 const AliDigit* Digits() const { return fDigits; }
1504                 
1505                 /// Returns true if there were problems with the data.
1506                 bool DataProblems() const { return fDataProblems; }
1507                 
1508                 // Methods inherited from AliMUONTrackerDDLDecoderEventHandler:
1509                 
1510                 /// Called for each new buffer.
1511                 void OnNewBuffer(const void* buffer, UInt_t bufferSize);
1512                 
1513                 /// Called for each new DSP header.
1514                 void OnNewDSP(const AliMUONDSPHeaderStruct* header, const void* /*data*/);
1515                 
1516                 /// Called for each new bus patch. Just marks the current bus patch ID.
1517                 void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/)
1518                 {
1519                         fCurrentBusPatch = header->fBusPatchId;
1520                 }
1521                 
1522                 /// Called for each new data word found.
1523                 void OnData(UInt_t data, bool /*parityError*/);
1524                 
1525                 /// Logs an error message if there was a decoding problem with the DDL payload.
1526                 void OnError(ErrorCode code, const void* location)
1527                 {
1528                         fDataProblems = true;
1529                         LogError(code, location, *this);
1530                 }
1531         
1532         private:
1533         
1534                 // Do not allow copying of this object.
1535                 /// Not implemented.
1536                 AliHLTMUONTrackerDecoderHandler(const AliHLTMUONTrackerDecoderHandler& obj);
1537                 /// Not implemented.
1538                 AliHLTMUONTrackerDecoderHandler& operator = (const AliHLTMUONTrackerDecoderHandler& obj);
1539                 
1540                 UInt_t fMaxDigits;  ///< Maximum number of digits that can be stored in fDigits.
1541                 UInt_t fDigitCount;  ///< The number of digits currently stored in fDigits.
1542                 AliDigit* fDigits;  ///< The array of digits found in the DDL data.
1543                 UInt_t fCurrentBusPatch;  ///< The current bus patch ID being processed.
1544                 bool fDataProblems;  ///< flag indicating there were problems with the data.
1545         };
1546         
1547         
1548         void AliHLTMUONTrackerDecoderHandler::OnNewBuffer(const void* buffer, UInt_t bufferSize)
1549         {
1550                 /// Called for a new buffer. It will reset internal counters and
1551                 /// resize the digits array if necessary.
1552                 
1553                 fDataProblems = false;
1554                 fDigitCount = 0;
1555                 fBufferStart = buffer;
1556                 
1557                 // Resize the fDigits array to be able to store
1558                 // all the digits in the data buffer.
1559                 UInt_t maxSize = bufferSize / sizeof(UInt_t) + 1;
1560                 if (maxSize > fMaxDigits)
1561                 {
1562                         if (fDigits != NULL)
1563                         {
1564                                 delete [] fDigits;
1565                                 fDigits = NULL;
1566                                 fMaxDigits = 0;
1567                         }
1568                         try
1569                         {
1570                                 fDigits = new AliDigit[maxSize];
1571                                 fMaxDigits = maxSize;
1572                         }
1573                         catch (const std::bad_alloc&)
1574                         {
1575                                 HLTError("Could not allocate enough buffer space for internal arrays.");
1576                                 return;
1577                         }
1578                 }
1579         }
1580         
1581         
1582         void AliHLTMUONTrackerDecoderHandler::OnNewDSP(
1583                         const AliMUONDSPHeaderStruct* header, const void* /*data*/
1584                 )
1585         {
1586                 if (header->fPaddingWord != 0 and header->fPaddingWord != 1)
1587                 {
1588                         // create data type string.
1589                         char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
1590                         memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
1591                         strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
1592                         strncat( dataType, ":", 1 );
1593                         strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
1594                                 
1595                         HLTError("Problem found with data block %d, fDataType = '%s',"
1596                                 " fPtr = %p and fSize = %u bytes."
1597                                 " Assuming this is a tracker DDL raw data block."
1598                                 " Problem: Found padding word marker 0x%8.8X in DSP"
1599                                 " header with DSP ID %d which has an invalid value.",
1600                                 fBlockNumber,
1601                                 &dataType[0],
1602                                 fDescriptor->fPtr,
1603                                 fDescriptor->fSize,
1604                                 header->fPaddingWord,
1605                                 header->fDSPId
1606                         );
1607                         fDataProblems = true;
1608                         return;
1609                 }
1610         }
1611         
1612         
1613         void AliHLTMUONTrackerDecoderHandler::OnData(UInt_t data, bool /*parityError*/)
1614         {
1615                 /// Called for each new data word found. This method will add
1616                 /// these to the list of digits and check if they are not duplicated.
1617                 
1618                 assert( fDigits != NULL );
1619                 
1620                 if ((data & 0x60000000) != 0)
1621                 {
1622                         // create data type string.
1623                         char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
1624                         memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
1625                         strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
1626                         strncat( dataType, ":", 1 );
1627                         strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
1628                                 
1629                         HLTError("Problem found with data block %d, fDataType = '%s',"
1630                                 " fPtr = %p and fSize = %u bytes."
1631                                 " Assuming this is a tracker DDL raw data block."
1632                                 " Problem: Found a data word 0x%8.8X for bus patch %d"
1633                                 " whose bits 29 or 30 are not zero.",
1634                                 fBlockNumber,
1635                                 &dataType[0],
1636                                 fDescriptor->fPtr,
1637                                 fDescriptor->fSize,
1638                                 data,
1639                                 fCurrentBusPatch
1640                         );
1641                         fDataProblems = true;
1642                         return;
1643                 }
1644                 
1645                 // Check if the data word + bus patch have been duplicated.
1646                 for (UInt_t i = 0; i < fDigitCount; i++)
1647                 {
1648                         if (fDigits[i].fDataWord == data and fDigits[i].fBusPatchId == fCurrentBusPatch)
1649                         {
1650                                 // create data type string.
1651                                 char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
1652                                 memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
1653                                 strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
1654                                 strncat( dataType, ":", 1 );
1655                                 strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
1656                                 
1657                                 HLTError("Problem found with data block %d, fDataType = '%s',"
1658                                         " fPtr = %p and fSize = %u bytes."
1659                                         " Assuming this is a tracker DDL raw data block."
1660                                         " Problem: Found a duplicate data word 0x%8.8X for bus patch %d.",
1661                                         fBlockNumber,
1662                                         &dataType[0],
1663                                         fDescriptor->fPtr,
1664                                         fDescriptor->fSize,
1665                                         data,
1666                                         fCurrentBusPatch
1667                                 );
1668                                 fDataProblems = true;
1669                                 return;
1670                         }
1671                 }
1672                 
1673                 // Add the data word + bus patch to the list of decoded digits.
1674                 if (fDigitCount < fMaxDigits)
1675                 {
1676                         fDigits[fDigitCount].fBusPatchId = fCurrentBusPatch;
1677                         fDigits[fDigitCount].fDataWord = data;
1678                         fDigitCount++;
1679                 }
1680         }
1681         
1682         /**
1683          * Class for logging decoding errors when checking trigger raw DDL data.
1684          * Used in the AliHLTMUONDataCheckerComponent::CheckRawDataBlock method.
1685          */
1686         class AliHLTMUONTriggerDecoderHandler :
1687                 public AliMUONTriggerDDLDecoderEventHandler, public AliHLTMUONDecoderHandler
1688         {
1689         public:
1690                 // Methods inherited from AliMUONTriggerDDLDecoderEventHandler:
1691                 
1692                 /// Called for each new buffer.
1693                 void OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
1694                 {
1695                         fBufferStart = buffer;
1696                 }
1697                 
1698                 /// Logs an error message if there was a decoding problem with the DDL payload.
1699                 void OnError(ErrorCode code, const void* location)
1700                 {
1701                         LogError(code, location, *this);
1702                 }
1703         };
1704         
1705 } // end of namespace
1706
1707
1708 bool AliHLTMUONDataCheckerComponent::CheckRawDataBlock(
1709                 const AliHLTComponentBlockData& block,
1710                 AliHLTUInt32_t blockNumber
1711         ) const
1712 {
1713         /// Checks the validity of a raw data block.
1714         
1715         bool result = true;
1716
1717         if (fIgnoreSpec)
1718         {
1719                 HLTWarning("Not able to check DDL raw data if -ignorespec is specified.");
1720                 return false;
1721         }
1722         
1723         bool ddl[22];
1724         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
1725         
1726         // Check that only one DDL was marked in the specification.
1727         int ddlIndex = -1;
1728         for (int i = 0; i < 22; i++)
1729         {
1730                 if (not ddl[i]) continue;
1731                 
1732                 if (ddlIndex == -1)
1733                 {
1734                         ddlIndex = i;
1735                         continue;
1736                 }
1737                 
1738                 HLTError("Problem found with data block %d, fDataType = '%s',"
1739                          " fPtr = %p and fSize = %u bytes."
1740                          " Assuming this is a DDL raw data block."
1741                          " Problem: The specification indicates multiple"
1742                          " DDL sources, DDL %d and %d.",
1743                         blockNumber,
1744                         DataType2Text(block.fDataType).c_str(),
1745                         block.fPtr,
1746                         block.fSize,
1747                         ddlIndex,
1748                         i
1749                 );
1750                 result = false;
1751         }
1752         
1753         // Check the DDL common data header.
1754         AliHLTUInt32_t totalDDLSize = block.fSize;
1755         if (totalDDLSize < sizeof(AliRawDataHeader))
1756         {
1757                 HLTError("Problem found with data block %d, fDataType = '%s',"
1758                          " fPtr = %p and fSize = %u bytes."
1759                          " Assuming this is a DDL raw data block."
1760                          " Problem: The size of the data block is too short to contain"
1761                          " a valid common DDL data header. Size of buffer is only %d"
1762                          " bytes, but expected at least %d bytes.",
1763                         blockNumber,
1764                         DataType2Text(block.fDataType).c_str(),
1765                         block.fPtr,
1766                         block.fSize,
1767                         totalDDLSize,
1768                         sizeof(AliRawDataHeader)
1769                 );
1770                 return false;
1771         }
1772         
1773         const AliRawDataHeader* header =
1774                 reinterpret_cast<const AliRawDataHeader*>(block.fPtr);
1775         
1776         if (header->GetVersion() != 2)
1777         {
1778                 HLTError("Problem found with data block %d, fDataType = '%s',"
1779                          " fPtr = %p and fSize = %u bytes."
1780                          " Assuming this is a DDL raw data block."
1781                          " Problem: The common DDL data header indicates an"
1782                          " incorrect version number. Expected 2 but got %d.",
1783                         blockNumber,
1784                         DataType2Text(block.fDataType).c_str(),
1785                         block.fPtr,
1786                         block.fSize,
1787                         int( header->GetVersion() )
1788                 );
1789                 result = false;
1790         }
1791         
1792         if (header->fSize != 0xFFFFFFFF and header->fSize != block.fSize)
1793         {
1794                 HLTError("Problem found with data block %d, fDataType = '%s',"
1795                          " fPtr = %p and fSize = %u bytes."
1796                          " Assuming this is a DDL raw data block."
1797                          " Problem: The common DDL data header indicates an"
1798                          " incorrect DDL buffer size. Expected %d bytes but"
1799                          " size reported in header is %d bytes.",
1800                         blockNumber,
1801                         DataType2Text(block.fDataType).c_str(),
1802                         block.fPtr,
1803                         block.fSize,
1804                         block.fSize,
1805                         header->fSize
1806                 );
1807                 result = false;
1808         }
1809         
1810         if (header->fSize != 0xFFFFFFFF and header->fSize != block.fSize)
1811         {
1812                 HLTError("Problem found with data block %d, fDataType = '%s',"
1813                          " fPtr = %p and fSize = %u bytes."
1814                          " Assuming this is a DDL raw data block."
1815                          " Problem: The common DDL data header indicates an"
1816                          " incorrect DDL buffer size. Expected %d bytes but"
1817                          " size reported in header is %d bytes.",
1818                         blockNumber,
1819                         DataType2Text(block.fDataType).c_str(),
1820                         block.fPtr,
1821                         block.fSize,
1822                         block.fSize,
1823                         header->fSize
1824                 );
1825                 result = false;
1826         }
1827         
1828         // Check that the bits that should be zero in the CDH are infact zero.
1829         if ((header->fWord2 & 0x00C03000) != 0 or
1830             (header->fEventID2 & 0xFF000000) != 0 or
1831             (header->fStatusMiniEventID & 0xF0000000) != 0 or
1832             (header->fROILowTriggerClassHigh & 0x0FFC0000) != 0
1833            )
1834         {
1835                 HLTError("Problem found with data block %d, fDataType = '%s',"
1836                          " fPtr = %p and fSize = %u bytes."
1837                          " Assuming this is a DDL raw data block."
1838                          " Problem: The common DDL data header has non-zero"
1839                          " bits that are reserved and must be set to zero.",
1840                         blockNumber,
1841                         DataType2Text(block.fDataType).c_str(),
1842                         block.fPtr,
1843                         block.fSize
1844                 );
1845                 result = false;
1846         }
1847         
1848         AliHLTUInt32_t payloadSize = block.fSize - sizeof(AliRawDataHeader);
1849         const AliHLTUInt8_t* payload =
1850                 reinterpret_cast<const AliHLTUInt8_t*>(header + 1);
1851         
1852         if (AliHLTMUONUtils::IsTriggerDDL(block.fSpecification))
1853         {
1854                 bool scalarEvent = ((header->GetL1TriggerMessage() & 0x1) == 0x1);
1855                 AliMUONTriggerDDLDecoder<AliHLTMUONTriggerDecoderHandler> decoder;
1856                 decoder.ExitOnError(false);
1857                 decoder.TryRecover(false);
1858                 decoder.AutoDetectScalars(false);
1859                 decoder.GetHandler().SetDescriptor(&block);
1860                 decoder.GetHandler().SetBlockNumber(blockNumber);
1861                 result = decoder.Decode(payload, payloadSize, scalarEvent);
1862         }
1863         else if (AliHLTMUONUtils::IsTrackerDDL(block.fSpecification))
1864         {
1865                 AliMUONTrackerDDLDecoder<AliHLTMUONTrackerDecoderHandler> decoder;
1866                 decoder.ExitOnError(false);
1867                 decoder.TryRecover(false);
1868                 decoder.SendDataOnParityError(true);
1869                 decoder.AutoDetectTrailer(true);
1870                 decoder.CheckForTrailer(true);
1871                 decoder.GetHandler().SetDescriptor(&block);
1872                 decoder.GetHandler().SetBlockNumber(blockNumber);
1873                 result = decoder.Decode(payload, payloadSize);
1874                 if (decoder.GetHandler().DataProblems()) result = false;
1875                 
1876                 if (FetchMappingStores() == 0)  // are stores loaded?
1877                 {
1878                         Bool_t warn = kFALSE;
1879                         AliMpDDLStore* ddlStore = AliMpDDLStore::Instance(warn);
1880                         
1881                         // Check that the bus patch, manu ID and channel addresses are valid
1882                         // for each raw data word.
1883                         for (UInt_t i = 0; i < decoder.GetHandler().DigitCount(); i++)
1884                         {
1885                                 UInt_t busPatchId = decoder.GetHandler().Digits()[i].fBusPatchId;
1886                                 UInt_t dataWord = decoder.GetHandler().Digits()[i].fDataWord;
1887                                 
1888                                 UShort_t manuId; UChar_t channelId; UShort_t adc;
1889                                 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(
1890                                                 dataWord, manuId, channelId, adc
1891                                         );
1892                                 
1893                                 // Check if the bus patch is valid.
1894                                 AliMpBusPatch* busPatch = ddlStore->GetBusPatch(busPatchId, warn);
1895                                 if (busPatch == NULL)
1896                                 {
1897                                         HLTError("Problem found with data block %d, fDataType = '%s',"
1898                                                  " fPtr = %p and fSize = %u bytes."
1899                                                  " Assuming this is a tracker DDL raw data block."
1900                                                  " Problem: Found a bus patch identifier %d that"
1901                                                  " is not valid.",
1902                                                 blockNumber,
1903                                                 DataType2Text(block.fDataType).c_str(),
1904                                                 block.fPtr,
1905                                                 block.fSize,
1906                                                 busPatchId
1907                                         );
1908                                         result = false;
1909                                         continue;
1910                                 }
1911                                 
1912                                 // We can check that the bus patch is for the DDL
1913                                 // which is also indicated by the specification bits.
1914                                 if (not fIgnoreSpec and busPatch->GetDdlId() != ddlIndex)
1915                                 {
1916                                         HLTError("Problem found with data block %d, fDataType = '%s',"
1917                                                  " fPtr = %p and fSize = %u bytes."
1918                                                  " Assuming this is a tracker DDL raw data block."
1919                                                  " Problem: Found a bus patch identifier %d for"
1920                                                  " DDL %d, but the data block specification 0x%8.8X"
1921                                                  " indicates a different DDL of %d.",
1922                                                 blockNumber,
1923                                                 DataType2Text(block.fDataType).c_str(),
1924                                                 block.fPtr,
1925                                                 block.fSize,
1926                                                 busPatchId,
1927                                                 busPatch->GetDdlId(),
1928                                                 block.fSpecification,
1929                                                 ddlIndex
1930                                         );
1931                                         result = false;
1932                                         continue;
1933                                 }
1934                                 
1935                                 // Check if the MANU ID is valid.
1936                                 if (not busPatch->HasManu(manuId))
1937                                 {
1938                                         HLTError("Problem found with data block %d, fDataType = '%s',"
1939                                                  " fPtr = %p and fSize = %u bytes."
1940                                                  " Assuming this is a tracker DDL raw data block."
1941                                                  " Problem: Found a MANU identifier %d on bus patch %d"
1942                                                  " that is not valid.",
1943                                                 blockNumber,
1944                                                 DataType2Text(block.fDataType).c_str(),
1945                                                 block.fPtr,
1946                                                 block.fSize,
1947                                                 manuId,
1948                                                 busPatchId
1949                                         );
1950                                         result = false;
1951                                         continue;
1952                                 }
1953                                 
1954                                 // Now try to fetch the detector element to check the MANU channel.
1955                                 AliMpDetElement* de = ddlStore->GetDetElement(busPatch->GetDEId(), warn);
1956                                 if (de == NULL)
1957                                 {
1958                                         HLTError("Problem found with data block %d, fDataType = '%s',"
1959                                                  " fPtr = %p and fSize = %u bytes."
1960                                                  " Assuming this is a tracker DDL raw data block."
1961                                                  " Problem: Found a bus patch identifier %d that"
1962                                                  " does not correspond to a detector element.",
1963                                                 blockNumber,
1964                                                 DataType2Text(block.fDataType).c_str(),
1965                                                 block.fPtr,
1966                                                 block.fSize,
1967                                                 busPatchId
1968                                         );
1969                                         result = false;
1970                                         continue;
1971                                 }
1972                                 
1973                                 if (not de->IsConnectedChannel(manuId, channelId))
1974                                 {
1975                                         // Just a warning because this is marked not
1976                                         // to be an error in the AliMUONDigitMaker.
1977                                         HLTWarning("Problem found with data block %d, fDataType = '%s',"
1978                                                  " fPtr = %p and fSize = %u bytes."
1979                                                  " Assuming this is a tracker DDL raw data block."
1980                                                  " Problem: Found a channel with address %d on"
1981                                                  " MANU ID %d and bus patch %d that is not connected.",
1982                                                 blockNumber,
1983                                                 DataType2Text(block.fDataType).c_str(),
1984                                                 block.fPtr,
1985                                                 block.fSize,
1986                                                 channelId,
1987                                                 manuId,
1988                                                 busPatchId
1989                                         );
1990                                         result = false;
1991                                         continue;
1992                                 }
1993                                 
1994                                 // Need to also load the correct segmentation to check the channel.
1995                                 const AliMpVSegmentation* seg =
1996                                         AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(
1997                                                 busPatch->GetDEId(), manuId
1998                                         );
1999                                 if (seg == NULL)
2000                                 {
2001                                         HLTError("Could not load segmentation for detector element %d"
2002                                                  " and MANU ID %d.",
2003                                                 busPatch->GetDEId(), manuId
2004                                         );
2005                                         result = false;
2006                                         continue;
2007                                 }
2008                                 
2009 #ifndef HAVE_NOT_MUON_ALIMPPAD_GETPOSITION
2010                                 AliMpPad pad = seg->PadByLocation(manuId, channelId, warn);
2011 #else // old AliMpPad functionality < r 31742
2012                                 AliMpPad pad = seg->PadByLocation(AliMpIntPair(manuId, channelId), warn);
2013 #endif //HAVE_NOT_MUON_ALIMPPAD_GETPOSITION
2014                                 if (not pad.IsValid())
2015                                 {
2016                                         HLTError("Problem found with data block %d, fDataType = '%s',"
2017                                                  " fPtr = %p and fSize = %u bytes."
2018                                                  " Assuming this is a tracker DDL raw data block."
2019                                                  " Problem: Found a channel with address %d on"
2020                                                  " MANU ID %d and bus patch %d that is not valid.",
2021                                                 blockNumber,
2022                                                 DataType2Text(block.fDataType).c_str(),
2023                                                 block.fPtr,
2024                                                 block.fSize,
2025                                                 channelId,
2026                                                 manuId,
2027                                                 busPatchId
2028                                         );
2029                                         result = false;
2030                                         continue;
2031                                 }
2032                         }
2033                 }
2034                 else
2035                 {
2036                         HLTWarning("Cannot check if the bus patch IDs, MANU ID and"
2037                                 " channel addresses for DDL raw data are valid without"
2038                                 " being able to load the mapping from CDB."
2039                         );
2040                         result = false;
2041                 }
2042         }
2043         else
2044         {
2045                 HLTError("Problem found with data block %d, fDataType = '%s',"
2046                          " fPtr = %p and fSize = %u bytes."
2047                          " Assuming this is a DDL raw data block."
2048                          " Problem: The specification does not contain a valid pattern,"
2049                          " received 0x%8.8X for the specification.",
2050                         blockNumber,
2051                         DataType2Text(block.fDataType).c_str(),
2052                         block.fPtr,
2053                         block.fSize,
2054                         block.fSpecification
2055                 );
2056                 result = false;
2057         }
2058         
2059         return result;
2060 }
2061
2062
2063 bool AliHLTMUONDataCheckerComponent::CheckTriggerRecordsBlock(
2064                 const AliHLTComponentBlockData& block,
2065                 AliHLTUInt32_t blockNumber
2066         ) const
2067 {
2068         /// Checks the validity of a trigger records block.
2069
2070         bool result = true;
2071         const char* name = "trigger records";
2072         
2073         if (not fIgnoreSpec)
2074         {
2075                 if (not IsFromTriggerOnly(block, blockNumber, name))
2076                         result = false;
2077         }
2078         
2079         AliHLTMUONTriggerRecordsBlockReader inblock(block.fPtr, block.fSize);
2080         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2081                 return false;
2082         
2083         bool ddl[22];
2084         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2085         
2086         // Min and max allowed chamber numbers for hits:
2087         Int_t minCh = AliMUONConstants::NCh() - AliMUONConstants::NTriggerCh();
2088         Int_t maxCh = AliMUONConstants::NCh() - 1;
2089         
2090         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2091         {
2092                 // Check that each hit in each trigger record has a reasonable coordinate.
2093                 AliHLTMUONParticleSign sign;
2094                 bool hitset[4];
2095                 AliHLTMUONUtils::UnpackTriggerRecordFlags(inblock[i].fFlags, sign, hitset);
2096         
2097                 for (Int_t j = 0; j < 4; j++)  // loop over 4 trigger chamber hits.
2098                 {
2099                         if (not hitset[i]) continue; // ignore hits that are not initialised.
2100                         bool hitOk = IsHitCoordinateOk(
2101                                         block, blockNumber, name, i, inblock[i].fHit[j],
2102                                         minCh, maxCh, j+10, ddl
2103                                 );
2104                         if (not hitOk) result = false;
2105                 }
2106                 
2107                 // We can also check the momentum vector.
2108                 bool momOk = IsMomentumVectorOk(
2109                                 block, blockNumber, name, i,
2110                                 inblock[i].fPx, inblock[i].fPy, inblock[i].fPz
2111                         );
2112                 if (not momOk) result = false;
2113         }
2114         
2115         // Need to check that no entries have duplicated data but with a different
2116         // ID number.
2117         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2118         {
2119                 AliHLTMUONTriggerRecordStruct ti = inblock[i];
2120                 ti.fId = -1;
2121                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2122                 {
2123                         AliHLTMUONTriggerRecordStruct tj = inblock[j];
2124                         tj.fId = ti.fId;
2125                         
2126                         if (ti == tj)
2127                         {
2128                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2129                                         " fPtr = %p and fSize = %u bytes."
2130                                         " Assuming this is a %s data block."
2131                                         " Problem: The trigger records %d and %d contain the"
2132                                         " same data. The data might have been duplicated.",
2133                                         blockNumber,
2134                                         DataType2Text(block.fDataType).c_str(),
2135                                         block.fPtr,
2136                                         block.fSize,
2137                                         name,
2138                                         i, j
2139                                 );
2140                                 result = false;
2141                         }
2142                 }
2143         }
2144         
2145         return result;
2146 }
2147
2148
2149 bool AliHLTMUONDataCheckerComponent::CheckTrigRecsDebugBlock(
2150                 const AliHLTComponentBlockData& block,
2151                 AliHLTUInt32_t blockNumber
2152         ) const
2153 {
2154         /// Checks the validity of a trigger records debug block.
2155         
2156         bool result = true;
2157         const char* name = "trigger records debug information";
2158         
2159         if (not fIgnoreSpec)
2160         {
2161                 if (not IsFromTriggerOnly(block, blockNumber, name))
2162                         result = false;
2163         }
2164         
2165         AliHLTMUONTrigRecsDebugBlockReader inblock(block.fPtr, block.fSize);
2166         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2167                 return false;
2168         
2169         bool ddl[22];
2170         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2171         
2172         // Check that each detector element ID is valid and the corresponding DDL
2173         // bit is set in the data block specification.
2174         if (FetchMappingStores() == 0)  // are stores loaded?
2175         {
2176                 Bool_t warn = kFALSE;
2177                 AliMpDEStore* store = AliMpDEStore::Instance(warn);
2178                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2179                 for (AliHLTUInt32_t j = 0; j < 4; j++)
2180                 {
2181                         const AliHLTMUONTrigRecInfoStruct& trig = inblock[i];
2182                         AliMpDetElement* de = store->GetDetElement(trig.fDetElemId[j], warn);
2183                         if (de == NULL)
2184                         {
2185                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2186                                          " fPtr = %p and fSize = %u bytes."
2187                                          " Assuming this is a %s data block."
2188                                          " Problem: The detector element number %d on chamber"
2189                                          " %d for trigger record debug structure %d is not valid.",
2190                                         blockNumber,
2191                                         DataType2Text(block.fDataType).c_str(),
2192                                         block.fPtr,
2193                                         block.fSize,
2194                                         name,
2195                                         trig.fDetElemId[j],
2196                                         j+11,
2197                                         i
2198                                 );
2199                                 result = false;
2200                                 continue;
2201                         }
2202                         
2203                         // Check that the chamber number from the detector element number
2204                         // has the expected value.
2205                         Int_t chamber = AliMpDEManager::GetChamberId(trig.fDetElemId[j], warn);
2206                         if (chamber != Int_t(j+10))
2207                         {
2208                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2209                                          " fPtr = %p and fSize = %u bytes."
2210                                          " Assuming this is a %s data block."
2211                                          " Problem: The detector element number %d for trigger"
2212                                          " record debug structure %d, corresponds to chamber"
2213                                          " %d, but we expected a hit for chamber %d.",
2214                                         blockNumber,
2215                                         DataType2Text(block.fDataType).c_str(),
2216                                         block.fPtr,
2217                                         block.fSize,
2218                                         name,
2219                                         trig.fDetElemId[j],
2220                                         i,
2221                                         chamber+1,
2222                                         j+11
2223                                 );
2224                                 result = false;
2225                         }
2226                         
2227                         if (fIgnoreSpec) continue;
2228                         if (0 <= de->GetDdlId() and de->GetDdlId() < 22 and not ddl[de->GetDdlId()])
2229                         {
2230                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2231                                          " fPtr = %p and fSize = %u bytes."
2232                                          " Assuming this is a %s data block."
2233                                          " Problem: The detector element number %d for trigger"
2234                                          " record %d corresponds to DDL number %d, but the"
2235                                          " data block specification 0x%8.8X does not have the"
2236                                          " corresponding bit set.",
2237                                         blockNumber,
2238                                         DataType2Text(block.fDataType).c_str(),
2239                                         block.fPtr,
2240                                         block.fSize,
2241                                         name,
2242                                         trig.fDetElemId[j],
2243                                         i,
2244                                         de->GetDdlId(),
2245                                         block.fSpecification
2246                                 );
2247                                 result = false;
2248                         }
2249                 }
2250         }
2251         else
2252         {
2253                 HLTWarning("Cannot check trigger record debug information without"
2254                         " being able to load the mapping from CDB."
2255                 );
2256                 result = false;
2257         }
2258         
2259         // Need to check that no entries have duplicated data but with a different
2260         // ID number.
2261         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2262         {
2263                 AliHLTMUONTrigRecInfoStruct ti = inblock[i];
2264                 ti.fTrigRecId = -1;
2265                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2266                 {
2267                         AliHLTMUONTrigRecInfoStruct tj = inblock[j];
2268                         tj.fTrigRecId = ti.fTrigRecId;
2269                         
2270                         if (ti == tj)
2271                         {
2272                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2273                                         " fPtr = %p and fSize = %u bytes."
2274                                         " Assuming this is a %s data block."
2275                                         " Problem: The trigger record debug information"
2276                                         " structures %d and %d contain the same data."
2277                                         " The data might have been duplicated.",
2278                                         blockNumber,
2279                                         DataType2Text(block.fDataType).c_str(),
2280                                         block.fPtr,
2281                                         block.fSize,
2282                                         name,
2283                                         i, j
2284                                 );
2285                                 result = false;
2286                         }
2287                 }
2288                 
2289                 // Can also check that the value of the fZmiddle and fBl.
2290                 bool paramsOk = AreMomentumCalcParamsOk(
2291                                 block, blockNumber, name, i, ti.fZmiddle, ti.fBl
2292                         );
2293                 if (not paramsOk) result = false;
2294         }
2295         
2296         return result;
2297 }
2298
2299
2300 bool AliHLTMUONDataCheckerComponent::CheckRecHitsBlock(
2301                 const AliHLTComponentBlockData& block,
2302                 AliHLTUInt32_t blockNumber
2303         ) const
2304 {
2305         /// Checks the validity of a reconstructed hits block.
2306
2307         bool result = true;
2308         const char* name = "reconstructed hits";
2309         
2310         if (not fIgnoreSpec)
2311         {
2312                 if (not IsFromTrackerOnly(block, blockNumber, name))
2313                         result = false;
2314         }
2315         
2316         AliHLTMUONRecHitsBlockReader inblock(block.fPtr, block.fSize);
2317         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2318                 return false;
2319         
2320         bool ddl[22];
2321         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2322         
2323         // Check that each hit has a reasonable coordinate.
2324         Int_t minCh = 0;
2325         Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
2326         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2327         {
2328                 bool hitOk = IsHitCoordinateOk(
2329                                 block, blockNumber, name, i, inblock[i],
2330                                 minCh, maxCh, -1, ddl
2331                         );
2332                 if (not hitOk) result = false;
2333         }
2334         
2335         return result;
2336 }
2337
2338
2339 bool AliHLTMUONDataCheckerComponent::CheckClustersBlock(
2340                 const AliHLTComponentBlockData& block,
2341                 AliHLTUInt32_t blockNumber
2342         ) const
2343 {
2344         /// Checks the validity of a clusters block.
2345
2346         bool result = true;
2347         const char* name = "clusters";
2348         
2349         if (not fIgnoreSpec)
2350         {
2351                 if (not IsFromTrackerOnly(block, blockNumber, name))
2352                         result = false;
2353         }
2354         
2355         AliHLTMUONClustersBlockReader inblock(block.fPtr, block.fSize);
2356         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2357                 return false;
2358         
2359         bool ddl[22];
2360         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2361         
2362         if (FetchMappingStores() == 0)  // are stores loaded?
2363         {
2364                 Bool_t warn = kFALSE;
2365                 AliMpDEStore* store = AliMpDEStore::Instance(warn);
2366                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2367                 {
2368                         const AliHLTMUONClusterStruct& cluster = inblock[i];
2369                         
2370                         // Check that the detector element ID is valid.
2371                         AliMpDetElement* de = store->GetDetElement(cluster.fDetElemId, warn);
2372                         if (de == NULL)
2373                         {
2374                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2375                                          " fPtr = %p and fSize = %u bytes."
2376                                          " Assuming this is a %s data block."
2377                                          " Problem: The detector element number %d for cluster"
2378                                          " %d is not valid.",
2379                                         blockNumber,
2380                                         DataType2Text(block.fDataType).c_str(),
2381                                         block.fPtr,
2382                                         block.fSize,
2383                                         name,
2384                                         cluster.fDetElemId,
2385                                         i
2386                                 );
2387                                 result = false;
2388                                 continue;
2389                         }
2390                         
2391                         // Check that the chamber number found from the hit coordinate and
2392                         // that from the detector element number are the same.
2393                         Int_t chamberFromHit = AliMUONConstants::ChamberNumber(cluster.fHit.fZ, warn);
2394                         Int_t chamberFromDE = AliMpDEManager::GetChamberId(cluster.fDetElemId, warn);
2395                         if (chamberFromHit != chamberFromDE)
2396                         {
2397                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2398                                          " fPtr = %p and fSize = %u bytes."
2399                                          " Assuming this is a %s data block."
2400                                          " Problem: The detector element number %d for"
2401                                          " cluster %d, corresponds to chamber %d, but"
2402                                          " found a different chamber number %d for the"
2403                                          " corresponding hit coordinate {x = %f, y = %f,"
2404                                          " z = %f}.",
2405                                         blockNumber,
2406                                         DataType2Text(block.fDataType).c_str(),
2407                                         block.fPtr,
2408                                         block.fSize,
2409                                         name,
2410                                         cluster.fDetElemId,
2411                                         i,
2412                                         chamberFromDE+1,
2413                                         chamberFromHit+1,
2414                                         cluster.fHit.fX,
2415                                         cluster.fHit.fY,
2416                                         cluster.fHit.fZ
2417                                 );
2418                                 result = false;
2419                         }
2420                         
2421                         // Make sure the corresponding DDL bit is set in the data
2422                         // block specification.
2423                         if (fIgnoreSpec) continue;
2424                         if (0 <= de->GetDdlId() and de->GetDdlId() < 22 and not ddl[de->GetDdlId()])
2425                         {
2426                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2427                                          " fPtr = %p and fSize = %u bytes."
2428                                          " Assuming this is a %s data block."
2429                                          " Problem: The detector element number %d for cluster"
2430                                          " %d corresponds to DDL number %d, but the data"
2431                                          " block specification 0x%8.8X does not have the"
2432                                          " corresponding bit set.",
2433                                         blockNumber,
2434                                         DataType2Text(block.fDataType).c_str(),
2435                                         block.fPtr,
2436                                         block.fSize,
2437                                         name,
2438                                         cluster.fDetElemId,
2439                                         i,
2440                                         de->GetDdlId(),
2441                                         block.fSpecification
2442                                 );
2443                                 result = false;
2444                         }
2445                         
2446                         // Check that the total cluster charge is a reasonable value.
2447                         if ((cluster.fChargeB + cluster.fChargeNB)< 0 and 1e4 < (cluster.fChargeB + cluster.fChargeNB))
2448                         {
2449                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2450                                          " fPtr = %p and fSize = %u bytes."
2451                                          " Assuming this is a %s data block."
2452                                          " Problem: The total charge %f for the cluster"
2453                                          " %d is not in a reasonable range [0..1e4].",
2454                                         blockNumber,
2455                                         DataType2Text(block.fDataType).c_str(),
2456                                         block.fPtr,
2457                                         block.fSize,
2458                                         name,
2459                                         (cluster.fChargeB + cluster.fChargeNB),
2460                                         i
2461                                 );
2462                                 result = false;
2463                                 continue;
2464                         }
2465                 }
2466         }
2467         else
2468         {
2469                 HLTWarning("Cannot check cluster information without being able"
2470                         " to load the mapping from CDB."
2471                 );
2472                 result = false;
2473         }
2474         
2475         // Min and max chamber numbers allowed for the cluster hits.
2476         Int_t minCh = 0;
2477         Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
2478         
2479         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2480         {
2481                 // Need to check that no cluster data has duplicated data but with
2482                 // a different ID number.
2483                 AliHLTMUONClusterStruct ci = inblock[i];
2484                 ci.fId = -1;
2485                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2486                 {
2487                         AliHLTMUONClusterStruct cj = inblock[j];
2488                         cj.fId = ci.fId;
2489                         
2490                         if (ci == cj)
2491                         {
2492                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2493                                         " fPtr = %p and fSize = %u bytes."
2494                                         " Assuming this is a %s data block."
2495                                         " Problem: The cluster structures %d and %d contain"
2496                                         " the same data. The data might have been duplicated.",
2497                                         blockNumber,
2498                                         DataType2Text(block.fDataType).c_str(),
2499                                         block.fPtr,
2500                                         block.fSize,
2501                                         name,
2502                                         i, j
2503                                 );
2504                                 result = false;
2505                         }
2506                 }
2507                 
2508                 // Check that the hit structure in the cluster corresponds
2509                 // to a tracker chamber.
2510                 bool hitOk = IsHitCoordinateOk(
2511                                 block, blockNumber, name, i, ci.fHit,
2512                                 minCh, maxCh, -1, ddl
2513                         );
2514                 if (not hitOk) result = false;
2515         }
2516         
2517         return result;
2518 }
2519
2520
2521 bool AliHLTMUONDataCheckerComponent::CheckChannelsBlock(
2522                 const AliHLTComponentBlockData& block,
2523                 AliHLTUInt32_t blockNumber
2524         ) const
2525 {
2526         /// Checks the validity of a channels block.
2527
2528         bool result = true;
2529         const char* name = "channels";
2530         
2531         if (not fIgnoreSpec)
2532         {
2533                 if (not IsFromTrackerOnly(block, blockNumber, name))
2534                         result = false;
2535         }
2536         
2537         AliHLTMUONChannelsBlockReader inblock(block.fPtr, block.fSize);
2538         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2539                 return false;
2540         
2541         bool ddl[22];
2542         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2543         
2544         if (FetchMappingStores() == 0)  // are stores loaded?
2545         {
2546                 Bool_t warn = kFALSE;
2547                 AliMpDDLStore* store = AliMpDDLStore::Instance(warn);
2548                 
2549                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2550                 {
2551                         const AliHLTMUONChannelStruct& channel = inblock[i];
2552                         
2553                         // Check if the bus patch is valid.
2554                         AliMpBusPatch* busPatch = store->GetBusPatch(channel.fBusPatch, warn);
2555                         if (busPatch == NULL)
2556                         {
2557                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2558                                         " fPtr = %p and fSize = %u bytes."
2559                                         " Assuming this is a %s data block."
2560                                         " Problem: Found a bus patch identifier %d that"
2561                                         " is not valid.",
2562                                         blockNumber,
2563                                         DataType2Text(block.fDataType).c_str(),
2564                                         block.fPtr,
2565                                         block.fSize,
2566                                         name,
2567                                         channel.fBusPatch
2568                                 );
2569                                 result = false;
2570                                 continue;
2571                         }
2572                         
2573                         // We can check that the bus patch is for a DDL
2574                         // which is also indicated by the specification bits.
2575                         if (not fIgnoreSpec and (
2576                              not (0 <= busPatch->GetDdlId() and busPatch->GetDdlId() < 20)
2577                              or  (0 <= busPatch->GetDdlId() and busPatch->GetDdlId() < 20
2578                                   and not ddl[busPatch->GetDdlId()])
2579                            ))
2580                         {
2581                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2582                                          " fPtr = %p and fSize = %u bytes."
2583                                          " Assuming this is a %s data block."
2584                                          " Problem: Found a bus patch identifier %d for"
2585                                          " DDL %d, but the data block specification 0x%8.8X"
2586                                          " does not have the corresponding bit set.",
2587                                         blockNumber,
2588                                         DataType2Text(block.fDataType).c_str(),
2589                                         block.fPtr,
2590                                         block.fSize,
2591                                         name,
2592                                         channel.fBusPatch,
2593                                         busPatch->GetDdlId(),
2594                                         block.fSpecification
2595                                 );
2596                                 result = false;
2597                                 continue;
2598                         }
2599                         
2600                         // Check if the MANU ID is valid.
2601                         if (not busPatch->HasManu(channel.fManu))
2602                         {
2603                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2604                                          " fPtr = %p and fSize = %u bytes."
2605                                          " Assuming this is a %s data block."
2606                                          " Problem: Found a MANU identifier %d on bus patch %d"
2607                                          " that is not valid.",
2608                                         blockNumber,
2609                                         DataType2Text(block.fDataType).c_str(),
2610                                         block.fPtr,
2611                                         block.fSize,
2612                                         name,
2613                                         channel.fManu,
2614                                         channel.fBusPatch
2615                                 );
2616                                 result = false;
2617                                 continue;
2618                         }
2619                         
2620                         // Now try to fetch the detector element to check the MANU channel.
2621                         AliMpDetElement* de = store->GetDetElement(busPatch->GetDEId(), warn);
2622                         if (de == NULL)
2623                         {
2624                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2625                                          " fPtr = %p and fSize = %u bytes."
2626                                          " Assuming this is a %s data block."
2627                                          " Problem: Found a bus patch identifier %d that"
2628                                          " does not correspond to a detector element.",
2629                                         blockNumber,
2630                                         DataType2Text(block.fDataType).c_str(),
2631                                         block.fPtr,
2632                                         block.fSize,
2633                                         name,
2634                                         channel.fBusPatch
2635                                 );
2636                                 result = false;
2637                                 continue;
2638                         }
2639                         
2640                         if (not de->IsConnectedChannel(channel.fManu, channel.fChannelAddress))
2641                         {
2642                                 // Just a warning because this is marked not
2643                                 // to be an error in the AliMUONDigitMaker.
2644                                 HLTWarning("Problem found with data block %d, fDataType = '%s',"
2645                                         " fPtr = %p and fSize = %u bytes."
2646                                         " Assuming this is a %s data block."
2647                                         " Problem: Found a channel with address %d on"
2648                                         " MANU ID %d and bus patch %d that is not connected.",
2649                                         blockNumber,
2650                                         DataType2Text(block.fDataType).c_str(),
2651                                         block.fPtr,
2652                                         block.fSize,
2653                                         name,
2654                                         channel.fChannelAddress,
2655                                         channel.fManu,
2656                                         channel.fBusPatch
2657                                 );
2658                                 result = false;
2659                                 continue;
2660                         }
2661                         
2662                         // Need to also load the correct segmentation to check the channel.
2663                         const AliMpVSegmentation* seg =
2664                                 AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(
2665                                         busPatch->GetDEId(), channel.fManu
2666                                 );
2667                         if (seg == NULL)
2668                         {
2669                                 HLTError("Could not load segmentation for detector element %d"
2670                                          " and MANU ID %d.",
2671                                         busPatch->GetDEId(), channel.fManu
2672                                 );
2673                                 result = false;
2674                                 continue;
2675                         }
2676                         
2677                         AliMpPad pad = seg->PadByLocation(
2678 #ifndef HAVE_NOT_MUON_ALIMPPAD_GETPOSITION
2679                                         channel.fManu, channel.fChannelAddress,
2680 #else // old AliMpPad functionality < r 31742
2681                                         AliMpIntPair(channel.fManu, channel.fChannelAddress),
2682 #endif //HAVE_NOT_MUON_ALIMPPAD_GETPOSITION
2683                                         warn
2684                                 );
2685                         if (not pad.IsValid())
2686                         {
2687                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2688                                         " fPtr = %p and fSize = %u bytes."
2689                                         " Assuming this is a %s data block."
2690                                         " Problem: Found a channel with address %d on"
2691                                         " MANU ID %d and bus patch %d that is not valid.",
2692                                         blockNumber,
2693                                         DataType2Text(block.fDataType).c_str(),
2694                                         block.fPtr,
2695                                         block.fSize,
2696                                         name,
2697                                         channel.fChannelAddress,
2698                                         channel.fManu,
2699                                         channel.fBusPatch
2700                                 );
2701                                 result = false;
2702                                 continue;
2703                         }
2704                 }
2705         }
2706         else
2707         {
2708                 HLTWarning("Cannot check channel information without being able"
2709                         " to load the mapping from CDB."
2710                 );
2711                 result = false;
2712         }
2713         
2714         // Need to check that no channel data has duplicated data but with
2715         // a different cluster ID number.
2716         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2717         {
2718                 AliHLTMUONChannelStruct ci = inblock[i];
2719                 ci.fClusterId = -1;
2720                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2721                 {
2722                         AliHLTMUONChannelStruct cj = inblock[j];
2723                         cj.fClusterId = ci.fClusterId;
2724                         
2725                         if (ci == cj)
2726                         {
2727                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2728                                         " fPtr = %p and fSize = %u bytes."
2729                                         " Assuming this is a %s data block."
2730                                         " Problem: The channel structures %d and %d contain"
2731                                         " the same data. The data might have been duplicated.",
2732                                         blockNumber,
2733                                         DataType2Text(block.fDataType).c_str(),
2734                                         block.fPtr,
2735                                         block.fSize,
2736                                         name,
2737                                         i, j
2738                                 );
2739                                 result = false;
2740                         }
2741                 }
2742         }
2743         
2744         return result;
2745 }
2746
2747
2748 bool AliHLTMUONDataCheckerComponent::CheckMansoTracksBlock(
2749                 const AliHLTComponentBlockData& block,
2750                 AliHLTUInt32_t blockNumber
2751         ) const
2752 {
2753         /// Checks the validity of a Manso tracks block.
2754
2755         bool result = true;
2756         const char* name = "Manso tracks";
2757         
2758         if (not fIgnoreSpec)
2759         {
2760                 if (not IsSpecificationValid(block, blockNumber, name))
2761                         result = false;
2762         }
2763         
2764         AliHLTMUONMansoTracksBlockReader inblock(block.fPtr, block.fSize);
2765         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2766                 return false;
2767         
2768         bool ddl[22];
2769         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2770         
2771         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2772         {
2773                 // Need to check that no entries have duplicated data but with
2774                 // a different track ID number.
2775                 AliHLTMUONMansoTrackStruct ti = inblock[i];
2776                 ti.fId = -1;
2777                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2778                 {
2779                         AliHLTMUONMansoTrackStruct tj = inblock[j];
2780                         tj.fId = ti.fId;
2781                         
2782                         if (ti == tj)
2783                         {
2784                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2785                                         " fPtr = %p and fSize = %u bytes."
2786                                         " Assuming this is a %s data block."
2787                                         " Problem: The Manso tracks %d and %d contain the"
2788                                         " same data. The data might have been duplicated.",
2789                                         blockNumber,
2790                                         DataType2Text(block.fDataType).c_str(),
2791                                         block.fPtr,
2792                                         block.fSize,
2793                                         name,
2794                                         i, j
2795                                 );
2796                                 result = false;
2797                         }
2798                 }
2799                 
2800                 bool trackOk = IsMansoTrackOk(block, blockNumber, name, i, ti, ddl);
2801                 if (not trackOk) result = false;
2802         }
2803         
2804         return result;
2805 }
2806
2807
2808 bool AliHLTMUONDataCheckerComponent::CheckMansoCandidatesBlock(
2809                 const AliHLTComponentBlockData& block,
2810                 AliHLTUInt32_t blockNumber
2811         ) const
2812 {
2813         /// Checks the validity of a Manso candidates block.
2814
2815         bool result = true;
2816         const char* name = "Manso track candidates";
2817         
2818         if (not fIgnoreSpec)
2819         {
2820                 if (not IsSpecificationValid(block, blockNumber, name))
2821                         result = false;
2822         }
2823         
2824         AliHLTMUONMansoCandidatesBlockReader inblock(block.fPtr, block.fSize);
2825         if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
2826                 return false;
2827         
2828         bool ddl[22];
2829         AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
2830         
2831         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
2832         {
2833                 // Need to check that no entries have duplicated data but with a
2834                 // different track ID number.
2835                 AliHLTMUONMansoCandidateStruct ti = inblock[i];
2836                 ti.fTrack.fId = -1;
2837                 for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
2838                 {
2839                         AliHLTMUONMansoCandidateStruct tj = inblock[j];
2840                         tj.fTrack.fId = ti.fTrack.fId;
2841                         
2842                         if (ti == tj)
2843                         {
2844                                 HLTError("Problem found with data block %d, fDataType = '%s',"
2845                                         " fPtr = %p and fSize = %u bytes."
2846                                         " Assuming this is a %s data block."
2847                                         " Problem: The Manso track candidates %d and %d"