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