]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/AliHLTMUONUtils.cxx
Adding dictionary generation for AliHLTMUONConstants and AliHLTMUONUtils.
[u/mrichter/AliRoot.git] / HLT / MUON / AliHLTMUONUtils.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///
19 /// @file   AliHLTMUONUtils.cxx
20 /// @author Artur Szostak <artursz@iafrica.com>
21 /// @date   17 May 2007
22 /// @brief  Implementation of AliHLTMUONUtils utility routines.
23 ///
24
25 #include "AliHLTMUONUtils.h"
26 #include "AliHLTMUONConstants.h"
27 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
28 #include "AliHLTMUONTrigRecsDebugBlockStruct.h"
29 #include "AliHLTMUONRecHitsBlockStruct.h"
30 #include "AliHLTMUONClustersBlockStruct.h"
31 #include "AliHLTMUONChannelsBlockStruct.h"
32 #include "AliHLTMUONMansoTracksBlockStruct.h"
33 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
34 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
35 #include "AliHLTMUONPairsDecisionBlockStruct.h"
36 #include "AliMUONTrackerDDLDecoderEventHandler.h"
37 #include <cstring>
38 #include <cmath>
39 #include <cassert>
40
41 ClassImp(AliHLTMUONUtils);
42
43
44 AliHLTUInt32_t AliHLTMUONUtils::PackTriggerRecordFlags(
45                 AliHLTMUONParticleSign sign, const bool hitset[4]
46         )
47 {
48         ///
49         /// This packs the given parameters into the bits of a word appropriate
50         /// for AliHLTMUONTriggerRecordStruct::fFlags.
51         /// @param sign    The particle sign.
52         /// @param hitset  Flags to indicate if the corresponding fHits[i] elements
53         ///                was set/filled.
54         /// @return  Returns the 32 bit packed word.
55         ///
56         
57         AliHLTUInt32_t flags;
58         switch (sign)
59         {
60         case kSignMinus: flags = 0x80000000; break;
61         case kSignPlus:  flags = 0x40000000; break;
62         default:         flags = 0x00000000; break;
63         }
64
65         return flags | (hitset[0] ? 0x1 : 0) | (hitset[1] ? 0x2 : 0)
66                 | (hitset[2] ? 0x4 : 0) | (hitset[3] ? 0x8 : 0);
67 }
68
69
70 void AliHLTMUONUtils::UnpackTriggerRecordFlags(
71                 AliHLTUInt32_t flags, AliHLTMUONParticleSign& sign, bool hitset[4]
72         )
73 {
74         ///
75         /// This unpacks the AliHLTMUONTriggerRecordStruct::fFlags bits into
76         /// its component fields.
77         /// @param flags  The flags from an AliHLTMUONTriggerRecordStruct structure.
78         /// @param sign    Sets this to the particle sign.
79         /// @param hitset  Sets the array elements to indicate if the corresponding
80         ///                fHits[i] element was set/filled.
81         ///
82         
83         AliHLTUInt32_t signbits = flags & 0xC0000000;
84         switch (signbits)
85         {
86         case 0x80000000: sign = kSignMinus;   break;
87         case 0x40000000: sign = kSignPlus;    break;
88         default:         sign = kSignUnknown; break;
89         }
90         hitset[0] = (flags & 0x1) == 0x1;
91         hitset[1] = (flags & 0x2) == 0x2;
92         hitset[2] = (flags & 0x4) == 0x4;
93         hitset[3] = (flags & 0x8) == 0x8;
94 }
95
96
97 AliHLTUInt32_t AliHLTMUONUtils::PackRecHitFlags(
98                 AliHLTUInt8_t chamber, AliHLTUInt16_t detElemId
99         )
100 {
101         /// This packs the given parameters into the bits of a word appropriate
102         /// for AliHLTMUONRecHitStruct::fFlags.
103         /// @param chamber    The chamber number in the range [0..13].
104         /// @param detElemId  Detector element ID number.
105         /// @return  Returns the 32 bit packed word.
106         
107         return ((chamber & 0xF) << 12) | (detElemId & 0xFFF);
108 }
109
110
111 void AliHLTMUONUtils::UnpackRecHitFlags(
112                 AliHLTUInt32_t flags, // [in]
113                 AliHLTUInt8_t& chamber, // [out]
114                 AliHLTUInt16_t& detElemId // [out]
115         )
116 {
117         /// This unpacks the AliHLTMUONRecHitStruct::fFlags bits into
118         /// its component fields.
119         /// [in]  @param flags  The flags from an AliHLTMUONRecHitStruct structure.
120         /// [out] @param chamber    Sets the chamber number in the range [0..13].
121         /// [out] @param detElemId  Sets the detector element ID number.
122         
123         chamber = (flags >> 12) & 0xF;
124         detElemId = flags & 0xFFF;
125 }
126
127
128 AliHLTUInt32_t AliHLTMUONUtils::PackTrackDecisionBits(bool highPt, bool lowPt)
129 {
130         ///
131         /// This packs the given parameters into the bits of a word appropriate
132         /// for AliHLTMUONTrackDecisionStruct::fTriggerBits.
133         /// @param highPt  Has the track passed the high pt cut.
134         /// @param lowPt   Has the track passed the low pt cut.
135         /// @return  Returns the 32 bit packed word.
136         ///
137         
138         return (highPt ? 0x2 : 0) | (lowPt ? 0x1 : 0);
139 }
140
141
142 void AliHLTMUONUtils::UnpackTrackDecisionBits(
143                 AliHLTUInt32_t bits, bool& highPt, bool& lowPt
144         )
145 {
146         ///
147         /// This unpacks the AliHLTMUONTrackDecisionStruct::fTriggerBits bits into
148         /// its component fields.
149         /// @param bits  The trigger bits from an AliHLTMUONTrackDecisionStruct
150         ///              structure.
151         /// @param highPt Sets this to the value of the high pt cut bit.
152         /// @param lowPt  Sets this to the value of the low pt cut bit.
153         ///
154         
155         lowPt  = (bits & 0x1) == 0x1;
156         highPt = (bits & 0x2) == 0x2;
157 }
158
159
160 AliHLTUInt32_t AliHLTMUONUtils::PackPairDecisionBits(
161                 bool highMass, bool lowMass, bool unlike,
162                 AliHLTUInt8_t highPtCount, AliHLTUInt8_t lowPtCount
163         )
164 {
165         ///
166         /// This packs the given parameters into the bits of a word appropriate
167         /// for AliHLTMUONPairDecisionStruct::fTriggerBits.
168         ///
169         /// @param highMass Has the track pair passed the high invariant mass cut.
170         /// @param lowMass  Has the track pair passed the low invariant mass cut.
171         /// @param unlike   Does the track pair have unlike signs.
172         /// @param highPtCount The number of tracks that passed the high pt cut
173         ///                    in the pair.
174         /// @param lowPtCount  The number of tracks that passed the low pt cut
175         ///                    in the pair.
176         /// @return  Returns the 32 bit packed word.
177         ///
178         /// Note: Must have highPtCount <= 2, lowPtCount <= 2 and
179         /// unlike == true if highMass or lowMass is true.
180         ///
181         
182         assert( lowPtCount <= 2 );
183         assert( highPtCount <= 2 );
184         // highMass and lowMass must be false if unlike is false:
185         assert( not unlike ? (highMass == false and lowMass == false) : true );
186         
187         return (highMass ? 0x40 : 0) | (lowMass ? 0x20 : 0) | (unlike ? 0x10 : 0)
188                 | ((highPtCount & 0x3) << 2) | (lowPtCount & 0x3);
189 }
190
191
192 void AliHLTMUONUtils::UnpackPairDecisionBits(
193                 AliHLTUInt32_t bits, bool& highMass, bool& lowMass, bool& unlike,
194                 AliHLTUInt8_t& highPtCount, AliHLTUInt8_t& lowPtCount
195         )
196 {
197         ///
198         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
199         /// its component fields.
200         /// @param bits  The trigger bits from an AliHLTMUONPairDecisionStruct
201         ///              structure.
202         /// @param highMass Sets this to the value of the high invariant mass cut bit.
203         /// @param lowMass  Sets this to the value of the low invariant mass cut bit.
204         /// @param unlike   Sets this if the pair is unlike sign.
205         /// @param highPtCount Sets this to the high pt count bits.
206         /// @param lowPtCount  Sets this to the low pt count bits.
207         ///
208         
209         highMass = (bits & 0x40) == 0x40;
210         lowMass  = (bits & 0x20) == 0x20;
211         unlike   = (bits & 0x10) == 0x10;
212         highPtCount = (bits & 0xC) >> 2;
213         lowPtCount = bits & 0x3;
214 }
215
216
217 AliHLTUInt32_t AliHLTMUONUtils::PackSpecBits(
218                 const bool ddl[22]
219         )
220 {
221         ///
222         /// This packs the given parameters into the 32bit Pub/Sub specification
223         /// word in the data block descriptor.
224         ///
225         /// @param ddl  The list of DDLs forming part of the readout. ddl[0]
226         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
227         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
228         ///             trigger DDLs 2816 and 2817 respectively.
229         /// @return  Returns the 32 bit packed specification word.
230         ///
231         
232         // Pack the bits into the following format:
233         //   bit:   [        31 - 22        ][     21     ][     20     ][  19 - 0 ]
234         //   field: [ reserved, set to zero ][ TRGDDL2817 ][ TRGDDL2816 ][ TRKDDLS ]
235         // Meaning of field acronyms:
236         //   TRGDDL2816 - Trigger DDL number 2816.
237         //   TRGDDL2817 - Trigger DDL number 2817.
238         //   TRKDDLS - Tracking DDL flags where bit 0 will be for DDL number 2560,
239         //             bit 1 for DDL no. 2561 etc. up to bit 19 which is for DDL 2579.
240         AliHLTUInt32_t bits = 0;
241         for (int i = 0; i < 22; i++)
242                 bits |= (ddl[i] ? 0x1 : 0x0) << i;
243         return bits;
244 }
245
246
247 void AliHLTMUONUtils::UnpackSpecBits(
248                 AliHLTUInt32_t bits, bool ddl[22]
249         )
250 {
251         ///
252         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
253         /// its component fields.
254         /// @param bits  The Pub/Sub specification word from a data block descriptor.
255         /// @param ddl  The output list of DDLs forming part of the readout. ddl[0]
256         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
257         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
258         ///             trigger DDLs 2816 and 2817 respectively.
259         ///
260         
261         // Perform the inverse operation of PackSpecBits.
262         for (int i = 0; i < 22; i++)
263                 ddl[i] = ((bits >> i) & 0x1) == 1;
264 }
265
266
267 AliHLTInt32_t AliHLTMUONUtils::DDLNumberToEquipId(AliHLTInt32_t ddlNo)
268 {
269         ///
270         /// This method converts the DDL number for the muon spectrometer in the
271         /// range [0..21] to the equipment ID number.
272         /// @param ddlNo  The DDL number in the range [0..21].
273         /// @return  Returns the equipment ID number or -1 if ddlNo was invalid.
274         ///
275         
276         if (0 <= ddlNo and ddlNo <= 19)
277         {
278                 return 2560 + ddlNo;
279         }
280         else if (20 <= ddlNo and ddlNo <= 21)
281         {
282                 return 2816 + (ddlNo - 20);
283         }
284         else
285         {
286                 return -1;
287         }
288 }
289
290
291 AliHLTInt32_t AliHLTMUONUtils::EquipIdToDDLNumber(AliHLTInt32_t id)
292 {
293         ///
294         /// This method converts the equipment ID number for a muon spectrometer
295         /// DDL to the DDL number in the range [0..21].
296         /// @param id  The equipment ID of the DDL.
297         /// @return  Returns the DDL number in the range [0..21] or -1 if the
298         ///          equipment ID was invalid.
299         ///
300         
301         if (2560 <= id and id <= 2560+19)
302         {
303                 return id - 2560;
304         }
305         else if (2816 <= id and id <= 2817)
306         {
307                 return id - 2816 + 20;
308         }
309         else
310         {
311                 return -1;
312         }
313 }
314
315
316 AliHLTInt32_t AliHLTMUONUtils::SpecToEquipId(AliHLTUInt32_t spec)
317 {
318         ///
319         /// This method converts a 32 bit data block specification for a MUON-HLT
320         /// data block into its corresponding DDL equipment ID number.
321         /// It is assumed that the specification is for a data block comming from
322         /// a single DDL source. If more than one DDL contributed to the data block
323         /// then -1 is returned.
324         /// @param spec  The 32 bit specification for a data block.
325         /// @return  Returns the equipment ID corresponding to the specification
326         ///          or -1 if the specification was invalid.
327         ///
328         
329         for (AliHLTInt32_t ddlNo = 0; ddlNo < 20; ddlNo++)
330         {
331                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
332                         return ddlNo + 2560;
333         }
334         for (AliHLTInt32_t ddlNo = 20; ddlNo < 22; ddlNo++)
335         {
336                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
337                         return ddlNo - 20 + 2816;
338         }
339         return -1;
340 }
341
342
343 AliHLTUInt32_t AliHLTMUONUtils::EquipIdToSpec(AliHLTInt32_t id)
344 {
345         ///
346         /// This method converts a equipment ID number for a DDL into its corresponding
347         /// 32 bit data block specification for the MUON-HLT.
348         /// @param id  The equipment ID number of the DDL.
349         /// @return  Returns the 32 bit data block specification or 0x0 if the
350         ///          equipment ID was invalid.
351         ///
352         
353         if (2560 <= id and id <= 2560+19)
354         {
355                 return 0x1 << (id - 2560);
356         }
357         else if (2816 <= id and id <= 2817)
358         {
359                 return 0x1 << (id - 2816 + 20);
360         }
361         else
362         {
363                 return 0x0;
364         }
365 }
366
367
368 AliHLTInt32_t AliHLTMUONUtils::SpecToDDLNumber(AliHLTUInt32_t spec)
369 {
370         ///
371         /// This method converts a 32 bit data block specification for a MUON-HLT
372         /// data block into its corresponding DDL number in the range [0..21].
373         /// It is assumed that the specification is for a data block comming from
374         /// a single DDL source. If more than one DDL contributed to the data block
375         /// then -1 is returned.
376         /// @param spec  The 32 bit specification for a data block.
377         /// @return  Returns the corresponding DDL number for the specification
378         ///          or -1 if the specification was invalid.
379         ///
380         
381         for (AliHLTInt32_t ddlNo = 0; ddlNo < 22; ddlNo++)
382         {
383                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
384                         return ddlNo;
385         }
386         return -1;
387 }
388
389
390 AliHLTUInt32_t AliHLTMUONUtils::DDLNumberToSpec(AliHLTInt32_t ddlNo)
391 {
392         ///
393         /// This method converts a DDL number in the range [0..21] into its
394         /// corresponding 32 bit data block specification for the MUON-HLT.
395         /// @param ddlNo  The equipment ID number of the DDL.
396         /// @return  Returns the 32 bit data block specification or 0x0 if the
397         ///          DDL number was invalid (out of range).
398         ///
399         
400         if (0 <= ddlNo and ddlNo <= 21)
401         {
402                 return 0x1 << ddlNo;
403         }
404         else
405         {
406                 return 0x0;
407         }
408 }
409
410
411 AliHLTMUONDataBlockType AliHLTMUONUtils::ParseCommandLineTypeString(const char* type)
412 {
413         /// Parses the string containing the type name of a dHLT data block and
414         /// returns the corresponding AliHLTMUONDataBlockType value.
415         /// \param  type  The string containing the type name.
416         /// \returns  The data block type or kUnknownDataBlock if the type name
417         ///      is invalid.
418
419         if (strcmp(type, "trigrecs") == 0)
420         {
421                 return kTriggerRecordsDataBlock;
422         }
423         else if (strcmp(type, "trigrecsdebug") == 0)
424         {
425                 return kTrigRecsDebugDataBlock;
426         }
427         else if (strcmp(type, "rechits") == 0)
428         {
429                 return kRecHitsDataBlock;
430         }
431         else if (strcmp(type,"channels") == 0)
432         {
433                 return kChannelsDataBlock;
434         }
435         else if (strcmp(type,"clusters") == 0)
436         {
437                 return kClustersDataBlock;
438         }
439         else if (strcmp(type, "mansotracks") == 0)
440         {
441                 return kMansoTracksDataBlock;
442         }
443         else if (strcmp(type, "mansocandidates") == 0)
444         {
445                 return kMansoCandidatesDataBlock;
446         }
447         else if (strcmp(type, "singlesdecision") == 0)
448         {
449                 return kSinglesDecisionDataBlock;
450         }
451         else if (strcmp(type, "pairsdecision") == 0)
452         {
453                 return kPairsDecisionDataBlock;
454         }
455         
456         return kUnknownDataBlock;
457 }
458
459
460 const char* AliHLTMUONUtils::DataBlockTypeToString(AliHLTMUONDataBlockType type)
461 {
462         /// Converts a type ID to a type string compatible with
463         /// HLT data types.
464         
465         static char str[kAliHLTComponentDataTypefIDsize+1];
466         AliHLTComponentDataType t;
467         switch (type)
468         {
469         case kTriggerRecordsDataBlock:
470                 t = AliHLTMUONConstants::TriggerRecordsBlockDataType();
471                 break;
472         case kTrigRecsDebugDataBlock:
473                 t = AliHLTMUONConstants::TrigRecsDebugBlockDataType();
474                 break;
475         case kRecHitsDataBlock:
476                 t = AliHLTMUONConstants::RecHitsBlockDataType();
477                 break;
478         case kClustersDataBlock:
479                 t = AliHLTMUONConstants::ClusterBlockDataType();
480                 break;
481         case kChannelsDataBlock:
482                 t = AliHLTMUONConstants::ChannelBlockDataType();
483                 break;
484         case kMansoTracksDataBlock:
485                 t = AliHLTMUONConstants::MansoTracksBlockDataType();
486                 break;
487         case kMansoCandidatesDataBlock:
488                 t = AliHLTMUONConstants::MansoCandidatesBlockDataType();
489                 break;
490         case kSinglesDecisionDataBlock:
491                 t = AliHLTMUONConstants::SinglesDecisionBlockDataType();
492                 break;
493         case kPairsDecisionDataBlock:
494                 t = AliHLTMUONConstants::PairsDecisionBlockDataType();
495                 break;
496         default:
497                 return "UNKNOWN";
498         }
499         memcpy(&str, &t.fID, kAliHLTComponentDataTypefIDsize);
500         // Must insert the NULL character to make this an ANSI C string.
501         str[kAliHLTComponentDataTypefIDsize] = '\0';
502         return &str[0];
503 }
504
505
506 const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid reason)
507 {
508         /// This method converts the WhyNotValid enumeration to a string representation.
509         
510         switch (reason)
511         {
512         case kNoReason: return "kNoReason";
513         case kHeaderContainsWrongType: return "kHeaderContainsWrongType";
514         case kHeaderContainsWrongRecordWidth: return "kHeaderContainsWrongRecordWidth";
515         case kInvalidIdValue: return "kInvalidIdValue";
516         case kInvalidTriggerIdValue: return "kInvalidTriggerIdValue";
517         case kInvalidTrackIdValue: return "kInvalidTrackIdValue";
518         case kReservedBitsNotZero: return "kReservedBitsNotZero";
519         case kParticleSignBitsNotValid: return "kParticleSignBitsNotValid";
520         case kHitNotMarkedAsNil: return "kHitNotMarkedAsNil";
521         case kInvalidDetElementNumber: return "kInvalidDetElementNumber";
522         case kInvalidChamberNumber: return "kInvalidChamberNumber";
523         case kHitIsNil: return "kHitIsNil";
524         case kInvalidChannelCount: return "kInvalidChannelCount";
525         case kInvalidBusPatchId: return "kInvalidBusPatchId";
526         case kInvalidManuId: return "kInvalidManuId";
527         case kInvalidChannelAddress: return "kInvalidChannelAddress";
528         case kInvalidSignal: return "kInvalidSignal";
529         case kDataWordDifferent: return "kDataWordDifferent";
530         case kChiSquareInvalid: return "kChiSquareInvalid";
531         case kMomentumVectorNotZero: return "kMomentumVectorNotZero";
532         case kRoiRadiusInvalid: return "kRoiRadiusInvalid";
533         case kHitNotWithinRoi: return "kHitNotWithinRoi";
534         case kPtValueNotValid: return "kPtValueNotValid";
535         case kPairTrackIdsAreIdentical: return "kPairTrackIdsAreIdentical";
536         case kMassValueNotValid: return "kMassValueNotValid";
537         case kLowPtCountInvalid: return "kLowPtCountInvalid";
538         case kHighPtCountInvalid: return "kHighPtCountInvalid";
539         case kFoundDuplicateIDs: return "kFoundDuplicateIDs";
540         case kFoundDuplicateHits: return "kFoundDuplicateHits";
541         case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
542         default: return "INVALID";
543         }
544 }
545
546
547 const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
548 {
549         /// This method returns a string containing a user readable message explaining
550         /// the reason for failure described by the WhyNotValid enumeration.
551         
552         switch (reason)
553         {
554         case kNoReason:
555                 return "There was no problem with the data block.";
556         case kHeaderContainsWrongType:
557                 return "The common data header contains an incorrect type"
558                         " identifier.";
559         case kHeaderContainsWrongRecordWidth:
560                 return "The common data header contains an incorrect data"
561                         " record width.";
562         case kInvalidIdValue:
563                 return "The structure identifier does not have a valid value.";
564         case kInvalidTriggerIdValue:
565                 return "The trigger structure identifier does not have a valid"
566                         " value.";
567         case kInvalidTrackIdValue:
568                 return "The track structure identifier does not have a valid"
569                         " value.";
570         case kReservedBitsNotZero:
571                 return "Reserved bits have not been set to zero.";
572         case kParticleSignBitsNotValid:
573                 return "The particle sign bits are not a valid value.";
574         case kHitNotMarkedAsNil:
575                 return "A hit was marked as not found, but the corresponding hit"
576                         " structure was not set to nil.";
577         case kInvalidDetElementNumber:
578                 return "An invalid detector element ID was found.";
579         case kInvalidChamberNumber:
580                 return "An invalid chamber number was found.";
581         case kHitIsNil:
582                 return "The hit cannot be set to a nil value.";
583         case kInvalidChannelCount:
584                 return "The number of channels indicated is zero or outside"
585                         " the valid range.";
586         case kInvalidBusPatchId:
587                 return "The bus patch identifier is outside the valid range.";
588         case kInvalidManuId:
589                 return "The MANU identifier is outside the valid range.";
590         case kInvalidChannelAddress:
591                 return "The MANU channel address is outside the valid range.";
592         case kInvalidSignal:
593                 return "The ADC signal value is outside the valid range.";
594         case kDataWordDifferent:
595                 return "The raw data word is different from the unpacked values.";
596         case kChiSquareInvalid:
597                 return "The chi squared value must be a positive value or -1"
598                         " indicating a fitting error.";
599         case kMomentumVectorNotZero:
600                 return "The chi sqaured value is set to -1 indicating momentum"
601                         " was not fitted, but the momentum vector was not zero.";
602         case kRoiRadiusInvalid:
603                 return "The region of interest radius is invalid.";
604         case kHitNotWithinRoi:
605                 return "A tracks hit is not within the corresponding region"
606                         " of interest.";
607         case kPtValueNotValid:
608                 return "The pT value is not positive, nor -1 indicating an"
609                         " invalid value.";
610         case kPairTrackIdsAreIdentical:
611                 return "The track identifiers of the track pair are identical.";
612         case kMassValueNotValid:
613                 return "The invariant mass value is not positive, nor -1"
614                         " indicating an invalid value.";
615         case kLowPtCountInvalid:
616                 return "The low pT trigger count is greater than 2,"
617                         " which is invalid.";
618         case kHighPtCountInvalid:
619                 return "The high pT trigger count is greater than 2,"
620                         " which is invalid.";
621         case kFoundDuplicateIDs:
622                 return "Found duplicate data record identifiers, but they"
623                         " should all be unique.";
624         case kFoundDuplicateHits:
625                 return "Found duplicate hit structures, but they should all"
626                         " be unique.";
627         case kFoundDuplicateTriggers:
628                 return "Found duplicate trigger decisions.";
629         default:
630                 return "UNKNOWN REASON CODE";
631         }
632 }
633
634
635 bool AliHLTMUONUtils::RecordNumberWasSet(WhyNotValid reason)
636 {
637         /// Returns true if the \em recordNum in the corresponding IntegrityOk method
638         /// would have been set, if it returned false and a reason was set.
639         /// This helper method makes it easy to test if the \em recordNum parameter
640         /// is filled with a valid value or not.
641         /// \param reason  The reason code as returned by the IntegrityOk method.
642         /// \returns  true if the \em recordNum parameter was set for the given
643         ///      reason code.
644         
645         switch (reason)
646         {
647         case kInvalidIdValue:
648         case kInvalidTriggerIdValue:
649         case kInvalidTrackIdValue:
650         case kReservedBitsNotZero:
651         case kParticleSignBitsNotValid:
652         case kHitNotMarkedAsNil:
653         case kInvalidDetElementNumber:
654         case kInvalidChamberNumber:
655         case kHitIsNil:
656         case kInvalidChannelCount:
657         case kInvalidBusPatchId:
658         case kInvalidManuId:
659         case kInvalidChannelAddress:
660         case kInvalidSignal:
661         case kDataWordDifferent:
662         case kChiSquareInvalid:
663         case kPtValueNotValid:
664         case kPairTrackIdsAreIdentical:
665         case kMassValueNotValid:
666         case kLowPtCountInvalid:
667         case kHighPtCountInvalid:
668                 return true;
669         default: return false;
670         }
671 }
672
673
674 bool AliHLTMUONUtils::HeaderOk(
675                 const AliHLTMUONTriggerRecordsBlockStruct& block,
676                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
677         )
678 {
679         /// Method used to check if the header information corresponds to the
680         /// supposed type of the raw dHLT data block.
681         /// [in]  \param block  The data block to check.
682         /// [out] \param reason  If this is not NULL, then it is assumed to point
683         ///      to an array of at least 'reasonCount' number of elements. It will
684         ///      be filled with the reason codes describing why the header is not
685         ///      valid.
686         /// [in/out] \param reasonCount  This should initially specify the size of
687         ///      the array pointed to by 'reason'. It will be filled with the number
688         ///      of items actually filled into the reason array upon exit from this
689         ///      method.
690         /// \returns  true if there is no problem with the header and false otherwise.
691         
692         AliHLTUInt32_t maxCount = reasonCount;
693         reasonCount = 0;
694         bool result = true;
695         
696         // The block must have the correct type.
697         if (block.fHeader.fType != kTriggerRecordsDataBlock)
698         {
699                 if (reason != NULL and reasonCount < maxCount)
700                 {
701                         reason[reasonCount] = kHeaderContainsWrongType;
702                         reasonCount++;
703                 }
704                 result = false;
705         }
706         
707         // The block's record width must be the correct size.
708         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerRecordStruct))
709         {
710                 if (reason != NULL and reasonCount < maxCount)
711                 {
712                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
713                         reasonCount++;
714                 }
715                 result = false;
716         }
717         
718         return result;
719 }
720
721
722 bool AliHLTMUONUtils::HeaderOk(
723                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
724                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
725         )
726 {
727         /// Method used to check if the header information corresponds to the
728         /// supposed type of the raw dHLT data block.
729         /// [in]  \param block  The data block to check.
730         /// [out] \param reason  If this is not NULL, then it is assumed to point
731         ///      to an array of at least 'reasonCount' number of elements. It will
732         ///      be filled with the reason codes describing why the header is not
733         ///      valid.
734         /// [in/out] \param reasonCount  This should initially specify the size of
735         ///      the array pointed to by 'reason'. It will be filled with the number
736         ///      of items actually filled into the reason array upon exit from this
737         ///      method.
738         /// \returns  true if there is no problem with the header and false otherwise.
739         
740         AliHLTUInt32_t maxCount = reasonCount;
741         reasonCount = 0;
742         bool result = true;
743         
744         // The block must have the correct type.
745         if (block.fHeader.fType != kTrigRecsDebugDataBlock)
746         {
747                 if (reason != NULL and reasonCount < maxCount)
748                 {
749                         reason[reasonCount] = kHeaderContainsWrongType;
750                         reasonCount++;
751                 }
752                 result = false;
753         }
754         
755         // The block's record width must be the correct size.
756         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
757         {
758                 if (reason != NULL and reasonCount < maxCount)
759                 {
760                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
761                         reasonCount++;
762                 }
763                 result = false;
764         }
765         
766         return result;
767 }
768
769
770 bool AliHLTMUONUtils::HeaderOk(
771                 const AliHLTMUONRecHitsBlockStruct& block,
772                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
773         )
774 {
775         /// Method used to check if the header information corresponds to the
776         /// supposed type of the raw dHLT data block.
777         /// [in]  \param block  The data block to check.
778         /// [out] \param reason  If this is not NULL, then it is assumed to point
779         ///      to an array of at least 'reasonCount' number of elements. It will
780         ///      be filled with the reason codes describing why the header is not
781         ///      valid.
782         /// [in/out] \param reasonCount  This should initially specify the size of
783         ///      the array pointed to by 'reason'. It will be filled with the number
784         ///      of items actually filled into the reason array upon exit from this
785         ///      method.
786         /// \returns  true if there is no problem with the header and false otherwise.
787         
788         AliHLTUInt32_t maxCount = reasonCount;
789         reasonCount = 0;
790         bool result = true;
791         
792         // The block must have the correct type.
793         if (block.fHeader.fType != kRecHitsDataBlock)
794         {
795                 if (reason != NULL and reasonCount < maxCount)
796                 {
797                         reason[reasonCount] = kHeaderContainsWrongType;
798                         reasonCount++;
799                 }
800                 result = false;
801         }
802         
803         // The block's record width must be the correct size.
804         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
805         {
806                 if (reason != NULL and reasonCount < maxCount)
807                 {
808                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
809                         reasonCount++;
810                 }
811                 result = false;
812         }
813         
814         return result;
815 }
816
817
818 bool AliHLTMUONUtils::HeaderOk(
819                 const AliHLTMUONClustersBlockStruct& block,
820                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
821         )
822 {
823         /// Method used to check if the header information corresponds to the
824         /// supposed type of the raw dHLT data block.
825         /// [in]  \param block  The data block to check.
826         /// [out] \param reason  If this is not NULL, then it is assumed to point
827         ///      to an array of at least 'reasonCount' number of elements. It will
828         ///      be filled with the reason codes describing why the header is not
829         ///      valid.
830         /// [in/out] \param reasonCount  This should initially specify the size of
831         ///      the array pointed to by 'reason'. It will be filled with the number
832         ///      of items actually filled into the reason array upon exit from this
833         ///      method.
834         /// \returns  true if there is no problem with the header and false otherwise.
835         
836         AliHLTUInt32_t maxCount = reasonCount;
837         reasonCount = 0;
838         bool result = true;
839         
840         // The block must have the correct type.
841         if (block.fHeader.fType != kClustersDataBlock)
842         {
843                 if (reason != NULL and reasonCount < maxCount)
844                 {
845                         reason[reasonCount] = kHeaderContainsWrongType;
846                         reasonCount++;
847                 }
848                 result = false;
849         }
850         
851         // The block's record width must be the correct size.
852         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
853         {
854                 if (reason != NULL and reasonCount < maxCount)
855                 {
856                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
857                         reasonCount++;
858                 }
859                 result = false;
860         }
861         
862         return result;
863 }
864
865
866 bool AliHLTMUONUtils::HeaderOk(
867                 const AliHLTMUONChannelsBlockStruct& block,
868                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
869         )
870 {
871         /// Method used to check if the header information corresponds to the
872         /// supposed type of the raw dHLT data block.
873         /// [in]  \param block  The data block to check.
874         /// [out] \param reason  If this is not NULL, then it is assumed to point
875         ///      to an array of at least 'reasonCount' number of elements. It will
876         ///      be filled with the reason codes describing why the header is not
877         ///      valid.
878         /// [in/out] \param reasonCount  This should initially specify the size of
879         ///      the array pointed to by 'reason'. It will be filled with the number
880         ///      of items actually filled into the reason array upon exit from this
881         ///      method.
882         /// \returns  true if there is no problem with the header and false otherwise.
883         
884         AliHLTUInt32_t maxCount = reasonCount;
885         reasonCount = 0;
886         bool result = true;
887         
888         // The block must have the correct type.
889         if (block.fHeader.fType != kChannelsDataBlock)
890         {
891                 if (reason != NULL and reasonCount < maxCount)
892                 {
893                         reason[reasonCount] = kHeaderContainsWrongType;
894                         reasonCount++;
895                 }
896                 result = false;
897         }
898         
899         // The block's record width must be the correct size.
900         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
901         {
902                 if (reason != NULL and reasonCount < maxCount)
903                 {
904                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
905                         reasonCount++;
906                 }
907                 result = false;
908         }
909         
910         return result;
911 }
912
913
914 bool AliHLTMUONUtils::HeaderOk(
915                 const AliHLTMUONMansoTracksBlockStruct& block,
916                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
917         )
918 {
919         /// Method used to check if the header information corresponds to the
920         /// supposed type of the raw dHLT data block.
921         /// [in]  \param block  The data block to check.
922         /// [out] \param reason  If this is not NULL, then it is assumed to point
923         ///      to an array of at least 'reasonCount' number of elements. It will
924         ///      be filled with the reason codes describing why the header is not
925         ///      valid.
926         /// [in/out] \param reasonCount  This should initially specify the size of
927         ///      the array pointed to by 'reason'. It will be filled with the number
928         ///      of items actually filled into the reason array upon exit from this
929         ///      method.
930         /// \returns  true if there is no problem with the header and false otherwise.
931         
932         AliHLTUInt32_t maxCount = reasonCount;
933         reasonCount = 0;
934         bool result = true;
935         
936         // The block must have the correct type.
937         if (block.fHeader.fType != kMansoTracksDataBlock)
938         {
939                 if (reason != NULL and reasonCount < maxCount)
940                 {
941                         reason[reasonCount] = kHeaderContainsWrongType;
942                         reasonCount++;
943                 }
944                 result = false;
945         }
946         
947         // The block's record width must be the correct size.
948         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
949         {
950                 if (reason != NULL and reasonCount < maxCount)
951                 {
952                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
953                         reasonCount++;
954                 }
955                 result = false;
956         }
957         
958         return result;
959 }
960
961
962 bool AliHLTMUONUtils::HeaderOk(
963                 const AliHLTMUONMansoCandidatesBlockStruct& block,
964                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
965         )
966 {
967         /// Method used to check if the header information corresponds to the
968         /// supposed type of the raw dHLT data block.
969         /// [in]  \param block  The data block to check.
970         /// [out] \param reason  If this is not NULL, then it is assumed to point
971         ///      to an array of at least 'reasonCount' number of elements. It will
972         ///      be filled with the reason codes describing why the header is not
973         ///      valid.
974         /// [in/out] \param reasonCount  This should initially specify the size of
975         ///      the array pointed to by 'reason'. It will be filled with the number
976         ///      of items actually filled into the reason array upon exit from this
977         ///      method.
978         /// \returns  true if there is no problem with the header and false otherwise.
979         
980         AliHLTUInt32_t maxCount = reasonCount;
981         reasonCount = 0;
982         bool result = true;
983         
984         // The block must have the correct type.
985         if (block.fHeader.fType != kMansoCandidatesDataBlock)
986         {
987                 if (reason != NULL and reasonCount < maxCount)
988                 {
989                         reason[reasonCount] = kHeaderContainsWrongType;
990                         reasonCount++;
991                 }
992                 result = false;
993         }
994         
995         // The block's record width must be the correct size.
996         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
997         {
998                 if (reason != NULL and reasonCount < maxCount)
999                 {
1000                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1001                         reasonCount++;
1002                 }
1003                 result = false;
1004         }
1005         
1006         return result;
1007 }
1008
1009
1010 bool AliHLTMUONUtils::HeaderOk(
1011                 const AliHLTMUONSinglesDecisionBlockStruct& block,
1012                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
1013         )
1014 {
1015         /// Method used to check if the header information corresponds to the
1016         /// supposed type of the raw dHLT data block.
1017         /// [in]  \param block  The data block to check.
1018         /// [out] \param reason  If this is not NULL, then it is assumed to point
1019         ///      to an array of at least 'reasonCount' number of elements. It will
1020         ///      be filled with the reason codes describing why the header is not
1021         ///      valid.
1022         /// [in/out] \param reasonCount  This should initially specify the size of
1023         ///      the array pointed to by 'reason'. It will be filled with the number
1024         ///      of items actually filled into the reason array upon exit from this
1025         ///      method.
1026         /// \returns  true if there is no problem with the header and false otherwise.
1027         
1028         AliHLTUInt32_t maxCount = reasonCount;
1029         reasonCount = 0;
1030         bool result = true;
1031         
1032         // The block must have the correct type.
1033         if (block.fHeader.fType != kSinglesDecisionDataBlock)
1034         {
1035                 if (reason != NULL and reasonCount < maxCount)
1036                 {
1037                         reason[reasonCount] = kHeaderContainsWrongType;
1038                         reasonCount++;
1039                 }
1040                 result = false;
1041         }
1042         
1043         // The block's record width must be the correct size.
1044         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
1045         {
1046                 if (reason != NULL and reasonCount < maxCount)
1047                 {
1048                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1049                         reasonCount++;
1050                 }
1051                 result = false;
1052         }
1053         
1054         return result;
1055 }
1056
1057
1058 bool AliHLTMUONUtils::HeaderOk(
1059                 const AliHLTMUONPairsDecisionBlockStruct& block,
1060                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
1061         )
1062 {
1063         /// Method used to check if the header information corresponds to the
1064         /// supposed type of the raw dHLT data block.
1065         /// [in]  \param block  The data block to check.
1066         /// [out] \param reason  If this is not NULL, then it is assumed to point
1067         ///      to an array of at least 'reasonCount' number of elements. It will
1068         ///      be filled with the reason codes describing why the header is not
1069         ///      valid.
1070         /// [in/out] \param reasonCount  This should initially specify the size of
1071         ///      the array pointed to by 'reason'. It will be filled with the number
1072         ///      of items actually filled into the reason array upon exit from this
1073         ///      method.
1074         /// \returns  true if there is no problem with the header and false otherwise.
1075         
1076         AliHLTUInt32_t maxCount = reasonCount;
1077         reasonCount = 0;
1078         bool result = true;
1079         
1080         // The block must have the correct type.
1081         if (block.fHeader.fType != kPairsDecisionDataBlock)
1082         {
1083                 if (reason != NULL and reasonCount < maxCount)
1084                 {
1085                         reason[reasonCount] = kHeaderContainsWrongType;
1086                         reasonCount++;
1087                 }
1088                 result = false;
1089         }
1090         
1091         // The block's record width must be the correct size.
1092         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
1093         {
1094                 if (reason != NULL and reasonCount < maxCount)
1095                 {
1096                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1097                         reasonCount++;
1098                 }
1099                 result = false;
1100         }
1101         
1102         return result;
1103 }
1104
1105
1106 bool AliHLTMUONUtils::IntegrityOk(
1107                 const AliHLTMUONTriggerRecordStruct& tr,
1108                 WhyNotValid* reason,
1109                 AliHLTUInt32_t& reasonCount
1110         )
1111 {
1112         /// This method is used to check more extensively if the integrity of the
1113         /// trigger record structure is OK and returns true in that case.
1114         /// [in] \param tr  The trigger record structure to check.
1115         /// [out] \param reason  If this is not NULL, then it is assumed to point
1116         ///      to an array of at least 'reasonCount' number of elements. It will
1117         ///      be filled with the reason codes describing why the structure is
1118         ///      not valid.
1119         /// [in/out] \param reasonCount  This should initially specify the size of
1120         ///      the array pointed to by 'reason'. It will be filled with the number
1121         ///      of items actually filled into the reason array upon exit from this
1122         ///      method.
1123         /// \returns  true if there is no problem with the structure and false otherwise.
1124         
1125         AliHLTUInt32_t maxCount = reasonCount;
1126         reasonCount = 0;
1127         bool result = true;
1128         
1129         // Check that the ID has a valid value.
1130         if (not (tr.fId >= 0 or tr.fId == -1))
1131         {
1132                 if (reason != NULL and reasonCount < maxCount)
1133                 {
1134                         reason[reasonCount] = kInvalidIdValue;
1135                         reasonCount++;
1136                 }
1137                 result = false;
1138         }
1139         
1140         // Make sure that the reserved bits in the fFlags field are set
1141         // to zero.
1142         if ((tr.fFlags & 0x3FFFFFF0) != 0)
1143         {
1144                 if (reason != NULL and reasonCount < maxCount)
1145                 {
1146                         reason[reasonCount] = kReservedBitsNotZero;
1147                         reasonCount++;
1148                 }
1149                 result = false;
1150         }
1151
1152         // Make sure the sign is not invalid.
1153         if ((tr.fFlags & 0xC0000000) == 0xC0000000)
1154         {
1155                 if (reason != NULL and reasonCount < maxCount)
1156                 {
1157                         reason[reasonCount] = kParticleSignBitsNotValid;
1158                         reasonCount++;
1159                 }
1160                 result = false;
1161         }
1162
1163         // Check that fHit[i] is nil if the corresponding bit in the
1164         // flags word is zero.
1165         const AliHLTMUONRecHitStruct& nilhit
1166                 = AliHLTMUONConstants::NilRecHitStruct();
1167         if ( ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) or
1168              ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) or
1169              ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) or
1170              ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
1171            )
1172         {
1173                 if (reason != NULL and reasonCount < maxCount)
1174                 {
1175                         reason[reasonCount] = kHitNotMarkedAsNil;
1176                         reasonCount++;
1177                 }
1178                 result = false;
1179         }
1180         
1181         // Check the individual hits
1182         for (int i = 0; i < 4; i++)
1183         {
1184                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1185                 if (not IntegrityOk(tr.fHit[i], reason + reasonCount, filledCount))
1186                 {
1187                         reasonCount += filledCount;
1188                         result = false;
1189                 }
1190         }
1191
1192         return result;
1193 }
1194
1195
1196 bool AliHLTMUONUtils::IntegrityOk(
1197                 const AliHLTMUONTriggerRecordsBlockStruct& block,
1198                 WhyNotValid* reason,
1199                 AliHLTUInt32_t* recordNum,
1200                 AliHLTUInt32_t& reasonCount
1201         )
1202 {
1203         /// This method is used to check more extensively if the integrity of the
1204         /// dHLT raw internal data block is OK and returns true in that case.
1205         /// [in] \param block  The trigger record data block to check.
1206         /// [out] \param reason  If this is not NULL, then it is assumed to point
1207         ///      to an array of at least 'reasonCount' number of elements. It will
1208         ///      be filled with the reason codes describing why the data block is
1209         ///      not valid.
1210         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1211         ///      to an array of at least 'reasonCount' number of elements. It will
1212         ///      be filled with the number of the trigger record that had a problem.
1213         ///      The value 'recordNum[i]' will only contain a valid value if
1214         ///      the corresponding 'reason[i]' contains one of:
1215         ///        - kInvalidIdValue
1216         ///        - kReservedBitsNotZero
1217         ///        - kParticleSignBitsNotValid
1218         ///        - kHitNotMarkedAsNil
1219         ///        - kInvalidDetElementNumber
1220         ///        - kInvalidChamberNumber
1221         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1222         ///      was set and is valid or not.
1223         /// [in/out] \param reasonCount  This should initially specify the size of
1224         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1225         ///      with the number of items actually filled into the arrays upon exit
1226         ///      from this method.
1227         /// \returns  true if there is no problem with the data and false otherwise.
1228         
1229         AliHLTUInt32_t maxCount = reasonCount;
1230         bool result = HeaderOk(block, reason, reasonCount);
1231         
1232         const AliHLTMUONTriggerRecordStruct* triggerRecord =
1233                 reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
1234
1235         // Check if any ID is duplicated.
1236         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1237         {
1238                 AliHLTInt32_t id = triggerRecord[i].fId;
1239                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1240                 {
1241                         if (id == triggerRecord[j].fId)
1242                         {
1243                                 if (reason != NULL and reasonCount < maxCount)
1244                                 {
1245                                         reason[reasonCount] = kFoundDuplicateIDs;
1246                                         reasonCount++;
1247                                 }
1248                                 result = false;
1249                         }
1250                 }
1251         }
1252
1253         // Check integrity of individual trigger records.
1254         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1255         {
1256                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1257                 if (not IntegrityOk(triggerRecord[i], reason+reasonCount, filledCount))
1258                 {
1259                         // reasons filled in IntegrityOk, now we just need to adjust
1260                         // reasonCount and fill the recordNum values.
1261                         if (recordNum != NULL)
1262                         {
1263                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1264                                         recordNum[reasonCount + n] = i;
1265                         }
1266                         reasonCount += filledCount;
1267                         result = false;
1268                 }
1269         }
1270
1271         return result;
1272 }
1273
1274
1275 bool AliHLTMUONUtils::IntegrityOk(
1276                 const AliHLTMUONTrigRecInfoStruct& trigInfo,
1277                 WhyNotValid* reason,
1278                 AliHLTUInt32_t& reasonCount
1279         )
1280 {
1281         /// This method is used to check more extensively if the integrity of the
1282         /// trigger record debug information structure is OK and returns true in that case.
1283         /// [in] \param trigInfo  The trigger record debug information structure to check.
1284         /// [out] \param reason  If this is not NULL, then it is assumed to point
1285         ///      to an array of at least 'reasonCount' number of elements. It will
1286         ///      be filled with the reason codes describing why the structure is not
1287         ///      valid.
1288         /// [in/out] \param reasonCount  This should initially specify the size of
1289         ///      the array pointed to by 'reason'. It will be filled with the number
1290         ///      of items actually filled into the reason array upon exit from this
1291         ///      method.
1292         /// \returns  true if there is no problem with the structure and false otherwise.
1293         
1294         AliHLTUInt32_t maxCount = reasonCount;
1295         reasonCount = 0;
1296         bool result = true;
1297         
1298         // Check that the trigger ID has a valid value.
1299         if (not (trigInfo.fTrigRecId >= 0 or trigInfo.fTrigRecId == -1))
1300         {
1301                 if (reason != NULL and reasonCount < maxCount)
1302                 {
1303                         reason[reasonCount] = kInvalidIdValue;
1304                         reasonCount++;
1305                 }
1306                 result = false;
1307         }
1308
1309         // Check that the fDetElemId[i] numbers are valid.
1310         if ( not ((trigInfo.fDetElemId[0] >= 100 and trigInfo.fDetElemId[0] < 1500)
1311                   or trigInfo.fDetElemId[0] == -1)
1312              or not ((trigInfo.fDetElemId[1] >= 100 and trigInfo.fDetElemId[1] < 1500)
1313                   or trigInfo.fDetElemId[1] == -1)
1314              or not ((trigInfo.fDetElemId[2] >= 100 and trigInfo.fDetElemId[2] < 1500)
1315                   or trigInfo.fDetElemId[2] == -1)
1316              or not ((trigInfo.fDetElemId[3] >= 100 and trigInfo.fDetElemId[3] < 1500)
1317                   or trigInfo.fDetElemId[3] == -1)
1318            )
1319         {
1320                 if (reason != NULL and reasonCount < maxCount)
1321                 {
1322                         reason[reasonCount] = kInvalidDetElementNumber;
1323                         reasonCount++;
1324                 }
1325                 result = false;
1326         }
1327
1328         return result;
1329 }
1330
1331
1332 bool AliHLTMUONUtils::IntegrityOk(
1333                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
1334                 WhyNotValid* reason,
1335                 AliHLTUInt32_t* recordNum,
1336                 AliHLTUInt32_t& reasonCount
1337         )
1338 {
1339         /// This method is used to check more extensively if the integrity of the
1340         /// dHLT raw internal data block is OK and returns true in that case.
1341         /// [in] \param block  The trigger record debugging information data block
1342         ///      to check.
1343         /// [out] \param reason  If this is not NULL, then it is assumed to point
1344         ///      to an array of at least 'reasonCount' number of elements. It will
1345         ///      be filled with the reason codes describing why the data block is
1346         ///      not valid.
1347         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1348         ///      to an array of at least 'reasonCount' number of elements. It will
1349         ///      be filled with the number of the trigger record debug information
1350         ///      structure that had a problem.
1351         ///      The value 'recordNum[i]' will only contain a valid value if
1352         ///      the corresponding 'reason[i]' contains one of:
1353         ///        - kInvalidIdValue
1354         ///        - kInvalidDetElementNumber
1355         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1356         ///      was set and is valid or not.
1357         /// [in/out] \param reasonCount  This should initially specify the size of
1358         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1359         ///      with the number of items actually filled into the arrays upon exit
1360         ///      from this method.
1361         /// \returns  true if there is no problem with the data and false otherwise.
1362         
1363         AliHLTUInt32_t maxCount = reasonCount;
1364         bool result = HeaderOk(block, reason, reasonCount);
1365         
1366         const AliHLTMUONTrigRecInfoStruct* triggerInfo =
1367                 reinterpret_cast<const AliHLTMUONTrigRecInfoStruct*>(&block + 1);
1368
1369         // Check if any trigger debug info structure has duplicated trigger IDs.
1370         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1371         {
1372                 AliHLTInt32_t id = triggerInfo[i].fTrigRecId;
1373                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1374                 {
1375                         if (id == triggerInfo[j].fTrigRecId)
1376                         {
1377                                 if (reason != NULL and reasonCount < maxCount)
1378                                 {
1379                                         reason[reasonCount] = kFoundDuplicateIDs;
1380                                         reasonCount++;
1381                                 }
1382                                 result = false;
1383                         }
1384                 }
1385         }
1386
1387         // Check integrity of individual trigger records.
1388         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1389         {
1390                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1391                 if (not IntegrityOk(triggerInfo[i], reason+reasonCount, filledCount))
1392                 {
1393                         // reasons filled in IntegrityOk, now we just need to adjust
1394                         // reasonCount and fill the recordNum values.
1395                         if (recordNum != NULL)
1396                         {
1397                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1398                                         recordNum[reasonCount + n] = i;
1399                         }
1400                         reasonCount += filledCount;
1401                         result = false;
1402                 }
1403         }
1404         
1405         return result;
1406 }
1407
1408
1409 bool AliHLTMUONUtils::IntegrityOk(
1410                 const AliHLTMUONRecHitStruct& hit,
1411                 WhyNotValid* reason,
1412                 AliHLTUInt32_t& reasonCount
1413         )
1414 {
1415         /// This method is used to check more extensively if the integrity of the
1416         /// reconstructed hit structure is OK and returns true in that case.
1417         /// [in] \param hit  The reconstructed hit structure to check.
1418         /// [out] \param reason  If this is not NULL, then it is assumed to point
1419         ///      to an array of at least 'reasonCount' number of elements. It will
1420         ///      be filled with the reason codes describing why the structure is
1421         ///      not valid.
1422         /// [in/out] \param reasonCount  This should initially specify the size of
1423         ///      the array pointed to by 'reason'. It will be filled with the number
1424         ///      of items actually filled into the reason array upon exit from this
1425         ///      method.
1426         /// \returns  true if there is no problem with the structure and false otherwise.
1427         
1428         AliHLTUInt32_t maxCount = reasonCount;
1429         reasonCount = 0;
1430         bool result = true;
1431         
1432         // If this is a NIL hit then skip all other checks.
1433         if (hit == AliHLTMUONConstants::NilRecHitStruct())
1434         {
1435                 return true;
1436         }
1437         
1438         // Make sure that the reserved bits in the fFlags field are set
1439         // to zero.
1440         if ((hit.fFlags & 0x3FFF0000) != 0)
1441         {
1442                 if (reason != NULL and reasonCount < maxCount)
1443                 {
1444                         reason[reasonCount] = kReservedBitsNotZero;
1445                         reasonCount++;
1446                 }
1447                 result = false;
1448         }
1449
1450         AliHLTUInt32_t detElemId = hit.fFlags & 0x00000FFF;
1451         AliHLTUInt32_t chamber = (hit.fFlags & 0x0000F000) >> 12;
1452         
1453         // Make sure the detector element ID number is valid.
1454         if (not (detElemId >= 100 and detElemId < 1500))
1455         {
1456                 if (reason != NULL and reasonCount < maxCount)
1457                 {
1458                         reason[reasonCount] = kInvalidDetElementNumber;
1459                         reasonCount++;
1460                 }
1461                 result = false;
1462         }
1463         
1464         // Make sure the chamber number is valid.
1465         if (((detElemId / 100) - 1) != chamber or chamber >= 14)
1466         {
1467                 if (reason != NULL and reasonCount < maxCount)
1468                 {
1469                         reason[reasonCount] = kInvalidChamberNumber;
1470                         reasonCount++;
1471                 }
1472                 result = false;
1473         }
1474
1475         return result;
1476 }
1477
1478
1479 bool AliHLTMUONUtils::IntegrityOk(
1480                 const AliHLTMUONRecHitsBlockStruct& block,
1481                 WhyNotValid* reason,
1482                 AliHLTUInt32_t* recordNum,
1483                 AliHLTUInt32_t& reasonCount
1484         )
1485 {
1486         /// This method is used to check more extensively if the integrity of the
1487         /// dHLT raw internal hits data block is OK and returns true in that case.
1488         /// [in] \param block  The reconstructed hits data block to check.
1489         /// [out] \param reason  If this is not NULL, then it is assumed to point
1490         ///      to an array of at least 'reasonCount' number of elements. It will
1491         ///      be filled with the reason codes describing why the data block is
1492         ///      not valid.
1493         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1494         ///      to an array of at least 'reasonCount' number of elements. It will
1495         ///      be filled with the number of the reconstructed hits that had a problem.
1496         ///      The value 'recordNum[i]' will only contain a valid value if
1497         ///      the corresponding 'reason[i]' contains one of:
1498         ///        - kReservedBitsNotZero
1499         ///        - kInvalidDetElementNumber
1500         ///        - kInvalidChamberNumber
1501         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1502         ///      was set and is valid or not.
1503         /// [in/out] \param reasonCount  This should initially specify the size of
1504         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1505         ///      with the number of items actually filled into the arrays upon exit
1506         ///      from this method.
1507         /// \returns  true if there is no problem with the data and false otherwise.
1508         
1509         AliHLTUInt32_t maxCount = reasonCount;
1510         bool result = HeaderOk(block, reason, reasonCount);
1511         
1512         const AliHLTMUONRecHitStruct* hit =
1513                 reinterpret_cast<const AliHLTMUONRecHitStruct*>(&block + 1);
1514
1515         // Check if any hit structure has been duplicated.
1516         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1517         {
1518                 const AliHLTMUONRecHitStruct& h = hit[i];
1519                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1520                 {
1521                         if (h == hit[j])
1522                         {
1523                                 if (reason != NULL and reasonCount < maxCount)
1524                                 {
1525                                         reason[reasonCount] = kFoundDuplicateHits;
1526                                         reasonCount++;
1527                                 }
1528                                 result = false;
1529                         }
1530                 }
1531         }
1532
1533         // Check integrity of the individual hit structures.
1534         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1535         {
1536                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1537                 if (not IntegrityOk(hit[i], reason+reasonCount, filledCount))
1538                 {
1539                         // reasons filled in IntegrityOk, now we just need to adjust
1540                         // reasonCount and fill the recordNum values.
1541                         if (recordNum != NULL)
1542                         {
1543                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1544                                         recordNum[reasonCount + n] = i;
1545                         }
1546                         reasonCount += filledCount;
1547                         result = false;
1548                 }
1549         }
1550         
1551         return result;
1552 }
1553
1554
1555 bool AliHLTMUONUtils::IntegrityOk(
1556                 const AliHLTMUONClusterStruct& cluster,
1557                 WhyNotValid* reason,
1558                 AliHLTUInt32_t& reasonCount
1559         )
1560 {
1561         /// This method is used to check more extensively if the integrity of the
1562         /// cluster structure is OK and returns true in that case.
1563         /// [in] \param cluster  The cluster structure to check.
1564         /// [out] \param reason  If this is not NULL, then it is assumed to point
1565         ///      to an array of at least 'reasonCount' number of elements. It will
1566         ///      be filled with the reason codes describing why the structure is
1567         ///      not valid.
1568         /// [in/out] \param reasonCount  This should initially specify the size of
1569         ///      the array pointed to by 'reason'. It will be filled with the number
1570         ///      of items actually filled into the reason array upon exit from this
1571         ///      method.
1572         /// \returns  true if there is no problem with the structure and false otherwise.
1573         
1574         AliHLTUInt32_t maxCount = reasonCount;
1575         reasonCount = 0;
1576         bool result = true;
1577         
1578         // Check that the cluster ID has a valid value.
1579         if (not (cluster.fId >= 0 or cluster.fId == -1))
1580         {
1581                 if (reason != NULL and reasonCount < maxCount)
1582                 {
1583                         reason[reasonCount] = kInvalidIdValue;
1584                         reasonCount++;
1585                 }
1586                 result = false;
1587         }
1588         
1589         // Check that the cluster does not have a nil value for its hit.
1590         if (cluster.fHit == AliHLTMUONConstants::NilRecHitStruct())
1591         {
1592                 if (reason != NULL and reasonCount < maxCount)
1593                 {
1594                         reason[reasonCount] = kHitIsNil;
1595                         reasonCount++;
1596                 }
1597                 result = false;
1598         }
1599         
1600         // Make sure the detector element is a valid value.
1601         if (not ((cluster.fDetElemId >= 100 and cluster.fDetElemId < 1500)
1602             or cluster.fDetElemId == -1)
1603            )
1604         {
1605                 if (reason != NULL and reasonCount < maxCount)
1606                 {
1607                         reason[reasonCount] = kInvalidDetElementNumber;
1608                         reasonCount++;
1609                 }
1610                 result = false;
1611         }
1612         
1613         // The number of channels should be in a reasonable range.
1614         // between 1 and the maximum number of channels per DDL.
1615         // 1<<17 taken from the 11 bits MANU ID + 6 bits channel address.
1616         if (cluster.fNchannels < 1 or (1<<17) < cluster.fNchannels)
1617         {
1618                 if (reason != NULL and reasonCount < maxCount)
1619                 {
1620                         reason[reasonCount] = kInvalidChannelCount;
1621                         reasonCount++;
1622                 }
1623                 result = false;
1624         }
1625
1626         return result;
1627 }
1628
1629
1630 bool AliHLTMUONUtils::IntegrityOk(
1631                 const AliHLTMUONClustersBlockStruct& block,
1632                 WhyNotValid* reason,
1633                 AliHLTUInt32_t* recordNum,
1634                 AliHLTUInt32_t& reasonCount
1635         )
1636 {
1637         /// This method is used to check more extensively if the integrity of the
1638         /// dHLT internal clusters data block is OK and returns true in that case.
1639         /// [in] \param block  The clusters data block to check.
1640         /// [out] \param reason  If this is not NULL, then it is assumed to point
1641         ///      to an array of at least 'reasonCount' number of elements. It will
1642         ///      be filled with the reason codes describing why the data block is
1643         ///      not valid.
1644         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1645         ///      to an array of at least 'reasonCount' number of elements. It will
1646         ///      be filled with the number of the cluster structure that had a problem.
1647         ///      The value 'recordNum[i]' will only contain a valid value if
1648         ///      the corresponding 'reason[i]' contains one of:
1649         ///        - kInvalidIdValue
1650         ///        - kHitIsNil
1651         ///        - kInvalidDetElementNumber
1652         ///        - kInvalidChannelCount
1653         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1654         ///      was set and is valid or not.
1655         /// [in/out] \param reasonCount  This should initially specify the size of
1656         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1657         ///      with the number of items actually filled into the arrays upon exit
1658         ///      from this method.
1659         /// \returns  true if there is no problem with the data and false otherwise.
1660         
1661         AliHLTUInt32_t maxCount = reasonCount;
1662         bool result = HeaderOk(block, reason, reasonCount);
1663
1664         const AliHLTMUONClusterStruct* cluster =
1665                 reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
1666         
1667         // Check if any ID is duplicated.
1668         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1669         {
1670                 AliHLTInt32_t id = cluster[i].fId;
1671                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1672                 {
1673                         if (id == cluster[j].fId)
1674                         {
1675                                 if (reason != NULL and reasonCount < maxCount)
1676                                 {
1677                                         reason[reasonCount] = kFoundDuplicateIDs;
1678                                         reasonCount++;
1679                                 }
1680                                 result = false;
1681                         }
1682                 }
1683         }
1684
1685         // Check if any hit structure has been duplicated.
1686         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1687         {
1688                 const AliHLTMUONRecHitStruct& h = cluster[i].fHit;
1689                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1690                 {
1691                         if (h == cluster[j].fHit)
1692                         {
1693                                 if (reason != NULL and reasonCount < maxCount)
1694                                 {
1695                                         reason[reasonCount] = kFoundDuplicateHits;
1696                                         reasonCount++;
1697                                 }
1698                                 result = false;
1699                         }
1700                 }
1701         }
1702
1703         // Check integrity of individual cluster structures.
1704         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1705         {
1706                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1707                 if (not IntegrityOk(cluster[i], reason+reasonCount, filledCount))
1708                 {
1709                         // reasons filled in IntegrityOk, now we just need to adjust
1710                         // reasonCount and fill the recordNum values.
1711                         if (recordNum != NULL)
1712                         {
1713                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1714                                         recordNum[reasonCount + n] = i;
1715                         }
1716                         reasonCount += filledCount;
1717                         result = false;
1718                 }
1719         }
1720         
1721         return result;
1722 }
1723
1724
1725 bool AliHLTMUONUtils::IntegrityOk(
1726                 const AliHLTMUONChannelStruct& channel,
1727                 WhyNotValid* reason,
1728                 AliHLTUInt32_t& reasonCount
1729         )
1730 {
1731         /// This method is used to check more extensively if the integrity of the
1732         /// channel structure is OK and returns true in that case.
1733         /// [in] \param cluster  The channel structure to check.
1734         /// [out] \param reason  If this is not NULL, then it is assumed to point
1735         ///      to an array of at least 'reasonCount' number of elements. It will
1736         ///      be filled with the reason codes describing why the structure is
1737         ///      not valid.
1738         /// [in/out] \param reasonCount  This should initially specify the size of
1739         ///      the array pointed to by 'reason'. It will be filled with the number
1740         ///      of items actually filled into the reason array upon exit from this
1741         ///      method.
1742         /// \returns  true if there is no problem with the structure and false otherwise.
1743         
1744         AliHLTUInt32_t maxCount = reasonCount;
1745         reasonCount = 0;
1746         bool result = true;
1747         
1748         // Check that the channel ID has a valid value.
1749         if (not (channel.fClusterId >= 0 or channel.fClusterId == -1))
1750         {
1751                 if (reason != NULL and reasonCount < maxCount)
1752                 {
1753                         reason[reasonCount] = kInvalidIdValue;
1754                         reasonCount++;
1755                 }
1756                 result = false;
1757         }
1758         
1759         // Check that the bus patch ID has a valid value, which fits into 12 bits.
1760         if ((channel.fBusPatch & (~0xFFF)) != 0)
1761         {
1762                 if (reason != NULL and reasonCount < maxCount)
1763                 {
1764                         reason[reasonCount] = kInvalidBusPatchId;
1765                         reasonCount++;
1766                 }
1767                 result = false;
1768         }
1769         
1770         // Check that the MANU ID has a valid value, which fits into 11 bits.
1771         if ((channel.fManu & (~0x7FF)) != 0)
1772         {
1773                 if (reason != NULL and reasonCount < maxCount)
1774                 {
1775                         reason[reasonCount] = kInvalidManuId;
1776                         reasonCount++;
1777                 }
1778                 result = false;
1779         }
1780         
1781         // Check that the channel address has a valid value, which fits into 6 bits.
1782         if ((channel.fChannelAddress & (~0x3F)) != 0)
1783         {
1784                 if (reason != NULL and reasonCount < maxCount)
1785                 {
1786                         reason[reasonCount] = kInvalidChannelAddress;
1787                         reasonCount++;
1788                 }
1789                 result = false;
1790         }
1791         
1792         // Check that the ADC signal has a valid value, which fits into 12 bits.
1793         if ((channel.fSignal & (~0xFFF)) != 0)
1794         {
1795                 if (reason != NULL and reasonCount < maxCount)
1796                 {
1797                         reason[reasonCount] = kInvalidSignal;
1798                         reasonCount++;
1799                 }
1800                 result = false;
1801         }
1802         
1803         // Check that the raw data word corresponds to the unpacked values for
1804         // the ADC signal, MANU ID and channel address.
1805         UShort_t manuId; UChar_t channelId; UShort_t adc;
1806         AliMUONTrackerDDLDecoderEventHandler::UnpackADC(
1807                         channel.fRawDataWord, manuId, channelId, adc
1808                 );
1809         if (manuId != channel.fManu or channelId != channel.fChannelAddress
1810             or adc != channel.fSignal
1811            )
1812         {
1813                 if (reason != NULL and reasonCount < maxCount)
1814                 {
1815                         reason[reasonCount] = kDataWordDifferent;
1816                         reasonCount++;
1817                 }
1818                 result = false;
1819         }
1820
1821         return result;
1822 }
1823
1824
1825 bool AliHLTMUONUtils::IntegrityOk(
1826                 const AliHLTMUONChannelsBlockStruct& block,
1827                 WhyNotValid* reason,
1828                 AliHLTUInt32_t* recordNum,
1829                 AliHLTUInt32_t& reasonCount
1830         )
1831 {
1832         /// This method is used to check more extensively if the integrity of the
1833         /// dHLT internal channels data block is OK and returns true in that case.
1834         /// [in] \param block  The channels data block to check.
1835         /// [out] \param reason  If this is not NULL, then it is assumed to point
1836         ///      to an array of at least 'reasonCount' number of elements. It will
1837         ///      be filled with the reason codes describing why the data block is
1838         ///      not valid.
1839         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1840         ///      to an array of at least 'reasonCount' number of elements. It will
1841         ///      be filled with the number of the channel structure that had a problem.
1842         ///      The value 'recordNum[i]' will only contain a valid value if
1843         ///      the corresponding 'reason[i]' contains one of:
1844         ///        - kInvalidIdValue
1845         ///        - kInvalidBusPatchId
1846         ///        - kInvalidManuId
1847         ///        - kInvalidChannelAddress
1848         ///        - kInvalidSignal
1849         ///        - kDataWordDifferent
1850         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1851         ///      was set and is valid or not.
1852         /// [in/out] \param reasonCount  This should initially specify the size of
1853         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1854         ///      with the number of items actually filled into the arrays upon exit
1855         ///      from this method.
1856         /// \returns  true if there is no problem with the data and false otherwise.
1857         
1858         AliHLTUInt32_t maxCount = reasonCount;
1859         bool result = HeaderOk(block, reason, reasonCount);
1860         
1861         const AliHLTMUONChannelStruct* channel =
1862                 reinterpret_cast<const AliHLTMUONChannelStruct*>(&block + 1);
1863         
1864         // Check if any cluster ID is duplicated.
1865         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1866         {
1867                 AliHLTInt32_t id = channel[i].fClusterId;
1868                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1869                 {
1870                         if (id == channel[j].fClusterId)
1871                         {
1872                                 if (reason != NULL and reasonCount < maxCount)
1873                                 {
1874                                         reason[reasonCount] = kFoundDuplicateIDs;
1875                                         reasonCount++;
1876                                 }
1877                                 result = false;
1878                         }
1879                 }
1880         }
1881
1882         // Check integrity of individual channel structures.
1883         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1884         {
1885                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1886                 if (not IntegrityOk(channel[i], reason+reasonCount, filledCount))
1887                 {
1888                         // reasons filled in IntegrityOk, now we just need to adjust
1889                         // reasonCount and fill the recordNum values.
1890                         if (recordNum != NULL)
1891                         {
1892                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1893                                         recordNum[reasonCount + n] = i;
1894                         }
1895                         reasonCount += filledCount;
1896                         result = false;
1897                 }
1898         }
1899         
1900         return result;
1901 }
1902
1903
1904 bool AliHLTMUONUtils::IntegrityOk(
1905                 const AliHLTMUONMansoTrackStruct& track,
1906                 WhyNotValid* reason,
1907                 AliHLTUInt32_t& reasonCount
1908         )
1909 {
1910         /// This method is used to check more extensively if the integrity of the
1911         /// Manso track structure is OK and returns true in that case.
1912         /// [in] \param track  The track structure to check.
1913         /// [out] \param reason  If this is not NULL, then it is assumed to point
1914         ///      to an array of at least 'reasonCount' number of elements. It will
1915         ///      be filled with the reason codes describing why the structure is
1916         ///      not valid.
1917         /// [in/out] \param reasonCount  This should initially specify the size of
1918         ///      the array pointed to by 'reason'. It will be filled with the number
1919         ///      of items actually filled into the reason array upon exit from this
1920         ///      method.
1921         /// \returns  true if there is no problem with the structure and false otherwise.
1922         
1923         AliHLTUInt32_t maxCount = reasonCount;
1924         reasonCount = 0;
1925         bool result = true;
1926         
1927         // Check that the Manso track ID has a valid value.
1928         if (not (track.fId >= 0 or track.fId == -1))
1929         {
1930                 if (reason != NULL and reasonCount < maxCount)
1931                 {
1932                         reason[reasonCount] = kInvalidIdValue;
1933                         reasonCount++;
1934                 }
1935                 result = false;
1936         }
1937         
1938         // Check that the corresponding trigger record ID has a valid value.
1939         if (not (track.fTrigRec >= 0 or track.fTrigRec == -1))
1940         {
1941                 if (reason != NULL and reasonCount < maxCount)
1942                 {
1943                         reason[reasonCount] = kInvalidTriggerIdValue;
1944                         reasonCount++;
1945                 }
1946                 result = false;
1947         }
1948         
1949         // Make sure that the reserved bits in the fFlags field are set
1950         // to zero.
1951         if ((track.fFlags & 0x3FFFFFF0) != 0)
1952         {
1953                 if (reason != NULL and reasonCount < maxCount)
1954                 {
1955                         reason[reasonCount] = kReservedBitsNotZero;
1956                         reasonCount++;
1957                 }
1958                 result = false;
1959         }
1960
1961         // Make sure the sign is not invalid.
1962         if ((track.fFlags & 0xC0000000) == 0xC0000000)
1963         {
1964                 if (reason != NULL and reasonCount < maxCount)
1965                 {
1966                         reason[reasonCount] = kParticleSignBitsNotValid;
1967                         reasonCount++;
1968                 }
1969                 result = false;
1970         }
1971
1972         // Check that fHit[i] is nil if the corresponding bit in the
1973         // flags word is zero.
1974         const AliHLTMUONRecHitStruct& nilhit
1975                 = AliHLTMUONConstants::NilRecHitStruct();
1976         if ( ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) or
1977              ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) or
1978              ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) or
1979              ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
1980            )
1981         {
1982                 if (reason != NULL and reasonCount < maxCount)
1983                 {
1984                         reason[reasonCount] = kHitNotMarkedAsNil;
1985                         reasonCount++;
1986                 }
1987                 result = false;
1988         }
1989
1990         // Check that the chi squared value is valid
1991         if (not (track.fChi2 >= 0 or track.fChi2 == -1))
1992         {
1993                 if (reason != NULL and reasonCount < maxCount)
1994                 {
1995                         reason[reasonCount] = kChiSquareInvalid;
1996                         reasonCount++;
1997                 }
1998                 result = false;
1999         }
2000
2001         // Check that if chi squared is -1 then the momentum vector is zero.
2002         if (track.fChi2 == -1 and
2003             not (track.fPx == 0 and track.fPy == 0 and track.fPz == 0)
2004            )
2005         {
2006                 if (reason != NULL and reasonCount < maxCount)
2007                 {
2008                         reason[reasonCount] = kMomentumVectorNotZero;
2009                         reasonCount++;
2010                 }
2011                 result = false;
2012         }
2013         
2014         // Check the individual hits
2015         for (int i = 0; i < 4; i++)
2016         {
2017                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2018                 if (not IntegrityOk(track.fHit[i], reason + reasonCount, filledCount))
2019                 {
2020                         reasonCount += filledCount;
2021                         result = false;
2022                 }
2023         }
2024         
2025         return result;
2026 }
2027
2028
2029 bool AliHLTMUONUtils::IntegrityOk(
2030                 const AliHLTMUONMansoTracksBlockStruct& block,
2031                 WhyNotValid* reason,
2032                 AliHLTUInt32_t* recordNum,
2033                 AliHLTUInt32_t& reasonCount
2034         )
2035 {
2036         /// This method is used to check more extensively if the integrity of the
2037         /// dHLT internal Manso track data block is OK and returns true in that case.
2038         /// [in] \param block  The Manso track data block to check.
2039         /// [out] \param reason  If this is not NULL, then it is assumed to point
2040         ///      to an array of at least 'reasonCount' number of elements. It will
2041         ///      be filled with the reason codes describing why the data block is
2042         ///      not valid.
2043         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2044         ///      to an array of at least 'reasonCount' number of elements. It will
2045         ///      be filled with the number of the Manso track that had a problem.
2046         ///      The value 'recordNum[i]' will only contain a valid value if
2047         ///      the corresponding 'reason[i]' contains one of:
2048         ///        - kInvalidIdValue
2049         ///        - kInvalidTriggerIdValue
2050         ///        - kReservedBitsNotZero
2051         ///        - kParticleSignBitsNotValid
2052         ///        - kHitNotMarkedAsNil
2053         ///        - kChiSquareInvalid
2054         ///        - kMomentumVectorNotZero
2055         ///        - kInvalidDetElementNumber
2056         ///        - kInvalidChamberNumber
2057         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2058         ///      was set and is valid or not.
2059         /// [in/out] \param reasonCount  This should initially specify the size of
2060         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2061         ///      with the number of items actually filled into the arrays upon exit
2062         ///      from this method.
2063         /// \returns  true if there is no problem with the data and false otherwise.
2064         
2065         AliHLTUInt32_t maxCount = reasonCount;
2066         bool result = HeaderOk(block, reason, reasonCount);
2067         
2068         const AliHLTMUONMansoTrackStruct* track =
2069                 reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
2070         
2071         // Check if any track ID is duplicated.
2072         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2073         {
2074                 AliHLTInt32_t id = track[i].fId;
2075                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2076                 {
2077                         if (id == track[j].fId)
2078                         {
2079                                 if (reason != NULL and reasonCount < maxCount)
2080                                 {
2081                                         reason[reasonCount] = kFoundDuplicateIDs;
2082                                         reasonCount++;
2083                                 }
2084                                 result = false;
2085                         }
2086                 }
2087         }
2088         
2089         // Check that all the tracks have integrity.
2090         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2091         {
2092                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2093                 if (not IntegrityOk(track[i], reason+reasonCount, filledCount))
2094                 {
2095                         // reasons filled in IntegrityOk, now we just need to adjust
2096                         // reasonCount and fill the recordNum values.
2097                         if (recordNum != NULL)
2098                         {
2099                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2100                                         recordNum[reasonCount + n] = i;
2101                         }
2102                         reasonCount += filledCount;
2103                         result = false;
2104                 }
2105         }
2106         
2107         return result;
2108 }
2109
2110
2111 bool AliHLTMUONUtils::IntegrityOk(
2112                 const AliHLTMUONMansoCandidateStruct& candidate,
2113                 WhyNotValid* reason,
2114                 AliHLTUInt32_t& reasonCount
2115         )
2116 {
2117         /// This method is used to check more extensively if the integrity of the
2118         /// Manso track candidate structure is OK and returns true in that case.
2119         /// [in] \param track  The track candidate structure to check.
2120         /// [out] \param reason  If this is not NULL, then it is assumed to point
2121         ///      to an array of at least 'reasonCount' number of elements. It will
2122         ///      be filled with the reason codes describing why the structure is
2123         ///      not valid.
2124         /// [in/out] \param reasonCount  This should initially specify the size of
2125         ///      the array pointed to by 'reason'. It will be filled with the number
2126         ///      of items actually filled into the reason array upon exit from this
2127         ///      method.
2128         /// \returns  true if there is no problem with the structure and false otherwise.
2129         
2130         // First check the integrity of the candidate track structure.
2131         AliHLTUInt32_t maxCount = reasonCount;
2132         bool result = IntegrityOk(candidate.fTrack, reason, reasonCount);
2133         
2134         // Now check that the ROIs are reasonable.
2135         // The radius must be positive or -1 indicating computation error and
2136         // the corresponding hit in the track must be within the ROI.
2137         for (AliHLTUInt32_t i = 0; i < 4; i++)
2138         {
2139                 if (not (candidate.fRoI[i].fRadius >= 0 or candidate.fRoI[i].fRadius == -1))
2140                 {
2141                         if (reason != NULL and reasonCount < maxCount)
2142                         {
2143                                 reason[reasonCount] = kRoiRadiusInvalid;
2144                                 reasonCount++;
2145                         }
2146                         result = false;
2147                 }
2148                 
2149                 // Check if the corresponding hit was even found in the track.
2150                 if ( (candidate.fTrack.fFlags & (0x1 << i)) == 0 ) continue;
2151                 
2152                 double dx = candidate.fRoI[i].fX - candidate.fTrack.fHit[i].fX;
2153                 double dy = candidate.fRoI[i].fY - candidate.fTrack.fHit[i].fY;
2154                 double dz = candidate.fRoI[i].fZ - candidate.fTrack.fHit[i].fZ;
2155                 double r = sqrt(dx*dx + dy*dy);
2156                 // Check if the projected distance between ROI centre and hit is
2157                 // bigger than the ROI radius. Also the difference between z
2158                 // coordinates should not exceed 20 cm.
2159                 if (r > candidate.fRoI[i].fRadius or fabs(dz) > 20.)
2160                 {
2161                         if (reason != NULL and reasonCount < maxCount)
2162                         {
2163                                 reason[reasonCount] = kHitNotWithinRoi;
2164                                 reasonCount++;
2165                         }
2166                         result = false;
2167                 }
2168         }
2169         
2170         return result;
2171 }
2172
2173
2174 bool AliHLTMUONUtils::IntegrityOk(
2175                 const AliHLTMUONMansoCandidatesBlockStruct& block,
2176                 WhyNotValid* reason,
2177                 AliHLTUInt32_t* recordNum,
2178                 AliHLTUInt32_t& reasonCount
2179         )
2180 {
2181         /// This method is used to check more extensively if the integrity of the
2182         /// dHLT internal Manso candidates data block is OK and returns true in
2183         /// that case.
2184         /// [in] \param block  The Manso track candidate data block to check.
2185         /// [out] \param reason  If this is not NULL, then it is assumed to point
2186         ///      to an array of at least 'reasonCount' number of elements. It will
2187         ///      be filled with the reason codes describing why the data block is
2188         ///      not valid.
2189         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2190         ///      to an array of at least 'reasonCount' number of elements. It will
2191         ///      be filled with the number of the track candidate that had a problem.
2192         ///      The value 'recordNum[i]' will only contain a valid value if
2193         ///      the corresponding 'reason[i]' contains one of:
2194         ///        - kInvalidIdValue
2195         ///        - kInvalidTriggerIdValue
2196         ///        - kReservedBitsNotZero
2197         ///        - kParticleSignBitsNotValid
2198         ///        - kHitNotMarkedAsNil
2199         ///        - kChiSquareInvalid
2200         ///        - kRoiRadiusInvalid
2201         ///        - kHitNotWithinRoi
2202         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2203         ///      was set and is valid or not.
2204         /// [in/out] \param reasonCount  This should initially specify the size of
2205         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2206         ///      with the number of items actually filled into the arrays upon exit
2207         ///      from this method.
2208         /// \returns  true if there is no problem with the data and false otherwise.
2209         
2210         AliHLTUInt32_t maxCount = reasonCount;
2211         bool result = HeaderOk(block, reason, reasonCount);
2212
2213         const AliHLTMUONMansoCandidateStruct* candidate =
2214                 reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
2215         
2216         // Check if any candidate track ID is duplicated.
2217         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2218         {
2219                 AliHLTInt32_t id = candidate[i].fTrack.fId;
2220                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2221                 {
2222                         if (id == candidate[j].fTrack.fId)
2223                         {
2224                                 if (reason != NULL and reasonCount < maxCount)
2225                                 {
2226                                         reason[reasonCount] = kFoundDuplicateIDs;
2227                                         reasonCount++;
2228                                 }
2229                                 result = false;
2230                         }
2231                 }
2232         }
2233         
2234         // Check that all the track candidates have integrity.
2235         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2236         {
2237                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2238                 if (not IntegrityOk(candidate[i], reason+reasonCount, filledCount))
2239                 {
2240                         // reasons filled in IntegrityOk, now we just need to adjust
2241                         // reasonCount and fill the recordNum values.
2242                         if (recordNum != NULL)
2243                         {
2244                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2245                                         recordNum[reasonCount + n] = i;
2246                         }
2247                         reasonCount += filledCount;
2248                         result = false;
2249                 }
2250         }
2251         
2252         return result;
2253 }
2254
2255
2256 bool AliHLTMUONUtils::IntegrityOk(
2257                 const AliHLTMUONTrackDecisionStruct& decision,
2258                 WhyNotValid* reason,
2259                 AliHLTUInt32_t& reasonCount
2260         )
2261 {
2262         /// This method is used to check more extensively if the integrity of the
2263         /// single track trigger decision structure is OK and returns true in that case.
2264         /// [in] \param decision  The trigger decision structure to check.
2265         /// [out] \param reason  If this is not NULL, then it is assumed to point
2266         ///      to an array of at least 'reasonCount' number of elements. It will
2267         ///      be filled with the reason codes describing why the structure is not
2268         ///      valid.
2269         /// [in/out] \param reasonCount  This should initially specify the size of
2270         ///      the array pointed to by 'reason'. It will be filled with the number
2271         ///      of items actually filled into the reason array upon exit from this
2272         ///      method.
2273         /// \returns  true if there is no problem with the structure and false otherwise.
2274         
2275         AliHLTUInt32_t maxCount = reasonCount;
2276         reasonCount = 0;
2277         bool result = true;
2278         
2279         // The track ID value must be positive or -1.
2280         if (not (decision.fTrackId >= 0 or decision.fTrackId == -1))
2281         {
2282                 if (reason != NULL and reasonCount < maxCount)
2283                 {
2284                         reason[reasonCount] = kInvalidTrackIdValue;
2285                         reasonCount++;
2286                 }
2287                 result = false;
2288         }
2289         
2290         // Make sure that the reserved bits in the fTriggerBits field are set
2291         // to zero.
2292         if ((decision.fTriggerBits & 0xFFFFFFFC) != 0)
2293         {
2294                 if (reason != NULL and reasonCount < maxCount)
2295                 {
2296                         reason[reasonCount] = kReservedBitsNotZero;
2297                         reasonCount++;
2298                 }
2299                 result = false;
2300         }
2301         
2302         // The pT should be -1 or a positive number.
2303         if (decision.fPt != -1. and decision.fPt < 0.)
2304         {
2305                 if (reason != NULL and reasonCount < maxCount)
2306                 {
2307                         reason[reasonCount] = kPtValueNotValid;
2308                         reasonCount++;
2309                 }
2310                 result = false;
2311         }
2312         
2313         return result;
2314 }
2315
2316
2317 bool AliHLTMUONUtils::IntegrityOk(
2318                 const AliHLTMUONSinglesDecisionBlockStruct& block,
2319                 WhyNotValid* reason,
2320                 AliHLTUInt32_t* recordNum,
2321                 AliHLTUInt32_t& reasonCount
2322         )
2323 {
2324         /// This method is used to check more extensively if the integrity of the
2325         /// dHLT internal single track trigger decision data block is OK and returns
2326         /// true in that case.
2327         /// [in] \param block  The single track trigger decision data block to check.
2328         /// [out] \param reason  If this is not NULL, then it is assumed to point
2329         ///      to an array of at least 'reasonCount' number of elements. It will
2330         ///      be filled with the reason codes describing why the data block is
2331         ///      not valid.
2332         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2333         ///      to an array of at least 'reasonCount' number of elements. It will
2334         ///      be filled with the number of the trigger decision that had a problem.
2335         ///      The value 'recordNum[i]' will only contain a valid value if
2336         ///      the corresponding 'reason[i]' contains one of:
2337         ///        - kInvalidTrackIdValue
2338         ///        - kReservedBitsNotZero
2339         ///        - kPtValueNotValid
2340         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2341         ///      was set and is valid or not.
2342         /// [in/out] \param reasonCount  This should initially specify the size of
2343         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2344         ///      with the number of items actually filled into the arrays upon exit
2345         ///      from this method.
2346         /// \returns  true if there is no problem with the data and false otherwise.
2347         
2348         AliHLTUInt32_t maxCount = reasonCount;
2349         bool result = HeaderOk(block, reason, reasonCount);
2350         
2351         const AliHLTMUONTrackDecisionStruct* decision =
2352                 reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
2353
2354         // Check that there are no duplicate trigger entries.
2355         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2356         {
2357                 AliHLTInt32_t id = decision[i].fTrackId;
2358                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2359                 {
2360                         if (id == decision[j].fTrackId)
2361                         {
2362                                 if (reason != NULL and reasonCount < maxCount)
2363                                 {
2364                                         reason[reasonCount] = kFoundDuplicateTriggers;
2365                                         reasonCount++;
2366                                 }
2367                                 result = false;
2368                         }
2369                 }
2370         }
2371         
2372         // Check that the trigger bits for each track have integrity.
2373         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2374         {
2375                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2376                 if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
2377                 {
2378                         // Reasons filled in IntegrityOk, now we just need to adjust
2379                         // reasonCount and fill the recordNum values.
2380                         if (recordNum != NULL)
2381                         {
2382                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2383                                         recordNum[reasonCount + n] = i;
2384                         }
2385                         reasonCount += filledCount;
2386                         result = false;
2387                 }
2388         }
2389         
2390         return result;
2391 }
2392
2393
2394 bool AliHLTMUONUtils::IntegrityOk(
2395                 const AliHLTMUONPairDecisionStruct& decision,
2396                 WhyNotValid* reason,
2397                 AliHLTUInt32_t& reasonCount
2398         )
2399 {
2400         /// This method is used to check more extensively if the integrity of the
2401         /// track pair trigger decision structure is OK and returns true in that case.
2402         /// [in] \param decision  The trigger decision structure to check.
2403         /// [out] \param reason  If this is not NULL, then it is assumed to point
2404         ///      to an array of at least 'reasonCount' number of elements. It will
2405         ///      be filled with the reason codes describing why the structure is not
2406         ///      valid.
2407         /// [in/out] \param reasonCount  This should initially specify the size of
2408         ///      the array pointed to by 'reason'. It will be filled with the number
2409         ///      of items actually filled into the reason array upon exit from this
2410         ///      method.
2411         /// \returns  true if there is no problem with the structure and false otherwise.
2412         
2413         AliHLTUInt32_t maxCount = reasonCount;
2414         reasonCount = 0;
2415         bool result = true;
2416         
2417         //kInvalidTrackIdValue
2418         
2419         // The track IDs must have a positive value or -1.
2420         if (not (decision.fTrackAId >= 0 or decision.fTrackAId == -1) or
2421             not (decision.fTrackBId >= 0 or decision.fTrackBId == -1)
2422            )
2423         {
2424                 if (reason != NULL and reasonCount < maxCount)
2425                 {
2426                         reason[reasonCount] = kInvalidTrackIdValue;
2427                         reasonCount++;
2428                 }
2429                 result = false;
2430         }
2431         
2432         // Make sure that the reserved bits in the fTriggerBits field are set
2433         // to zero.
2434         if ((decision.fTriggerBits & 0xFFFFFF80) != 0)
2435         {
2436                 if (reason != NULL and reasonCount < maxCount)
2437                 {
2438                         reason[reasonCount] = kReservedBitsNotZero;
2439                         reasonCount++;
2440                 }
2441                 result = false;
2442         }
2443         
2444         // Check that the track IDs are not the same.
2445         if (decision.fTrackAId == decision.fTrackBId)
2446         {
2447                 if (reason != NULL and reasonCount < maxCount)
2448                 {
2449                         reason[reasonCount] = kPairTrackIdsAreIdentical;
2450                         reasonCount++;
2451                 }
2452                 result = false;
2453         }
2454         
2455         // The invariant mass should be -1 or a positive number.
2456         if (decision.fInvMass != -1. and decision.fInvMass < 0.)
2457         {
2458                 if (reason != NULL and reasonCount < maxCount)
2459                 {
2460                         reason[reasonCount] = kMassValueNotValid;
2461                         reasonCount++;
2462                 }
2463                 result = false;
2464         }
2465         
2466         // Neither the high pt (hipt) or low pt (lopt) count bits can be > 2.
2467         AliHLTUInt8_t lowPtCount = (decision.fTriggerBits & 0x00000003);
2468         AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
2469         if (lowPtCount > 2)
2470         {
2471                 if (reason != NULL and reasonCount < maxCount)
2472                 {
2473                         reason[reasonCount] = kLowPtCountInvalid;
2474                         reasonCount++;
2475                 }
2476                 result = false;
2477         }
2478         if (highPtCount > 2)
2479         {
2480                 if (reason != NULL and reasonCount < maxCount)
2481                 {
2482                         reason[reasonCount] = kHighPtCountInvalid;
2483                         reasonCount++;
2484                 }
2485                 result = false;
2486         }
2487         
2488         return result;
2489 }
2490
2491
2492 bool AliHLTMUONUtils::IntegrityOk(
2493                 const AliHLTMUONPairsDecisionBlockStruct& block,
2494                 WhyNotValid* reason,
2495                 AliHLTUInt32_t* recordNum,
2496                 AliHLTUInt32_t& reasonCount
2497         )
2498 {
2499         /// This method is used to check more extensively if the integrity of the
2500         /// dHLT internal track pair trigger decision data block is OK and returns
2501         /// true in that case.
2502         /// [in] \param block  The track pair trigger decision data block to check.
2503         /// [out] \param reason  If this is not NULL, then it is assumed to point
2504         ///      to an array of at least 'reasonCount' number of elements. It will
2505         ///      be filled with the reason codes describing why the data block is
2506         ///      not valid.
2507         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2508         ///      to an array of at least 'reasonCount' number of elements. It will
2509         ///      be filled with the number of the trigger decision that had a problem.
2510         ///      The value 'recordNum[i]' will only contain a valid value if
2511         ///      the corresponding 'reason[i]' contains one of:
2512         ///        - kInvalidTrackIdValue
2513         ///        - kReservedBitsNotZero
2514         ///        - kPairTrackIdsAreIdentical
2515         ///        - kMassValueNotValid
2516         ///        - kLowPtCountInvalid
2517         ///        - kHighPtCountInvalid
2518         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2519         ///      was set and is valid or not.
2520         /// [in/out] \param reasonCount  This should initially specify the size of
2521         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2522         ///      with the number of items actually filled into the arrays upon exit
2523         ///      from this method.
2524         /// \returns  true if there is no problem with the data and false otherwise.
2525         
2526         AliHLTUInt32_t maxCount = reasonCount;
2527         bool result = HeaderOk(block, reason, reasonCount);
2528
2529         const AliHLTMUONPairDecisionStruct* decision =
2530                 reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
2531         
2532         // Check that there are no duplicate trigger entries.
2533         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2534         {
2535                 AliHLTInt32_t ta = decision[i].fTrackAId;
2536                 AliHLTInt32_t tb = decision[i].fTrackBId;
2537                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2538                 {
2539                         if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
2540                         {
2541                                 if (reason != NULL and reasonCount < maxCount)
2542                                 {
2543                                         reason[reasonCount] = kFoundDuplicateTriggers;
2544                                         reasonCount++;
2545                                 }
2546                                 result = false;
2547                         }
2548                 }
2549         }
2550         
2551         // Check that the trigger bits for each track pair have integrity.
2552         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2553         {
2554                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2555                 if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
2556                 {
2557                         // Reasons filled in IntegrityOk, now we just need to adjust
2558                         // reasonCount and fill the recordNum values.
2559                         if (recordNum != NULL)
2560                         {
2561                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2562                                         recordNum[reasonCount + n] = i;
2563                         }
2564                         reasonCount += filledCount;
2565                         result = false;
2566                 }
2567         }
2568         
2569         return result;
2570 }
2571