Fixing memory handling of AliHLTMUONHitReconstructorComponent during error conditions...
[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   
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 "AliHLTMUONTriggerChannelsBlockStruct.h"
30 #include "AliHLTMUONRecHitsBlockStruct.h"
31 #include "AliHLTMUONClustersBlockStruct.h"
32 #include "AliHLTMUONChannelsBlockStruct.h"
33 #include "AliHLTMUONMansoTracksBlockStruct.h"
34 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
35 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
36 #include "AliHLTMUONPairsDecisionBlockStruct.h"
37 #include <cstring>
38 #include <cassert>
39
40
41 AliHLTUInt32_t AliHLTMUONUtils::PackTriggerRecordFlags(
42                 AliHLTMUONParticleSign sign, const bool hitset[4]
43         )
44 {
45         ///
46         /// This packs the given parameters into the bits of a word appropriate
47         /// for AliHLTMUONTriggerRecordStruct::fFlags.
48         /// @param sign    The particle sign.
49         /// @param hitset  Flags to indicate if the corresponding fHits[i] elements
50         ///                was set/filled.
51         /// @return  Returns the 32 bit packed word.
52         ///
53         
54         AliHLTUInt32_t flags;
55         switch (sign)
56         {
57         case kSignMinus: flags = 0x80000000; break;
58         case kSignPlus:  flags = 0x40000000; break;
59         default:         flags = 0x00000000; break;
60         }
61
62         return flags | (hitset[0] ? 0x1 : 0) | (hitset[1] ? 0x2 : 0)
63                 | (hitset[2] ? 0x4 : 0) | (hitset[3] ? 0x8 : 0);
64 }
65
66
67 void AliHLTMUONUtils::UnpackTriggerRecordFlags(
68                 AliHLTUInt32_t flags, AliHLTMUONParticleSign& sign, bool hitset[4]
69         )
70 {
71         ///
72         /// This unpacks the AliHLTMUONTriggerRecordStruct::fFlags bits into
73         /// its component fields.
74         /// @param flags  The flags from an AliHLTMUONTriggerRecordStruct structure.
75         /// @param sign    Sets this to the particle sign.
76         /// @param hitset  Sets the array elements to indicate if the corresponding
77         ///                fHits[i] element was set/filled.
78         ///
79         
80         AliHLTUInt32_t signbits = flags & 0xC0000000;
81         switch (signbits)
82         {
83         case 0x80000000: sign = kSignMinus;   break;
84         case 0x40000000: sign = kSignPlus;    break;
85         default:         sign = kSignUnknown; break;
86         }
87         hitset[0] = (flags & 0x1) == 0x1;
88         hitset[1] = (flags & 0x2) == 0x2;
89         hitset[2] = (flags & 0x4) == 0x4;
90         hitset[3] = (flags & 0x8) == 0x8;
91 }
92
93
94 AliHLTUInt32_t AliHLTMUONUtils::PackTrackDecisionBits(bool highPt, bool lowPt)
95 {
96         ///
97         /// This packs the given parameters into the bits of a word appropriate
98         /// for AliHLTMUONTrackDecisionStruct::fTriggerBits.
99         /// @param highPt  Has the track passed the high pt cut.
100         /// @param lowPt   Has the track passed the low pt cut.
101         /// @return  Returns the 32 bit packed word.
102         ///
103         
104         return (highPt ? 0x2 : 0) | (lowPt ? 0x1 : 0);
105 }
106
107
108 void AliHLTMUONUtils::UnpackTrackDecisionBits(
109                 AliHLTUInt32_t bits, bool& highPt, bool& lowPt
110         )
111 {
112         ///
113         /// This unpacks the AliHLTMUONTrackDecisionStruct::fTriggerBits bits into
114         /// its component fields.
115         /// @param bits  The trigger bits from an AliHLTMUONTrackDecisionStruct
116         ///              structure.
117         /// @param highPt Sets this to the value of the high pt cut bit.
118         /// @param lowPt  Sets this to the value of the low pt cut bit.
119         ///
120         
121         lowPt  = (bits & 0x1) == 0x1;
122         highPt = (bits & 0x2) == 0x2;
123 }
124
125
126 AliHLTUInt32_t AliHLTMUONUtils::PackPairDecisionBits(
127                 bool highMass, bool lowMass, bool unlike,
128                 AliHLTUInt8_t highPtCount, AliHLTUInt8_t lowPtCount
129         )
130 {
131         ///
132         /// This packs the given parameters into the bits of a word appropriate
133         /// for AliHLTMUONPairDecisionStruct::fTriggerBits.
134         ///
135         /// @param highMass Has the track pair passed the high invariant mass cut.
136         /// @param lowMass  Has the track pair passed the low invariant mass cut.
137         /// @param unlike   Does the track pair have unlike signs.
138         /// @param highPtCount The number of tracks that passed the high pt cut
139         ///                    in the pair.
140         /// @param lowPtCount  The number of tracks that passed the low pt cut
141         ///                    in the pair.
142         /// @return  Returns the 32 bit packed word.
143         ///
144         /// Note: Must have highPtCount + lowPtCount <= 2 and unlike == true if
145         /// highMass or lowMass is true.
146         ///
147         
148         assert( highPtCount + lowPtCount <= 2 );
149         // highMass and lowMass must be false if unlike is false:
150         assert( not unlike ? (highMass == false and lowMass == false) : true );
151         
152         return (highMass ? 0x40 : 0) | (lowMass ? 0x20 : 0) | (unlike ? 0x10 : 0)
153                 | ((highPtCount & 0x3) << 2) | (lowPtCount & 0x3);
154 }
155
156
157 void AliHLTMUONUtils::UnpackPairDecisionBits(
158                 AliHLTUInt32_t bits, bool& highMass, bool& lowMass, bool& unlike,
159                 AliHLTUInt8_t& highPtCount, AliHLTUInt8_t& lowPtCount
160         )
161 {
162         ///
163         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
164         /// its component fields.
165         /// @param bits  The trigger bits from an AliHLTMUONPairDecisionStruct
166         ///              structure.
167         /// @param highMass Sets this to the value of the high invariant mass cut bit.
168         /// @param lowMass  Sets this to the value of the low invariant mass cut bit.
169         /// @param unlike   Sets this if the pair is unlike sign.
170         /// @param highPtCount Sets this to the high pt count bits.
171         /// @param lowPtCount  Sets this to the low pt count bits.
172         ///
173         
174         highMass = (bits & 0x40) == 0x40;
175         lowMass  = (bits & 0x20) == 0x20;
176         unlike   = (bits & 0x10) == 0x10;
177         highPtCount = (bits & 0xC) >> 2;
178         lowPtCount = bits & 0x3;
179 }
180
181
182 AliHLTUInt32_t AliHLTMUONUtils::PackSpecBits(
183                 const bool ddl[22]
184         )
185 {
186         ///
187         /// This packs the given parameters into the 32bit Pub/Sub specification
188         /// word in the data block descriptor.
189         ///
190         /// @param ddl  The list of DDLs forming part of the readout. ddl[0]
191         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
192         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
193         ///             trigger DDLs 2816 and 2817 respectively.
194         /// @return  Returns the 32 bit packed specification word.
195         ///
196         
197         // Pack the bits into the following format:
198         //   bit:   [        31 - 22        ][     21     ][     20     ][  19 - 0 ]
199         //   field: [ reserved, set to zero ][ TRGDDL2817 ][ TRGDDL2816 ][ TRKDDLS ]
200         // Meaning of field acronyms:
201         //   TRGDDL2816 - Trigger DDL number 2816.
202         //   TRGDDL2817 - Trigger DDL number 2817.
203         //   TRKDDLS - Tracking DDL flags where bit 0 will be for DDL number 2560,
204         //             bit 1 for DDL no. 2561 etc. up to bit 19 which is for DDL 2579.
205         AliHLTUInt32_t bits = 0;
206         for (int i = 0; i < 22; i++)
207                 bits |= (ddl[i] ? 0x1 : 0x0) << i;
208         return bits;
209 }
210
211
212 void AliHLTMUONUtils::UnpackSpecBits(
213                 AliHLTUInt32_t bits, bool ddl[22]
214         )
215 {
216         ///
217         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
218         /// its component fields.
219         /// @param bits  The Pub/Sub specification word from a data block descriptor.
220         /// @param ddl  The output list of DDLs forming part of the readout. ddl[0]
221         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
222         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
223         ///             trigger DDLs 2816 and 2817 respectively.
224         ///
225         
226         // Perform the inverse operation of PackSpecBits.
227         for (int i = 0; i < 22; i++)
228                 ddl[i] = ((bits >> i) & 0x1) == 1;
229 }
230
231
232 AliHLTInt32_t AliHLTMUONUtils::DDLNumberToEquipId(AliHLTInt32_t ddlNo)
233 {
234         ///
235         /// This method converts the DDL number for the muon spectrometer in the
236         /// range [0..21] to the equipment ID number.
237         /// @param ddlNo  The DDL number in the range [0..21].
238         /// @return  Returns the equipment ID number or -1 if ddlNo was invalid.
239         ///
240         
241         if (0 <= ddlNo and ddlNo <= 19)
242         {
243                 return 2560 + ddlNo;
244         }
245         else if (20 <= ddlNo and ddlNo <= 21)
246         {
247                 return 2816 + (ddlNo - 20);
248         }
249         else
250         {
251                 return -1;
252         }
253 }
254
255
256 AliHLTInt32_t AliHLTMUONUtils::EquipIdToDDLNumber(AliHLTInt32_t id)
257 {
258         ///
259         /// This method converts the equipment ID number for a muon spectrometer
260         /// DDL to the DDL number in the range [0..21].
261         /// @param id  The equipment ID of the DDL.
262         /// @return  Returns the DDL number in the range [0..21] or -1 if the
263         ///          equipment ID was invalid.
264         ///
265         
266         if (2560 <= id and id <= 2560+19)
267         {
268                 return id - 2560;
269         }
270         else if (2816 <= id and id <= 2817)
271         {
272                 return id - 2816 + 20;
273         }
274         else
275         {
276                 return -1;
277         }
278 }
279
280
281 AliHLTInt32_t AliHLTMUONUtils::SpecToEquipId(AliHLTUInt32_t spec)
282 {
283         ///
284         /// This method converts a 32 bit data block specification for a MUON-HLT
285         /// data block into its corresponding DDL equipment ID number.
286         /// It is assumed that the specification is for a data block comming from
287         /// a single DDL source. If more than one DDL contributed to the data block
288         /// then -1 is returned.
289         /// @param spec  The 32 bit specification for a data block.
290         /// @return  Returns the equipment ID corresponding to the specification
291         ///          or -1 if the specification was invalid.
292         ///
293         
294         for (AliHLTInt32_t ddlNo = 0; ddlNo < 20; ddlNo++)
295         {
296                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
297                         return ddlNo + 2560;
298         }
299         for (AliHLTInt32_t ddlNo = 20; ddlNo < 22; ddlNo++)
300         {
301                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
302                         return ddlNo - 20 + 2816;
303         }
304         return -1;
305 }
306
307
308 AliHLTUInt32_t AliHLTMUONUtils::EquipIdToSpec(AliHLTInt32_t id)
309 {
310         ///
311         /// This method converts a equipment ID number for a DDL into its corresponding
312         /// 32 bit data block specification for the MUON-HLT.
313         /// @param id  The equipment ID number of the DDL.
314         /// @return  Returns the 32 bit data block specification or 0x0 if the
315         ///          equipment ID was invalid.
316         ///
317         
318         if (2560 <= id and id <= 2560+19)
319         {
320                 return 0x1 << (id - 2560);
321         }
322         else if (2816 <= id and id <= 2817)
323         {
324                 return 0x1 << (id - 2816 + 20);
325         }
326         else
327         {
328                 return 0x0;
329         }
330 }
331
332
333 AliHLTInt32_t AliHLTMUONUtils::SpecToDDLNumber(AliHLTUInt32_t spec)
334 {
335         ///
336         /// This method converts a 32 bit data block specification for a MUON-HLT
337         /// data block into its corresponding DDL number in the range [0..21].
338         /// It is assumed that the specification is for a data block comming from
339         /// a single DDL source. If more than one DDL contributed to the data block
340         /// then -1 is returned.
341         /// @param spec  The 32 bit specification for a data block.
342         /// @return  Returns the corresponding DDL number for the specification
343         ///          or -1 if the specification was invalid.
344         ///
345         
346         for (AliHLTInt32_t ddlNo = 0; ddlNo < 22; ddlNo++)
347         {
348                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
349                         return ddlNo;
350         }
351         return -1;
352 }
353
354
355 AliHLTUInt32_t AliHLTMUONUtils::DDLNumberToSpec(AliHLTInt32_t ddlNo)
356 {
357         ///
358         /// This method converts a DDL number in the range [0..21] into its
359         /// corresponding 32 bit data block specification for the MUON-HLT.
360         /// @param ddlNo  The equipment ID number of the DDL.
361         /// @return  Returns the 32 bit data block specification or 0x0 if the
362         ///          DDL number was invalid (out of range).
363         ///
364         
365         if (0 <= ddlNo and ddlNo <= 21)
366         {
367                 return 0x1 << ddlNo;
368         }
369         else
370         {
371                 return 0x0;
372         }
373 }
374
375
376 AliHLTMUONDataBlockType AliHLTMUONUtils::ParseCommandLineTypeString(const char* type)
377 {
378         /// Parses the string containing the type name of a dHLT data block and
379         /// returns the corresponding AliHLTMUONDataBlockType value.
380         /// \param  type  The string containing the type name.
381         /// \returns  The data block type or kUnknownDataBlock if the type name
382         ///      is invalid.
383
384         if (strcmp(type, "trigrecs") == 0)
385         {
386                 return kTriggerRecordsDataBlock;
387         }
388         else if (strcmp(type, "trigrecsdebug") == 0)
389         {
390                 return kTrigRecsDebugDataBlock;
391         }
392         else if (strcmp(type, "trigchannels") == 0)
393         {
394                 return kTriggerChannelsDataBlock;
395         }
396         else if (strcmp(type, "rechits") == 0)
397         {
398                 return kRecHitsDataBlock;
399         }
400         else if (strcmp(type,"channels") == 0)
401         {
402                 return kChannelsDataBlock;
403         }
404         else if (strcmp(type,"clusters") == 0)
405         {
406                 return kClustersDataBlock;
407         }
408         else if (strcmp(type, "mansotracks") == 0)
409         {
410                 return kMansoTracksDataBlock;
411         }
412         else if (strcmp(type, "mansocandidates") == 0)
413         {
414                 return kMansoCandidatesDataBlock;
415         }
416         else if (strcmp(type, "singlesdecision") == 0)
417         {
418                 return kSinglesDecisionDataBlock;
419         }
420         else if (strcmp(type, "pairsdecision") == 0)
421         {
422                 return kPairsDecisionDataBlock;
423         }
424         
425         return kUnknownDataBlock;
426 }
427
428
429 const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid reason)
430 {
431         /// This method converts the WhyNotValid enumeration to a string representation.
432         
433         switch (reason)
434         {
435         case kNoReason: return "kNoReason";
436         case kHeaderContainsWrongType: return "kHeaderContainsWrongType";
437         case kHeaderContainsWrongRecordWidth: return "kHeaderContainsWrongRecordWidth";
438         case kReservedBitsNotZero: return "kReservedBitsNotZero";
439         case kParticleSignBitsNotValid: return "kParticleSignBitsNotValid";
440         case kHitNotMarkedAsNil: return "kHitNotMarkedAsNil";
441         case kFoundDuplicateIDs: return "kFoundDuplicateIDs";
442         case kPtValueNotValid: return "kPtValueNotValid";
443         case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
444         case kPairTrackIdsAreIdentical: return "kPairTrackIdsAreIdentical";
445         case kMassValueNotValid: return "kMassValueNotValid";
446         case kLowPtCountInvalid: return "kLowPtCountInvalid";
447         case kHighPtCountInvalid: return "kHighPtCountInvalid";
448         default: return "INVALID";
449         }
450 }
451
452
453 const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
454 {
455         /// This method returns a string containing a user readable message explaining
456         /// the reason for failure described by the WhyNotValid enumeration.
457         
458         switch (reason)
459         {
460         case kNoReason:
461                 return "There was no problem with the data block.";
462         case kHeaderContainsWrongType:
463                 return "The common data header contains an incorrect type identifier.";
464         case kHeaderContainsWrongRecordWidth:
465                 return "The common data header contains an incorrect data record width.";
466         case kReservedBitsNotZero:
467                 return "Reserved bits have not been set to zero.";
468         case kParticleSignBitsNotValid:
469                 return "The particle sign bits are not a valid value.";
470         case kHitNotMarkedAsNil:
471                 return "A hit was marked as not found, but the corresponding hit"
472                         " structure was not set to nil.";
473         case kFoundDuplicateIDs:
474                 return "Found duplicate data record identifiers, but they should all be unique.";
475         case kPtValueNotValid:
476                 return "The pT value is not positive, nor -1 indicating an invalid value.";
477         case kFoundDuplicateTriggers:
478                 return "Found duplicate trigger decisions.";
479         case kPairTrackIdsAreIdentical:
480                 return "The track identifiers of the track pair are identical.";
481         case kMassValueNotValid:
482                 return "The invariant mass value is not positive, nor -1 indicating an invalid value.";
483         case kLowPtCountInvalid:
484                 return "The low pT trigger count is greater than 2, which is invalid.";
485         case kHighPtCountInvalid:
486                 return "The high pT trigger count is greater than 2, which is invalid.";
487         default:
488                 return "UNKNOWN REASON CODE";
489         }
490 }
491
492
493 bool AliHLTMUONUtils::HeaderOk(
494                 const AliHLTMUONTriggerRecordsBlockStruct& block,
495                 WhyNotValid* reason
496         )
497 {
498         /// Method used to check if the header information corresponds to the
499         /// supposed type of the raw dHLT data block.
500         /// [in]  \param block  The data block to check.
501         /// [out] \param reason  If this is not NULL, then it will be filled with
502         ///      the reason code describing why the header is not valid, if and
503         ///      only if a problem is found with the data.
504         /// \returns  true if there is no problem with the header and false otherwise.
505          
506         // The block must have the correct type.
507         if (block.fHeader.fType != kTriggerRecordsDataBlock)
508         {
509                 if (reason != NULL) *reason = kHeaderContainsWrongType;
510                 return false;
511         }
512         
513         // The block's record width must be the correct size.
514         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerRecordStruct))
515         {
516                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
517                 return false;
518         }
519         
520         return true;
521 }
522
523
524 bool AliHLTMUONUtils::HeaderOk(
525                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
526                 WhyNotValid* reason
527         )
528 {
529         /// Method used to check if the header information corresponds to the
530         /// supposed type of the raw dHLT data block.
531         /// [in]  \param block  The data block to check.
532         /// [out] \param reason  If this is not NULL, then it will be filled with
533         ///      the reason code describing why the header is not valid, if and
534         ///      only if a problem is found with the data.
535         /// \returns  true if there is no problem with the header and false otherwise.
536         
537         // The block must have the correct type.
538         if (block.fHeader.fType != kTrigRecsDebugDataBlock)
539         {
540                 if (reason != NULL) *reason = kHeaderContainsWrongType;
541                 return false;
542         }
543         
544         // The block's record width must be the correct size.
545         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
546         {
547                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
548                 return false;
549         }
550         
551         return true;
552 }
553
554
555 bool AliHLTMUONUtils::HeaderOk(
556                 const AliHLTMUONTriggerChannelsBlockStruct& block,
557                 WhyNotValid* reason
558         )
559 {
560         /// Method used to check if the header information corresponds to the
561         /// supposed type of the raw dHLT data block.
562         /// [in]  \param block  The data block to check.
563         /// [out] \param reason  If this is not NULL, then it will be filled with
564         ///      the reason code describing why the header is not valid, if and
565         ///      only if a problem is found with the data.
566         /// \returns  true if there is no problem with the header and false otherwise.
567         
568         // The block must have the correct type.
569         if (block.fHeader.fType != kTriggerChannelsDataBlock)
570         {
571                 if (reason != NULL) *reason = kHeaderContainsWrongType;
572                 return false;
573         }
574         
575         // The block's record width must be the correct size.
576         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerChannelStruct))
577         {
578                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
579                 return false;
580         }
581         
582         return true;
583 }
584
585
586 bool AliHLTMUONUtils::HeaderOk(
587                 const AliHLTMUONRecHitsBlockStruct& block,
588                 WhyNotValid* reason
589         )
590 {
591         /// Method used to check if the header information corresponds to the
592         /// supposed type of the raw dHLT data block.
593         /// [in]  \param block  The data block to check.
594         /// [out] \param reason  If this is not NULL, then it will be filled with
595         ///      the reason code describing why the header is not valid, if and
596         ///      only if a problem is found with the data.
597         /// \returns  true if there is no problem with the header and false otherwise.
598         
599         // The block must have the correct type.
600         if (block.fHeader.fType != kRecHitsDataBlock)
601         {
602                 if (reason != NULL) *reason = kHeaderContainsWrongType;
603                 return false;
604         }
605         
606         // The block's record width must be the correct size.
607         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
608         {
609                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
610                 return false;
611         }
612         
613         return true;
614 }
615
616
617 bool AliHLTMUONUtils::HeaderOk(
618                 const AliHLTMUONClustersBlockStruct& block,
619                 WhyNotValid* reason
620         )
621 {
622         /// Method used to check if the header information corresponds to the
623         /// supposed type of the raw dHLT data block.
624         /// [in]  \param block  The data block to check.
625         /// [out] \param reason  If this is not NULL, then it will be filled with
626         ///      the reason code describing why the header is not valid, if and
627         ///      only if a problem is found with the data.
628         /// \returns  true if there is no problem with the header and false otherwise.
629         
630         // The block must have the correct type.
631         if (block.fHeader.fType != kClustersDataBlock)
632         {
633                 if (reason != NULL) *reason = kHeaderContainsWrongType;
634                 return false;
635         }
636         
637         // The block's record width must be the correct size.
638         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
639         {
640                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
641                 return false;
642         }
643         
644         return true;
645 }
646
647
648 bool AliHLTMUONUtils::HeaderOk(
649                 const AliHLTMUONChannelsBlockStruct& block,
650                 WhyNotValid* reason
651         )
652 {
653         /// Method used to check if the header information corresponds to the
654         /// supposed type of the raw dHLT data block.
655         /// [in]  \param block  The data block to check.
656         /// [out] \param reason  If this is not NULL, then it will be filled with
657         ///      the reason code describing why the header is not valid, if and
658         ///      only if a problem is found with the data.
659         /// \returns  true if there is no problem with the header and false otherwise.
660         
661         // The block must have the correct type.
662         if (block.fHeader.fType != kChannelsDataBlock)
663         {
664                 if (reason != NULL) *reason = kHeaderContainsWrongType;
665                 return false;
666         }
667         
668         // The block's record width must be the correct size.
669         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
670         {
671                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
672                 return false;
673         }
674         
675         return true;
676 }
677
678
679 bool AliHLTMUONUtils::HeaderOk(
680                 const AliHLTMUONMansoTracksBlockStruct& block,
681                 WhyNotValid* reason
682         )
683 {
684         /// Method used to check if the header information corresponds to the
685         /// supposed type of the raw dHLT data block.
686         /// [in]  \param block  The data block to check.
687         /// [out] \param reason  If this is not NULL, then it will be filled with
688         ///      the reason code describing why the header is not valid, if and
689         ///      only if a problem is found with the data.
690         /// \returns  true if there is no problem with the header and false otherwise.
691         
692         // The block must have the correct type.
693         if (block.fHeader.fType != kMansoTracksDataBlock)
694         {
695                 if (reason != NULL) *reason = kHeaderContainsWrongType;
696                 return false;
697         }
698         
699         // The block's record width must be the correct size.
700         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
701         {
702                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
703                 return false;
704         }
705         
706         return true;
707 }
708
709
710 bool AliHLTMUONUtils::HeaderOk(
711                 const AliHLTMUONMansoCandidatesBlockStruct& block,
712                 WhyNotValid* reason
713         )
714 {
715         /// Method used to check if the header information corresponds to the
716         /// supposed type of the raw dHLT data block.
717         /// [in]  \param block  The data block to check.
718         /// [out] \param reason  If this is not NULL, then it will be filled with
719         ///      the reason code describing why the header is not valid, if and
720         ///      only if a problem is found with the data.
721         /// \returns  true if there is no problem with the header and false otherwise.
722         
723         // The block must have the correct type.
724         if (block.fHeader.fType != kMansoCandidatesDataBlock)
725         {
726                 if (reason != NULL) *reason = kHeaderContainsWrongType;
727                 return false;
728         }
729         
730         // The block's record width must be the correct size.
731         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
732         {
733                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
734                 return false;
735         }
736         
737         return true;
738 }
739
740
741 bool AliHLTMUONUtils::HeaderOk(
742                 const AliHLTMUONSinglesDecisionBlockStruct& block,
743                 WhyNotValid* reason
744         )
745 {
746         /// Method used to check if the header information corresponds to the
747         /// supposed type of the raw dHLT data block.
748         /// [in]  \param block  The data block to check.
749         /// [out] \param reason  If this is not NULL, then it will be filled with
750         ///      the reason code describing why the header is not valid, if and
751         ///      only if a problem is found with the data.
752         /// \returns  true if there is no problem with the header and false otherwise.
753         
754         // The block must have the correct type.
755         if (block.fHeader.fType != kSinglesDecisionDataBlock)
756         {
757                 if (reason != NULL) *reason = kHeaderContainsWrongType;
758                 return false;
759         }
760         
761         // The block's record width must be the correct size.
762         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
763         {
764                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
765                 return false;
766         }
767         
768         return true;
769 }
770
771
772 bool AliHLTMUONUtils::HeaderOk(
773                 const AliHLTMUONPairsDecisionBlockStruct& block,
774                 WhyNotValid* reason
775         )
776 {
777         /// Method used to check if the header information corresponds to the
778         /// supposed type of the raw dHLT data block.
779         /// [in]  \param block  The data block to check.
780         /// [out] \param reason  If this is not NULL, then it will be filled with
781         ///      the reason code describing why the header is not valid, if and
782         ///      only if a problem is found with the data.
783         /// \returns  true if there is no problem with the header and false otherwise.
784         
785         // The block must have the correct type.
786         if (block.fHeader.fType != kPairsDecisionDataBlock)
787         {
788                 if (reason != NULL) *reason = kHeaderContainsWrongType;
789                 return false;
790         }
791         
792         // The block's record width must be the correct size.
793         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
794         {
795                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
796                 return false;
797         }
798         
799         return true;
800 }
801
802
803 bool AliHLTMUONUtils::IntegrityOk(
804                 const AliHLTMUONTriggerRecordStruct& tr,
805                 WhyNotValid* reason
806         )
807 {
808         /// This method is used to check more extensively if the integrity of the
809         /// trigger record structure is OK and returns true in that case.
810         /// [in] \param tr  The trigger record structure to check.
811         /// [out] \param reason  If this is not NULL, then it will be filled with
812         ///      the reason code describing why the structure is not valid, if and
813         ///      only if a problem is found with the data.
814         /// \returns  true if there is no problem with the structure and false otherwise.
815         
816         // Make sure that the reserved bits in the fFlags field are set
817         // to zero.
818         if ((tr.fFlags & 0x3FFFFFF0) != 0)
819         {
820                 if (reason != NULL) *reason = kReservedBitsNotZero;
821                 return false;
822         }
823
824         // Make sure the sign is not invalid.
825         if ((tr.fFlags & 0xC0000000) == 0xC0000000)
826         {
827                 if (reason != NULL) *reason = kParticleSignBitsNotValid;
828                 return false;
829         }
830
831         // Check that fHit[i] is nil if the corresponding bit in the
832         // flags word is zero.
833         const AliHLTMUONRecHitStruct& nilhit
834                 = AliHLTMUONConstants::NilRecHitStruct();
835         if ( ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) or
836              ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) or
837              ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) or
838              ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
839            )
840         {
841                 if (reason != NULL) *reason = kHitNotMarkedAsNil;
842                 return false;
843         }
844
845         return true;
846 }
847
848
849 bool AliHLTMUONUtils::IntegrityOk(
850                 const AliHLTMUONTriggerRecordsBlockStruct& block,
851                 WhyNotValid* reason,
852                 AliHLTUInt32_t* recordNum
853         )
854 {
855         /// This method is used to check more extensively if the integrity of the
856         /// dHLT raw internal data block is OK and returns true in that case.
857         /// [in] \param block  The trigger record data block to check.
858         /// [out] \param reason  If this is not NULL, then it will be filled with
859         ///      the reason code describing why the data block is not valid, if and
860         ///      only if a problem is found with the data.
861         /// [out] \param recordNum  If this is not NULL, then it will be filled with
862         ///      the number of the trigger record that had a problem. This value will
863         ///      only contain a valid value if 'reason' contains one of:
864         ///        - kReservedBitsNotZero
865         ///        - kParticleSignBitsNotValid
866         ///        - kHitNotMarkedAsNil
867         /// \returns  true if there is no problem with the data and false otherwise.
868         
869         if (not HeaderOk(block, reason)) return false;
870         
871         const AliHLTMUONTriggerRecordStruct* triggerRecord =
872                 reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
873
874         // Check if any ID is duplicated.
875         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
876         {
877                 AliHLTInt32_t id = triggerRecord[i].fId;
878                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
879                 {
880                         if (id == triggerRecord[j].fId)
881                         {
882                                 if (reason != NULL) *reason = kFoundDuplicateIDs;
883                                 return false;
884                         }
885                 }
886         }
887
888         // Check integrity of individual trigger records.
889         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
890         {
891                 if (not IntegrityOk(triggerRecord[i], reason))
892                 {
893                         if (recordNum != NULL) *recordNum = i;
894                         return false;
895                 }
896         }
897
898         return true;
899 }
900
901
902 bool AliHLTMUONUtils::IntegrityOk(
903                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
904                 WhyNotValid* reason
905         )
906 {
907         /// This method is used to check more extensively if the integrity of the
908         /// dHLT raw internal data block is OK and returns true in that case.
909         /// [in] \param block  The trigger record debugging information data block to check.
910         /// [out] \param reason  If this is not NULL, then it will be filled with
911         ///      the reason code describing why the data block is not valid, if and
912         ///      only if a problem is found with the data.
913         /// \returns  true if there is no problem with the data and false otherwise.
914         
915         if (not HeaderOk(block, reason)) return false;
916         return true;
917 }
918
919
920 bool AliHLTMUONUtils::IntegrityOk(
921                 const AliHLTMUONTriggerChannelsBlockStruct& block,
922                 WhyNotValid* reason
923         )
924 {
925         /// This method is used to check more extensively if the integrity of the
926         /// dHLT raw internal data block is OK and returns true in that case.
927         /// [in] \param block  The trigger channels data block to check.
928         /// [out] \param reason  If this is not NULL, then it will be filled with
929         ///      the reason code describing why the data block is not valid, if and
930         ///      only if a problem is found with the data.
931         /// \returns  true if there is no problem with the data and false otherwise.
932         
933         if (not HeaderOk(block, reason)) return false;
934         return true;
935 }
936
937
938 bool AliHLTMUONUtils::IntegrityOk(
939                 const AliHLTMUONRecHitsBlockStruct& block,
940                 WhyNotValid* reason
941         )
942 {
943         /// This method is used to check more extensively if the integrity of the
944         /// dHLT raw internal data block is OK and returns true in that case.
945         /// [in] \param block  The reconstructed hits data block to check.
946         /// [out] \param reason  If this is not NULL, then it will be filled with
947         ///      the reason code describing why the data block is not valid, if and
948         ///      only if a problem is found with the data.
949         /// \returns  true if there is no problem with the data and false otherwise.
950         
951         if (not HeaderOk(block, reason)) return false;
952         return true;
953 }
954
955
956 bool AliHLTMUONUtils::IntegrityOk(
957                 const AliHLTMUONClustersBlockStruct& block,
958                 WhyNotValid* reason
959         )
960 {
961         /// This method is used to check more extensively if the integrity of the
962         /// dHLT raw internal data block is OK and returns true in that case.
963         /// [in] \param block  The clusters data block to check.
964         /// [out] \param reason  If this is not NULL, then it will be filled with
965         ///      the reason code describing why the data block is not valid, if and
966         ///      only if a problem is found with the data.
967         /// \returns  true if there is no problem with the data and false otherwise.
968         
969         if (not HeaderOk(block, reason)) return false;
970
971         const AliHLTMUONClusterStruct* cluster =
972                 reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
973         
974         // Check if any ID is duplicated.
975         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
976         {
977                 AliHLTInt32_t id = cluster[i].fId;
978                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
979                 {
980                         if (id == cluster[j].fId)
981                         {
982                                 if (reason != NULL) *reason = kFoundDuplicateIDs;
983                                 return false;
984                         }
985                 }
986         }
987         
988         return true;
989 }
990
991
992 bool AliHLTMUONUtils::IntegrityOk(
993                 const AliHLTMUONChannelsBlockStruct& block,
994                 WhyNotValid* reason
995         )
996 {
997         /// This method is used to check more extensively if the integrity of the
998         /// dHLT raw internal data block is OK and returns true in that case.
999         /// [in] \param block  The ADC channels data block to check.
1000         /// [out] \param reason  If this is not NULL, then it will be filled with
1001         ///      the reason code describing why the data block is not valid, if and
1002         ///      only if a problem is found with the data.
1003         /// \returns  true if there is no problem with the data and false otherwise.
1004         
1005         if (not HeaderOk(block, reason)) return false;
1006         return true;
1007 }
1008
1009
1010 bool AliHLTMUONUtils::IntegrityOk(
1011                 const AliHLTMUONMansoTrackStruct& track,
1012                 WhyNotValid* reason
1013         )
1014 {
1015         /// This method is used to check more extensively if the integrity of the
1016         /// Manso track structure is OK and returns true in that case.
1017         /// [in] \param track  The track structure to check.
1018         /// [out] \param reason  If this is not NULL, then it will be filled with
1019         ///      the reason code describing why the structure is not valid, if and
1020         ///      only if a problem is found with the data.
1021         /// \returns  true if there is no problem with the structure and false otherwise.
1022         
1023         // Make sure that the reserved bits in the fFlags field are set
1024         // to zero.
1025         if ((track.fFlags & 0x3FFFFFF0) != 0)
1026         {
1027                 if (reason != NULL) *reason = kReservedBitsNotZero;
1028                 return false;
1029         }
1030
1031         // Make sure the sign is not invalid.
1032         if ((track.fFlags & 0xC0000000) == 0xC0000000)
1033         {
1034                 if (reason != NULL) *reason = kParticleSignBitsNotValid;
1035                 return false;
1036         }
1037
1038         // Check that fHit[i] is nil if the corresponding bit in the
1039         // flags word is zero.
1040         const AliHLTMUONRecHitStruct& nilhit
1041                 = AliHLTMUONConstants::NilRecHitStruct();
1042         if ( ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) or
1043              ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) or
1044              ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) or
1045              ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
1046            )
1047         {
1048                 if (reason != NULL) *reason = kHitNotMarkedAsNil;
1049                 return false;
1050         }
1051         
1052         return true;
1053 }
1054
1055
1056 bool AliHLTMUONUtils::IntegrityOk(
1057                 const AliHLTMUONMansoTracksBlockStruct& block,
1058                 WhyNotValid* reason,
1059                 AliHLTUInt32_t* recordNum
1060         )
1061 {
1062         /// This method is used to check more extensively if the integrity of the
1063         /// dHLT raw internal data block is OK and returns true in that case.
1064         /// [in] \param block  The Manso track data block to check.
1065         /// [out] \param reason  If this is not NULL, then it will be filled with
1066         ///      the reason code describing why the data block is not valid, if and
1067         ///      only if a problem is found with the data.
1068         /// [out] \param recordNum  If this is not NULL, then it will be filled with
1069         ///      the number of the track that had a problem. This value will only
1070         ///      contain a valid value if 'reason' contains one of:
1071         ///        - kReservedBitsNotZero
1072         ///        - kParticleSignBitsNotValid
1073         ///        - kHitNotMarkedAsNil
1074         /// \returns  true if there is no problem with the data and false otherwise.
1075         
1076         if (not HeaderOk(block, reason)) return false;
1077
1078         const AliHLTMUONMansoTrackStruct* track =
1079                 reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
1080         
1081         // Check if any track ID is duplicated.
1082         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1083         {
1084                 AliHLTInt32_t id = track[i].fId;
1085                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
1086                 {
1087                         if (id == track[j].fId)
1088                         {
1089                                 if (reason != NULL) *reason = kFoundDuplicateIDs;
1090                                 return false;
1091                         }
1092                 }
1093         }
1094
1095         // Check that the tracks have integrity.
1096         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1097         {
1098                 if (not IntegrityOk(track[i], reason))
1099                 {
1100                         if (recordNum != NULL) *recordNum = i;
1101                         return false;
1102                 }
1103         }
1104
1105         return true;
1106 }
1107
1108
1109 bool AliHLTMUONUtils::IntegrityOk(
1110                 const AliHLTMUONMansoCandidatesBlockStruct& block,
1111                 WhyNotValid* reason,
1112                 AliHLTUInt32_t* recordNum
1113         )
1114 {
1115         /// This method is used to check more extensively if the integrity of the
1116         /// dHLT raw internal data block is OK and returns true in that case.
1117         /// [in] \param block  The Manso track candidate data block to check.
1118         /// [out] \param reason  If this is not NULL, then it will be filled with
1119         ///      the reason code describing why the data block is not valid, if and
1120         ///      only if a problem is found with the data.
1121         /// [out] \param recordNum  If this is not NULL, then it will be filled with
1122         ///      the number of the track candidate that had a problem. This value will
1123         ///      only contain a valid value if 'reason' contains one of:
1124         ///        - kReservedBitsNotZero
1125         ///        - kParticleSignBitsNotValid
1126         ///        - kHitNotMarkedAsNil
1127         /// \returns  true if there is no problem with the data and false otherwise.
1128         
1129         if (not HeaderOk(block, reason)) return false;
1130
1131         const AliHLTMUONMansoCandidateStruct* candidate =
1132                 reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
1133         
1134         // Check if any candidate track ID is duplicated.
1135         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1136         {
1137                 AliHLTInt32_t id = candidate[i].fTrack.fId;
1138                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
1139                 {
1140                         if (id == candidate[j].fTrack.fId)
1141                         {
1142                                 if (reason != NULL) *reason = kFoundDuplicateIDs;
1143                                 return false;
1144                         }
1145                 }
1146         }
1147         
1148         // Check that the tracks have integrity.
1149         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1150         {
1151                 if (not IntegrityOk(candidate[i].fTrack, reason))
1152                 {
1153                         if (recordNum != NULL) *recordNum = i;
1154                         return false;
1155                 }
1156         }
1157         
1158         return true;
1159 }
1160
1161
1162 bool AliHLTMUONUtils::IntegrityOk(
1163                 const AliHLTMUONTrackDecisionStruct& decision,
1164                 WhyNotValid* reason
1165         )
1166 {
1167         /// This method is used to check more extensively if the integrity of the
1168         /// single track trigger decision structure is OK and returns true in that case.
1169         /// [in] \param decision  The trigger decision structure to check.
1170         /// [out] \param reason  If this is not NULL, then it will be filled with
1171         ///      the reason code describing why the structure is not valid, if and
1172         ///      only if a problem is found with the data.
1173         /// \returns  true if there is no problem with the structure and false otherwise.
1174         
1175         // Make sure that the reserved bits in the fTriggerBits field are set
1176         // to zero.
1177         if ((decision.fTriggerBits & 0xFFFFFFFC) != 0)
1178         {
1179                 if (reason != NULL) *reason = kReservedBitsNotZero;
1180                 return false;
1181         }
1182         
1183         // The pT should be -1 or a positive number.
1184         if (decision.fPt != -1. and decision.fPt < 0.)
1185         {
1186                 if (reason != NULL) *reason = kPtValueNotValid;
1187                 return false;
1188         }
1189         
1190         return true;
1191 }
1192
1193
1194 bool AliHLTMUONUtils::IntegrityOk(
1195                 const AliHLTMUONSinglesDecisionBlockStruct& block,
1196                 WhyNotValid* reason,
1197                 AliHLTUInt32_t* recordNum
1198         )
1199 {
1200         /// This method is used to check more extensively if the integrity of the
1201         /// dHLT raw internal data block is OK and returns true in that case.
1202         /// [in] \param block  The single track trigger decision data block to check.
1203         /// [out] \param reason  If this is not NULL, then it will be filled with
1204         ///      the reason code describing why the data block is not valid, if and
1205         ///      only if a problem is found with the data.
1206         /// [out] \param recordNum  If this is not NULL, then it will be filled with
1207         ///      the number of the trigger decisions that had a problem. This value will
1208         ///      only contain a valid value if 'reason' contains one of:
1209         ///        - kReservedBitsNotZero
1210         ///        - kPtValueNotValid
1211         /// \returns  true if there is no problem with the data and false otherwise.
1212         
1213         if (not HeaderOk(block, reason)) return false;
1214         
1215         const AliHLTMUONTrackDecisionStruct* decision =
1216                 reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
1217
1218         // Check that there are no duplicate trigger entries.
1219         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1220         {
1221                 AliHLTInt32_t id = decision[i].fTrackId;
1222                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
1223                 {
1224                         if (id == decision[j].fTrackId)
1225                         {
1226                                 if (reason != NULL) *reason = kFoundDuplicateTriggers;
1227                                 return false;
1228                         }
1229                 }
1230         }
1231         
1232         // Check that the trigger bits for each track have integrity.
1233         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1234         {
1235                 if (not IntegrityOk(decision[i], reason))
1236                 {
1237                         if (recordNum != NULL) *recordNum = i;
1238                         return false;
1239                 }
1240         }
1241         
1242         return true;
1243 }
1244
1245
1246 bool AliHLTMUONUtils::IntegrityOk(
1247                 const AliHLTMUONPairDecisionStruct& decision,
1248                 WhyNotValid* reason
1249         )
1250 {
1251         /// This method is used to check more extensively if the integrity of the
1252         /// track pair trigger decision structure is OK and returns true in that case.
1253         /// [in] \param decision  The trigger decision structure to check.
1254         /// [out] \param reason  If this is not NULL, then it will be filled with
1255         ///      the reason code describing why the structure is not valid, if and
1256         ///      only if a problem is found with the data.
1257         /// \returns  true if there is no problem with the structure and false otherwise.
1258         
1259         // Make sure that the reserved bits in the fTriggerBits field are set
1260         // to zero.
1261         if ((decision.fTriggerBits & 0xFFFFFF80) != 0)
1262         {
1263                 if (reason != NULL) *reason = kReservedBitsNotZero;
1264                 return false;
1265         }
1266         
1267         // Check that the track IDs are not the same.
1268         if (decision.fTrackAId == decision.fTrackBId)
1269         {
1270                 if (reason != NULL) *reason = kPairTrackIdsAreIdentical;
1271                 return false;
1272         }
1273         
1274         // The invariant mass should be -1 or a positive number.
1275         if (decision.fInvMass != -1. and decision.fInvMass < 0.)
1276         {
1277                 if (reason != NULL) *reason = kMassValueNotValid;
1278                 return false;
1279         }
1280         
1281         // Neither the high pt (hipt) or low pt (lopt) count bits can be > 2.
1282         AliHLTUInt8_t lowPtCount = (decision.fTriggerBits & 0x00000003);
1283         AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
1284         if (lowPtCount > 2)
1285         {
1286                 if (reason != NULL) *reason = kLowPtCountInvalid;
1287                 return false;
1288         }
1289         if (highPtCount > 2)
1290         {
1291                 if (reason != NULL) *reason = kHighPtCountInvalid;
1292                 return false;
1293         }
1294         
1295         return true;
1296 }
1297
1298
1299 bool AliHLTMUONUtils::IntegrityOk(
1300                 const AliHLTMUONPairsDecisionBlockStruct& block,
1301                 WhyNotValid* reason,
1302                 AliHLTUInt32_t* recordNum
1303         )
1304 {
1305         /// This method is used to check more extensively if the integrity of the
1306         /// dHLT raw internal data block is OK and returns true in that case.
1307         /// [in] \param block  The track pair trigger decision data block to check.
1308         /// [out] \param reason  If this is not NULL, then it will be filled with
1309         ///      the reason code describing why the data block is not valid, if and
1310         ///      only if a problem is found with the data.
1311         /// [out] \param recordNum  If this is not NULL, then it will be filled with
1312         ///      the number of the trigger decisions that had a problem. This value will
1313         ///      only contain a valid value if 'reason' contains one of:
1314         ///        - kReservedBitsNotZero
1315         ///        - kPairTrackIdsAreIdentical
1316         ///        - kMassValueNotValid
1317         ///        - kLowPtCountInvalid
1318         ///        - kHighPtCountInvalid
1319         /// \returns  true if there is no problem with the data and false otherwise.
1320         
1321         if (not HeaderOk(block, reason)) return false;
1322
1323         const AliHLTMUONPairDecisionStruct* decision =
1324                 reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
1325         
1326         // Check that there are no duplicate trigger entries.
1327         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1328         {
1329                 AliHLTInt32_t ta = decision[i].fTrackAId;
1330                 AliHLTInt32_t tb = decision[i].fTrackBId;
1331                 for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
1332                 {
1333                         if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
1334                         {
1335                                 if (reason != NULL) *reason = kFoundDuplicateTriggers;
1336                                 return false;
1337                         }
1338                 }
1339         }
1340         
1341         // Check that the trigger bits for each track pair have integrity.
1342         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1343         {
1344                 if (not IntegrityOk(decision[i], reason))
1345                 {
1346                         if (recordNum != NULL) *recordNum = i;
1347                         return false;
1348                 }
1349         }
1350         
1351         return true;
1352 }