]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/MUON/AliHLTMUONUtils.cxx
ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / MUON / AliHLTMUONUtils.cxx
index c0dc4afbc23a4429425b90b10dae435e42f9f67f..12c13ff83263b5125a78e6b2c556762c3f852c26 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
-/* $Id$ */
+// $Id$
 
-/**
- * @file   AliHLTMUONUtils.cxx
- * @author Artur Szostak <artursz@iafrica.com>
- * @date   
- * @brief  Implementation of AliHLTMUONUtils utility routines.
- */
+///
+/// @file   AliHLTMUONUtils.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   17 May 2007
+/// @brief  Implementation of AliHLTMUONUtils utility routines.
+///
 
 #include "AliHLTMUONUtils.h"
 #include "AliHLTMUONConstants.h"
 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
 #include "AliHLTMUONTrigRecsDebugBlockStruct.h"
-#include "AliHLTMUONTriggerChannelsBlockStruct.h"
 #include "AliHLTMUONRecHitsBlockStruct.h"
 #include "AliHLTMUONClustersBlockStruct.h"
 #include "AliHLTMUONChannelsBlockStruct.h"
 #include "AliHLTMUONMansoTracksBlockStruct.h"
 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
+#include "AliHLTMUONTracksBlockStruct.h"
 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
 #include "AliHLTMUONPairsDecisionBlockStruct.h"
+#include "AliMUONTrackerDDLDecoderEventHandler.h"
+#include <cstring>
+#include <cmath>
 #include <cassert>
 
+ClassImp(AliHLTMUONUtils);
+
 
 AliHLTUInt32_t AliHLTMUONUtils::PackTriggerRecordFlags(
                AliHLTMUONParticleSign sign, const bool hitset[4]
        )
 {
+       ///
+       /// This packs the given parameters into the bits of a word appropriate
+       /// for AliHLTMUONTriggerRecordStruct::fFlags.
+       /// @param sign    The particle sign.
+       /// @param hitset  Flags to indicate if the corresponding fHits[i] elements
+       ///                was set/filled.
+       /// @return  Returns the 32 bit packed word.
+       ///
+       
        AliHLTUInt32_t flags;
        switch (sign)
        {
@@ -58,6 +72,15 @@ void AliHLTMUONUtils::UnpackTriggerRecordFlags(
                AliHLTUInt32_t flags, AliHLTMUONParticleSign& sign, bool hitset[4]
        )
 {
+       ///
+       /// This unpacks the AliHLTMUONTriggerRecordStruct::fFlags bits into
+       /// its component fields.
+       /// @param flags  The flags from an AliHLTMUONTriggerRecordStruct structure.
+       /// @param sign    Sets this to the particle sign.
+       /// @param hitset  Sets the array elements to indicate if the corresponding
+       ///                fHits[i] element was set/filled.
+       ///
+       
        AliHLTUInt32_t signbits = flags & 0xC0000000;
        switch (signbits)
        {
@@ -72,8 +95,100 @@ void AliHLTMUONUtils::UnpackTriggerRecordFlags(
 }
 
 
+AliHLTUInt32_t AliHLTMUONUtils::PackRecHitFlags(
+               AliHLTUInt8_t chamber, AliHLTUInt16_t detElemId
+       )
+{
+       /// This packs the given parameters into the bits of a word appropriate
+       /// for AliHLTMUONRecHitStruct::fFlags.
+       /// @param chamber    The chamber number in the range [0..13].
+       /// @param detElemId  Detector element ID number.
+       /// @return  Returns the 32 bit packed word.
+       
+       return ((chamber & 0xF) << 12) | (detElemId & 0xFFF);
+}
+
+
+void AliHLTMUONUtils::UnpackRecHitFlags(
+               AliHLTUInt32_t flags, // [in]
+               AliHLTUInt8_t& chamber, // [out]
+               AliHLTUInt16_t& detElemId // [out]
+       )
+{
+       /// This unpacks the AliHLTMUONRecHitStruct::fFlags bits into
+       /// its component fields.
+       /// @param [in]  flags  The flags from an AliHLTMUONRecHitStruct structure.
+       /// @param [out] chamber    Sets the chamber number in the range [0..13].
+       /// @param [out] detElemId  Sets the detector element ID number.
+       
+       chamber = (flags >> 12) & 0xF;
+       detElemId = flags & 0xFFF;
+}
+
+
+AliHLTUInt32_t AliHLTMUONUtils::PackTrackFlags(
+               AliHLTMUONParticleSign sign, const bool hitset[16]
+       )
+{
+       /// This packs the given parameters into the bits of a word appropriate
+       /// for AliHLTMUONTrackStruct::fFlags.
+       /// @param sign    The particle sign.
+       /// @param hitset  Flags to indicate if the corresponding fHits[i] elements
+       ///                was set/filled.
+       /// @return  Returns the 32 bit packed word.
+       
+       AliHLTUInt32_t flags;
+       switch (sign)
+       {
+       case kSignMinus: flags = 0x80000000; break;
+       case kSignPlus:  flags = 0x40000000; break;
+       default:         flags = 0x00000000; break;
+       }
+       
+       for (AliHLTUInt32_t i = 0; i < 16; i++)
+       {
+               flags |= (hitset[i] ? (0x1 << i) : 0);
+       }
+       return flags;
+}
+
+
+void AliHLTMUONUtils::UnpackTrackFlags(
+               AliHLTUInt32_t flags, AliHLTMUONParticleSign& sign, bool hitset[16]
+       )
+{
+       /// This unpacks the AliHLTMUONTrackStruct::fFlags bits into
+       /// its component fields.
+       /// @param flags  The flags from an AliHLTMUONTrackStruct structure.
+       /// @param sign    Sets this to the particle sign.
+       /// @param hitset  Sets the array elements to indicate if the corresponding
+       ///                fHits[i] element was set/filled.
+       
+       AliHLTUInt32_t signbits = flags & 0xC0000000;
+       switch (signbits)
+       {
+       case 0x80000000: sign = kSignMinus;   break;
+       case 0x40000000: sign = kSignPlus;    break;
+       default:         sign = kSignUnknown; break;
+       }
+       
+       for (AliHLTUInt32_t i = 0; i < 16; i++)
+       {
+               hitset[i] = ((flags & (0x1u << i)) == (0x1u << i));
+       }
+}
+
+
 AliHLTUInt32_t AliHLTMUONUtils::PackTrackDecisionBits(bool highPt, bool lowPt)
 {
+       ///
+       /// This packs the given parameters into the bits of a word appropriate
+       /// for AliHLTMUONTrackDecisionStruct::fTriggerBits.
+       /// @param highPt  Has the track passed the high pt cut.
+       /// @param lowPt   Has the track passed the low pt cut.
+       /// @return  Returns the 32 bit packed word.
+       ///
+       
        return (highPt ? 0x2 : 0) | (lowPt ? 0x1 : 0);
 }
 
@@ -82,8 +197,17 @@ void AliHLTMUONUtils::UnpackTrackDecisionBits(
                AliHLTUInt32_t bits, bool& highPt, bool& lowPt
        )
 {
-       lowPt  = (bits & 0x1) == 1;
-       highPt = (bits & 0x2) == 1;
+       ///
+       /// This unpacks the AliHLTMUONTrackDecisionStruct::fTriggerBits bits into
+       /// its component fields.
+       /// @param bits  The trigger bits from an AliHLTMUONTrackDecisionStruct
+       ///              structure.
+       /// @param highPt Sets this to the value of the high pt cut bit.
+       /// @param lowPt  Sets this to the value of the low pt cut bit.
+       ///
+       
+       lowPt  = (bits & 0x1) == 0x1;
+       highPt = (bits & 0x2) == 0x2;
 }
 
 
@@ -92,7 +216,25 @@ AliHLTUInt32_t AliHLTMUONUtils::PackPairDecisionBits(
                AliHLTUInt8_t highPtCount, AliHLTUInt8_t lowPtCount
        )
 {
-       assert( highPtCount + lowPtCount <= 2 );
+       ///
+       /// This packs the given parameters into the bits of a word appropriate
+       /// for AliHLTMUONPairDecisionStruct::fTriggerBits.
+       ///
+       /// @param highMass Has the track pair passed the high invariant mass cut.
+       /// @param lowMass  Has the track pair passed the low invariant mass cut.
+       /// @param unlike   Does the track pair have unlike signs.
+       /// @param highPtCount The number of tracks that passed the high pt cut
+       ///                    in the pair.
+       /// @param lowPtCount  The number of tracks that passed the low pt cut
+       ///                    in the pair.
+       /// @return  Returns the 32 bit packed word.
+       ///
+       /// Note: Must have highPtCount <= 2, lowPtCount <= 2 and
+       /// unlike == true if highMass or lowMass is true.
+       ///
+       
+       assert( lowPtCount <= 2 );
+       assert( highPtCount <= 2 );
        // highMass and lowMass must be false if unlike is false:
        assert( not unlike ? (highMass == false and lowMass == false) : true );
        
@@ -106,9 +248,21 @@ void AliHLTMUONUtils::UnpackPairDecisionBits(
                AliHLTUInt8_t& highPtCount, AliHLTUInt8_t& lowPtCount
        )
 {
-       highMass = (bits & 0x40) == 1;
-       lowMass  = (bits & 0x20) == 1;
-       unlike   = (bits & 0x10) == 1;
+       ///
+       /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
+       /// its component fields.
+       /// @param bits  The trigger bits from an AliHLTMUONPairDecisionStruct
+       ///              structure.
+       /// @param highMass Sets this to the value of the high invariant mass cut bit.
+       /// @param lowMass  Sets this to the value of the low invariant mass cut bit.
+       /// @param unlike   Sets this if the pair is unlike sign.
+       /// @param highPtCount Sets this to the high pt count bits.
+       /// @param lowPtCount  Sets this to the low pt count bits.
+       ///
+       
+       highMass = (bits & 0x40) == 0x40;
+       lowMass  = (bits & 0x20) == 0x20;
+       unlike   = (bits & 0x10) == 0x10;
        highPtCount = (bits & 0xC) >> 2;
        lowPtCount = bits & 0x3;
 }
@@ -118,6 +272,17 @@ AliHLTUInt32_t AliHLTMUONUtils::PackSpecBits(
                const bool ddl[22]
        )
 {
+       ///
+       /// This packs the given parameters into the 32bit Pub/Sub specification
+       /// word in the data block descriptor.
+       ///
+       /// @param ddl  The list of DDLs forming part of the readout. ddl[0]
+       ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
+       ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
+       ///             trigger DDLs 2816 and 2817 respectively.
+       /// @return  Returns the 32 bit packed specification word.
+       ///
+       
        // Pack the bits into the following format:
        //   bit:   [        31 - 22        ][     21     ][     20     ][  19 - 0 ]
        //   field: [ reserved, set to zero ][ TRGDDL2817 ][ TRGDDL2816 ][ TRKDDLS ]
@@ -137,343 +302,2648 @@ void AliHLTMUONUtils::UnpackSpecBits(
                AliHLTUInt32_t bits, bool ddl[22]
        )
 {
+       ///
+       /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
+       /// its component fields.
+       /// @param bits  The Pub/Sub specification word from a data block descriptor.
+       /// @param ddl  The output list of DDLs forming part of the readout. ddl[0]
+       ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
+       ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
+       ///             trigger DDLs 2816 and 2817 respectively.
+       ///
+       
        // Perform the inverse operation of PackSpecBits.
        for (int i = 0; i < 22; i++)
                ddl[i] = ((bits >> i) & 0x1) == 1;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(
-               const AliHLTMUONTriggerRecordsBlockStruct& block,
-               WhyNotValid* reason
-       )
+AliHLTInt32_t AliHLTMUONUtils::DDLNumberToEquipId(AliHLTInt32_t ddlNo)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kTriggerRecordsDataBlock)
+       ///
+       /// This method converts the DDL number for the muon spectrometer in the
+       /// range [0..21] to the equipment ID number.
+       /// @param ddlNo  The DDL number in the range [0..21].
+       /// @return  Returns the equipment ID number or -1 if ddlNo was invalid.
+       ///
+       
+       if (0 <= ddlNo and ddlNo <= 19)
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongType;
-               return false;
+               return 2560 + ddlNo;
        }
-       
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerRecordStruct))
+       else if (20 <= ddlNo and ddlNo <= 21)
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               return 2816 + (ddlNo - 20);
+       }
+       else
+       {
+               return -1;
        }
-       
-       return true;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block)
+AliHLTInt32_t AliHLTMUONUtils::EquipIdToDDLNumber(AliHLTInt32_t id)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kTrigRecsDebugDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
-               return false;
-       return true;
+       ///
+       /// This method converts the equipment ID number for a muon spectrometer
+       /// DDL to the DDL number in the range [0..21].
+       /// @param id  The equipment ID of the DDL.
+       /// @return  Returns the DDL number in the range [0..21] or -1 if the
+       ///          equipment ID was invalid.
+       ///
+       
+       if (2560 <= id and id <= 2560+19)
+       {
+               return id - 2560;
+       }
+       else if (2816 <= id and id <= 2817)
+       {
+               return id - 2816 + 20;
+       }
+       else
+       {
+               return -1;
+       }
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block)
+AliHLTInt32_t AliHLTMUONUtils::SpecToEquipId(AliHLTUInt32_t spec)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kTriggerChannelsDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerChannelStruct))
-               return false;
-       return true;
+       ///
+       /// This method converts a 32 bit data block specification for a MUON-HLT
+       /// data block into its corresponding DDL equipment ID number.
+       /// It is assumed that the specification is for a data block comming from
+       /// a single DDL source. If more than one DDL contributed to the data block
+       /// then -1 is returned.
+       /// @param spec  The 32 bit specification for a data block.
+       /// @return  Returns the equipment ID corresponding to the specification
+       ///          or -1 if the specification was invalid.
+       ///
+       
+       for (AliHLTInt32_t ddlNo = 0; ddlNo < 20; ddlNo++)
+       {
+               if (spec == AliHLTUInt32_t(0x1 << ddlNo))
+                       return ddlNo + 2560;
+       }
+       for (AliHLTInt32_t ddlNo = 20; ddlNo < 22; ddlNo++)
+       {
+               if (spec == AliHLTUInt32_t(0x1 << ddlNo))
+                       return ddlNo - 20 + 2816;
+       }
+       return -1;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONRecHitsBlockStruct& block)
+AliHLTUInt32_t AliHLTMUONUtils::EquipIdToSpec(AliHLTInt32_t id)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kRecHitsDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
-               return false;
-       return true;
+       ///
+       /// This method converts a equipment ID number for a DDL into its corresponding
+       /// 32 bit data block specification for the MUON-HLT.
+       /// @param id  The equipment ID number of the DDL.
+       /// @return  Returns the 32 bit data block specification or 0x0 if the
+       ///          equipment ID was invalid.
+       ///
+       
+       if (2560 <= id and id <= 2560+19)
+       {
+               return 0x1 << (id - 2560);
+       }
+       else if (2816 <= id and id <= 2817)
+       {
+               return 0x1 << (id - 2816 + 20);
+       }
+       else
+       {
+               return 0x0;
+       }
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONClustersBlockStruct& block)
+AliHLTInt32_t AliHLTMUONUtils::SpecToDDLNumber(AliHLTUInt32_t spec)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kClustersDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
-               return false;
-       return true;
+       ///
+       /// This method converts a 32 bit data block specification for a MUON-HLT
+       /// data block into its corresponding DDL number in the range [0..21].
+       /// It is assumed that the specification is for a data block comming from
+       /// a single DDL source. If more than one DDL contributed to the data block
+       /// then -1 is returned.
+       /// @param spec  The 32 bit specification for a data block.
+       /// @return  Returns the corresponding DDL number for the specification
+       ///          or -1 if the specification was invalid.
+       ///
+       
+       for (AliHLTInt32_t ddlNo = 0; ddlNo < 22; ddlNo++)
+       {
+               if (spec == AliHLTUInt32_t(0x1 << ddlNo))
+                       return ddlNo;
+       }
+       return -1;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONChannelsBlockStruct& block)
+AliHLTUInt32_t AliHLTMUONUtils::DDLNumberToSpec(AliHLTInt32_t ddlNo)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kChannelsDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
-               return false;
-       return true;
+       ///
+       /// This method converts a DDL number in the range [0..21] into its
+       /// corresponding 32 bit data block specification for the MUON-HLT.
+       /// @param ddlNo  The equipment ID number of the DDL.
+       /// @return  Returns the 32 bit data block specification or 0x0 if the
+       ///          DDL number was invalid (out of range).
+       ///
+       
+       if (0 <= ddlNo and ddlNo <= 21)
+       {
+               return 0x1 << ddlNo;
+       }
+       else
+       {
+               return 0x0;
+       }
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block)
+AliHLTMUONDataBlockType AliHLTMUONUtils::ParseCommandLineTypeString(const char* type)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kMansoTracksDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
-               return false;
-       return true;
+       /// Parses the string containing the type name of a dHLT data block and
+       /// returns the corresponding AliHLTMUONDataBlockType value.
+       /// \param  type  The string containing the type name.
+       /// \returns  The data block type or kUnknownDataBlock if the type name
+       ///      is invalid.
+
+       if (strcmp(type, "trigrecs") == 0)
+       {
+               return kTriggerRecordsDataBlock;
+       }
+       else if (strcmp(type, "trigrecsdebug") == 0)
+       {
+               return kTrigRecsDebugDataBlock;
+       }
+       else if (strcmp(type, "rechits") == 0)
+       {
+               return kRecHitsDataBlock;
+       }
+       else if (strcmp(type,"channels") == 0)
+       {
+               return kChannelsDataBlock;
+       }
+       else if (strcmp(type,"clusters") == 0)
+       {
+               return kClustersDataBlock;
+       }
+       else if (strcmp(type, "mansotracks") == 0)
+       {
+               return kMansoTracksDataBlock;
+       }
+       else if (strcmp(type, "mansocandidates") == 0)
+       {
+               return kMansoCandidatesDataBlock;
+       }
+       else if (strcmp(type, "tracks") == 0)
+       {
+               return kTracksDataBlock;
+       }
+       else if (strcmp(type, "singlesdecision") == 0)
+       {
+               return kSinglesDecisionDataBlock;
+       }
+       else if (strcmp(type, "pairsdecision") == 0)
+       {
+               return kPairsDecisionDataBlock;
+       }
+       
+       return kUnknownDataBlock;
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block)
+const char* AliHLTMUONUtils::DataBlockTypeToString(AliHLTMUONDataBlockType type)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kMansoCandidatesDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
-               return false;
-       return true;
+       /// Converts a type ID to a type string compatible with
+       /// HLT data types.
+       
+       static char str[kAliHLTComponentDataTypefIDsize+1];
+       AliHLTComponentDataType t;
+       switch (type)
+       {
+       case kTriggerRecordsDataBlock:
+               t = AliHLTMUONConstants::TriggerRecordsBlockDataType();
+               break;
+       case kTrigRecsDebugDataBlock:
+               t = AliHLTMUONConstants::TrigRecsDebugBlockDataType();
+               break;
+       case kRecHitsDataBlock:
+               t = AliHLTMUONConstants::RecHitsBlockDataType();
+               break;
+       case kClustersDataBlock:
+               t = AliHLTMUONConstants::ClusterBlockDataType();
+               break;
+       case kChannelsDataBlock:
+               t = AliHLTMUONConstants::ChannelBlockDataType();
+               break;
+       case kMansoTracksDataBlock:
+               t = AliHLTMUONConstants::MansoTracksBlockDataType();
+               break;
+       case kMansoCandidatesDataBlock:
+               t = AliHLTMUONConstants::MansoCandidatesBlockDataType();
+               break;
+       case kTracksDataBlock:
+               t = AliHLTMUONConstants::TracksBlockDataType();
+               break;
+       case kSinglesDecisionDataBlock:
+               t = AliHLTMUONConstants::SinglesDecisionBlockDataType();
+               break;
+       case kPairsDecisionDataBlock:
+               t = AliHLTMUONConstants::PairsDecisionBlockDataType();
+               break;
+       default:
+               return "UNKNOWN";
+       }
+       memcpy(&str, &t.fID, kAliHLTComponentDataTypefIDsize);
+       // Must insert the NULL character to make this an ANSI C string.
+       str[kAliHLTComponentDataTypefIDsize] = '\0';
+       return &str[0];
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block)
+const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid reason)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kSinglesDecisionDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
-               return false;
-       return true;
+       /// This method converts the WhyNotValid enumeration to a string representation.
+       
+       switch (reason)
+       {
+       case kNoReason: return "kNoReason";
+       case kHeaderContainsWrongType: return "kHeaderContainsWrongType";
+       case kHeaderContainsWrongRecordWidth: return "kHeaderContainsWrongRecordWidth";
+       case kInvalidIdValue: return "kInvalidIdValue";
+       case kInvalidTriggerIdValue: return "kInvalidTriggerIdValue";
+       case kInvalidTrackIdValue: return "kInvalidTrackIdValue";
+       case kReservedBitsNotZero: return "kReservedBitsNotZero";
+       case kParticleSignBitsNotValid: return "kParticleSignBitsNotValid";
+       case kHitNotMarkedAsNil: return "kHitNotMarkedAsNil";
+       case kInvalidDetElementNumber: return "kInvalidDetElementNumber";
+       case kInvalidChamberNumber: return "kInvalidChamberNumber";
+       case kHitIsNil: return "kHitIsNil";
+       case kInvalidChannelCountB: return "kInvalidChannelCountB";
+       case kInvalidChannelCountNB: return "kInvalidChannelCountNB";
+       case kInvalidChargeB: return "kInvalidChargeB";
+       case kInvalidChargeNB: return "kInvalidChargeNB";
+       case kInvalidBusPatchId: return "kInvalidBusPatchId";
+       case kInvalidManuId: return "kInvalidManuId";
+       case kInvalidChannelAddress: return "kInvalidChannelAddress";
+       case kInvalidSignal: return "kInvalidSignal";
+       case kDataWordDifferent: return "kDataWordDifferent";
+       case kChiSquareInvalid: return "kChiSquareInvalid";
+       case kMomentumVectorNotZero: return "kMomentumVectorNotZero";
+       case kMomentumParamsNotZero: return "kMomentumParamsNotZero";
+       case kDCAVertexNotZero: return "kDCAVertexNotZero";
+       case kRoiRadiusInvalid: return "kRoiRadiusInvalid";
+       case kHitNotWithinRoi: return "kHitNotWithinRoi";
+       case kPtValueNotValid: return "kPtValueNotValid";
+       case kPairTrackIdsAreIdentical: return "kPairTrackIdsAreIdentical";
+       case kMassValueNotValid: return "kMassValueNotValid";
+       case kLowPtCountInvalid: return "kLowPtCountInvalid";
+       case kHighPtCountInvalid: return "kHighPtCountInvalid";
+       case kFoundDuplicateIDs: return "kFoundDuplicateIDs";
+       case kFoundDuplicateHits: return "kFoundDuplicateHits";
+       case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
+       default: return "INVALID";
+       }
 }
 
 
-bool AliHLTMUONUtils::HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block)
+const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
 {
-       // The block must have the correct type.
-       if (block.fHeader.fType != kPairsDecisionDataBlock) return false;
-       // The block's record width must be the correct size.
-       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
-               return false;
-       return true;
+       /// This method returns a string containing a user readable message explaining
+       /// the reason for failure described by the WhyNotValid enumeration.
+       
+       switch (reason)
+       {
+       case kNoReason:
+               return "There was no problem with the data block.";
+       case kHeaderContainsWrongType:
+               return "The common data header contains an incorrect type"
+                       " identifier.";
+       case kHeaderContainsWrongRecordWidth:
+               return "The common data header contains an incorrect data"
+                       " record width.";
+       case kInvalidIdValue:
+               return "The structure identifier does not have a valid value.";
+       case kInvalidTriggerIdValue:
+               return "The trigger structure identifier does not have a valid"
+                       " value.";
+       case kInvalidTrackIdValue:
+               return "The track structure identifier does not have a valid"
+                       " value.";
+       case kReservedBitsNotZero:
+               return "Reserved bits have not been set to zero.";
+       case kParticleSignBitsNotValid:
+               return "The particle sign bits are not a valid value.";
+       case kHitNotMarkedAsNil:
+               return "A hit was marked as not found, but the corresponding hit"
+                       " structure was not set to nil.";
+       case kInvalidDetElementNumber:
+               return "An invalid detector element ID was found.";
+       case kInvalidChamberNumber:
+               return "An invalid chamber number was found.";
+       case kHitIsNil:
+               return "The hit cannot be set to a nil value.";
+       case kInvalidChannelCountB:
+               return "The number of channels in the bending plane indicated"
+                       " is zero or outside the valid range.";
+       case kInvalidChannelCountNB:
+               return "The number of channels in the non-bending plane indicated"
+                       " is zero or outside the valid range.";
+       case kInvalidChargeB:
+               return "The charge in the bending plane does not have a valid value.";
+       case kInvalidChargeNB:
+               return "The charge in the non-bending plane does not have a valid value.";
+       case kInvalidBusPatchId:
+               return "The bus patch identifier is outside the valid range.";
+       case kInvalidManuId:
+               return "The MANU identifier is outside the valid range.";
+       case kInvalidChannelAddress:
+               return "The MANU channel address is outside the valid range.";
+       case kInvalidSignal:
+               return "The ADC signal value is outside the valid range.";
+       case kDataWordDifferent:
+               return "The raw data word is different from the unpacked values.";
+       case kChiSquareInvalid:
+               return "The chi squared value must be a positive value or -1"
+                       " indicating no fit or a fitting error.";
+       case kMomentumVectorNotZero:
+               return "The chi sqaured value is set to -1 indicating momentum"
+                       " was not fitted, but the momentum vector was not zero.";
+       case kMomentumParamsNotZero:
+               return "The chi sqaured value is set to -1 indicating the track"
+                       " was not fitted, but the fitted momentum parameters are not zero.";
+       case kDCAVertexNotZero:
+               return "The chi sqaured value is set to -1 indicating the track"
+                       " was not fitted, but the DCA vertex is not zero.";
+       case kRoiRadiusInvalid:
+               return "The region of interest radius is invalid.";
+       case kHitNotWithinRoi:
+               return "A tracks hit is not within the corresponding region"
+                       " of interest.";
+       case kPtValueNotValid:
+               return "The pT value is not positive, nor -1 indicating an"
+                       " invalid value.";
+       case kPairTrackIdsAreIdentical:
+               return "The track identifiers of the track pair are identical.";
+       case kMassValueNotValid:
+               return "The invariant mass value is not positive, nor -1"
+                       " indicating an invalid value.";
+       case kLowPtCountInvalid:
+               return "The low pT trigger count is greater than 2,"
+                       " which is invalid.";
+       case kHighPtCountInvalid:
+               return "The high pT trigger count is greater than 2,"
+                       " which is invalid.";
+       case kFoundDuplicateIDs:
+               return "Found duplicate data record identifiers, but they"
+                       " should all be unique.";
+       case kFoundDuplicateHits:
+               return "Found duplicate hit structures, but they should all"
+                       " be unique.";
+       case kFoundDuplicateTriggers:
+               return "Found duplicate trigger decisions.";
+       default:
+               return "UNKNOWN REASON CODE";
+       }
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerRecordStruct& tr)
+bool AliHLTMUONUtils::RecordNumberWasSet(WhyNotValid reason)
 {
-       // Make sure that the reserved bits in the fFlags field are set
-       // to zero.
-       if ((tr.fFlags & 0x3FFFFFF0) != 0) return false;
-
-       // Make sure the sign is not invalid.
-       if ((tr.fFlags & 0xC0000000) == 3) return false;
-
-       // Check that fHit[i] is nil if the corresponding bit in the
-       // flags word is zero.
-       const AliHLTMUONRecHitStruct& nilhit
-               = AliHLTMUONConstants::NilRecHitStruct();
-       if ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) return false;
-       if ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) return false;
-       if ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) return false;
-       if ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit) return false;
-
-       return true;
+       /// Returns true if the \em recordNum in the corresponding IntegrityOk method
+       /// would have been set, if it returned false and a reason was set.
+       /// This helper method makes it easy to test if the \em recordNum parameter
+       /// is filled with a valid value or not.
+       /// \param reason  The reason code as returned by the IntegrityOk method.
+       /// \returns  true if the \em recordNum parameter was set for the given
+       ///      reason code.
+       
+       switch (reason)
+       {
+       case kInvalidIdValue:
+       case kInvalidTriggerIdValue:
+       case kInvalidTrackIdValue:
+       case kReservedBitsNotZero:
+       case kParticleSignBitsNotValid:
+       case kHitNotMarkedAsNil:
+       case kInvalidDetElementNumber:
+       case kInvalidChamberNumber:
+       case kHitIsNil:
+       case kInvalidChannelCountB:
+       case kInvalidChannelCountNB:
+       case kInvalidChargeB:
+       case kInvalidChargeNB:
+       case kInvalidBusPatchId:
+       case kInvalidManuId:
+       case kInvalidChannelAddress:
+       case kInvalidSignal:
+       case kDataWordDifferent:
+       case kChiSquareInvalid:
+       case kPtValueNotValid:
+       case kPairTrackIdsAreIdentical:
+       case kMassValueNotValid:
+       case kLowPtCountInvalid:
+       case kHighPtCountInvalid:
+               return true;
+       default: return false;
+       }
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerRecordsBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONTriggerRecordsBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
-
-       // Check if any ID is duplicated.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kTriggerRecordsDataBlock)
        {
-               AliHLTInt32_t id = block.fTriggerRecord[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               if (reason != NULL and reasonCount < maxCount)
                {
-                       if (id == block.fTriggerRecord[j].fId)
-                               return false;
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
                }
+               result = false;
        }
-
-       // Check integrity of individual trigger records.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerRecordStruct))
        {
-               if (not IntegrityOk(block.fTriggerRecord[i])) return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
-
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTrigRecsDebugBlockStruct& block)
-{
-       if (not HeaderOk(block)) return false;
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block)
-{
-       if (not HeaderOk(block)) return false;
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONRecHitsBlockStruct& block)
-{
-       if (not HeaderOk(block)) return false;
-       return true;
+       
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONClustersBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONTrigRecsDebugBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
-
-       // Check if any ID is duplicated.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kTrigRecsDebugDataBlock)
        {
-               AliHLTInt32_t id = block.fCluster[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               if (reason != NULL and reasonCount < maxCount)
                {
-                       if (id == block.fCluster[j].fId)
-                               return false;
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
                }
+               result = false;
        }
        
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONChannelsBlockStruct& block)
-{
-       if (not HeaderOk(block)) return false;
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoTrackStruct& track)
-{
-       // Make sure that the reserved bits in the fFlags field are set
-       // to zero.
-       if ((track.fFlags & 0x3FFFFFF0) != 0) return false;
-
-       // Make sure the sign is not invalid.
-       if ((track.fFlags & 0xC0000000) == 0xC0000000) return false;
-
-       // Check that fHit[i] is nil if the corresponding bit in the
-       // flags word is zero.
-       const AliHLTMUONRecHitStruct& nilhit
-               = AliHLTMUONConstants::NilRecHitStruct();
-       if ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) return false;
-       if ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) return false;
-       if ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) return false;
-       if ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit) return false;
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
        
-       return true;
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoTracksBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONRecHitsBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
-
-       // Check if any ID is duplicated.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kRecHitsDataBlock)
        {
-               AliHLTInt32_t id = block.fTrack[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               if (reason != NULL and reasonCount < maxCount)
                {
-                       if (id == block.fTrack[j].fId)
-                               return false;
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
                }
+               result = false;
        }
-
-       // Check that the tracks have integrity.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
        {
-               if (not IntegrityOk(block.fTrack[i])) return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
-
-       return true;
+       
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONMansoCandidatesBlockStruct& block)
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONClustersBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
-
-       // Check that the tracks have integrity.
-       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kClustersDataBlock)
        {
-               if (not IntegrityOk(block.fCandidate[i].fTrack)) return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
-}
-
-
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONTrackDecisionStruct& decision)
-{
-       // Make sure that the reserved bits in the fTriggerBits field are set
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONChannelsBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kChannelsDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONMansoTracksBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kMansoTracksDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONMansoCandidatesBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kMansoCandidatesDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONTracksBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kTracksDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONSinglesDecisionBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kSinglesDecisionDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::HeaderOk(
+               const AliHLTMUONPairsDecisionBlockStruct& block,
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+       )
+{
+       /// Method used to check if the header information corresponds to the
+       /// supposed type of the raw dHLT data block.
+       /// \param [in]  block  The data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the header is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the header and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The block must have the correct type.
+       if (block.fHeader.fType != kPairsDecisionDataBlock)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongType;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The block's record width must be the correct size.
+       if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTriggerRecordStruct& tr,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// trigger record structure is OK and returns true in that case.
+       /// \param [in]  tr  The trigger record structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the ID has a valid value.
+       if (not (tr.fId >= 0 or tr.fId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure that the reserved bits in the fFlags field are set
+       // to zero.
+       if ((tr.fFlags & 0x3FFFFFF0) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Make sure the sign is not invalid.
+       if ((tr.fFlags & 0xC0000000) == 0xC0000000)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kParticleSignBitsNotValid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that fHit[i] is nil if the corresponding bit in the
+       // flags word is zero.
+       const AliHLTMUONRecHitStruct& nilhit
+               = AliHLTMUONConstants::NilRecHitStruct();
+       if ( ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) or
+            ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) or
+            ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) or
+            ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHitNotMarkedAsNil;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check the individual hits
+       for (int i = 0; i < 4; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(tr.fHit[i], reason + reasonCount, filledCount))
+               {
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTriggerRecordsBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// \param [in]  block  The trigger record data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the trigger record that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       ///        - kInvalidDetElementNumber
+       ///        - kInvalidChamberNumber
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONTriggerRecordStruct* triggerRecord =
+               reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
+
+       // Check if any ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = triggerRecord[i].fId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == triggerRecord[j].fId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // Check integrity of individual trigger records.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(triggerRecord[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrigRecInfoStruct& trigInfo,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// trigger record debug information structure is OK and returns true in that case.
+       /// \param [in]  trigInfo  The trigger record debug information structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the trigger ID has a valid value.
+       if (not (trigInfo.fTrigRecId >= 0 or trigInfo.fTrigRecId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that the fDetElemId[i] numbers are valid.
+       if ( not ((trigInfo.fDetElemId[0] >= 100 and trigInfo.fDetElemId[0] < 1500)
+                 or trigInfo.fDetElemId[0] == -1)
+            or not ((trigInfo.fDetElemId[1] >= 100 and trigInfo.fDetElemId[1] < 1500)
+                 or trigInfo.fDetElemId[1] == -1)
+            or not ((trigInfo.fDetElemId[2] >= 100 and trigInfo.fDetElemId[2] < 1500)
+                 or trigInfo.fDetElemId[2] == -1)
+            or not ((trigInfo.fDetElemId[3] >= 100 and trigInfo.fDetElemId[3] < 1500)
+                 or trigInfo.fDetElemId[3] == -1)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidDetElementNumber;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrigRecsDebugBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal data block is OK and returns true in that case.
+       /// \param [in]  block  The trigger record debugging information data block
+       ///      to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the trigger record debug information
+       ///      structure that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kInvalidDetElementNumber
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONTrigRecInfoStruct* triggerInfo =
+               reinterpret_cast<const AliHLTMUONTrigRecInfoStruct*>(&block + 1);
+
+       // Check if any trigger debug info structure has duplicated trigger IDs.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = triggerInfo[i].fTrigRecId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == triggerInfo[j].fTrigRecId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // Check integrity of individual trigger records.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(triggerInfo[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONRecHitStruct& hit,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// reconstructed hit structure is OK and returns true in that case.
+       /// \param [in]  hit  The reconstructed hit structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // If this is a NIL hit then skip all other checks.
+       if (hit == AliHLTMUONConstants::NilRecHitStruct())
+       {
+               return true;
+       }
+       
+       // Make sure that the reserved bits in the fFlags field are set
+       // to zero.
+       if ((hit.fFlags & 0x3FFF0000) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       AliHLTUInt32_t detElemId = hit.fFlags & 0x00000FFF;
+       AliHLTUInt32_t chamber = (hit.fFlags & 0x0000F000) >> 12;
+       
+       // Make sure the detector element ID number is valid.
+       if (not (detElemId >= 100 and detElemId < 1500))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidDetElementNumber;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure the chamber number is valid.
+       if (((detElemId / 100) - 1) != chamber or chamber >= 14)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChamberNumber;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONRecHitsBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT raw internal hits data block is OK and returns true in that case.
+       /// \param [in]  block  The reconstructed hits data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the reconstructed hits that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kReservedBitsNotZero
+       ///        - kInvalidDetElementNumber
+       ///        - kInvalidChamberNumber
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONRecHitStruct* hit =
+               reinterpret_cast<const AliHLTMUONRecHitStruct*>(&block + 1);
+
+       // Check if any hit structure has been duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               const AliHLTMUONRecHitStruct& h = hit[i];
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (h == hit[j])
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateHits;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // Check integrity of the individual hit structures.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(hit[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONClusterStruct& cluster,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// cluster structure is OK and returns true in that case.
+       /// \param [in]  cluster  The cluster structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the cluster ID has a valid value.
+       if (not (cluster.fId >= 0 or cluster.fId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the cluster does not have a nil value for its hit.
+       if (cluster.fHit == AliHLTMUONConstants::NilRecHitStruct())
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHitIsNil;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure the detector element is a valid value.
+       if (not ((cluster.fDetElemId >= 100 and cluster.fDetElemId < 1500)
+           or cluster.fDetElemId == -1)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidDetElementNumber;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The number of channels should be in a reasonable range.
+       // Using a value of 5*5*2, 5 pads by 5 pads by 2 cathode planes.
+       if (int(cluster.fNchannelsB) < 1 or (5*5*2) < int(cluster.fNchannelsB))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChannelCountB;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       if (int(cluster.fNchannelsNB) < 1 or (5*5*2) < int(cluster.fNchannelsNB))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChannelCountNB;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       
+       // The charge values must be a positive value or -1.
+       if (not (cluster.fChargeB >= 0 or cluster.fChargeB == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChargeB;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       if (not (cluster.fChargeNB >= 0 or cluster.fChargeNB == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChargeNB;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONClustersBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal clusters data block is OK and returns true in that case.
+       /// \param [in]  block  The clusters data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the cluster structure that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kHitIsNil
+       ///        - kInvalidDetElementNumber
+       ///        - kInvalidChannelCountB
+       ///        - kInvalidChannelCountNB
+       ///        - kInvalidChargeB
+       ///        - kInvalidChargeNB
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+
+       const AliHLTMUONClusterStruct* cluster =
+               reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
+       
+       // Check if any ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = cluster[i].fId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == cluster[j].fId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // Check if any hit structure has been duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               const AliHLTMUONRecHitStruct& h = cluster[i].fHit;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (h == cluster[j].fHit)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateHits;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // Check integrity of individual cluster structures.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(cluster[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONChannelStruct& channel,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// channel structure is OK and returns true in that case.
+       /// \param [in]  cluster  The channel structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the channel ID has a valid value.
+       if (not (channel.fClusterId >= 0 or channel.fClusterId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the bus patch ID has a valid value, which fits into 12 bits.
+       if ((channel.fBusPatch & (~0xFFF)) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidBusPatchId;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the MANU ID has a valid value, which fits into 11 bits.
+       if ((channel.fManu & (~0x7FF)) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidManuId;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the channel address has a valid value, which fits into 6 bits.
+       if ((channel.fChannelAddress & (~0x3F)) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChannelAddress;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the ADC signal has a valid value, which fits into 12 bits.
+       if ((channel.fSignal & (~0xFFF)) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidSignal;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the raw data word corresponds to the unpacked values for
+       // the ADC signal, MANU ID and channel address.
+       UShort_t manuId; UChar_t channelId; UShort_t adc;
+       AliMUONTrackerDDLDecoderEventHandler::UnpackADC(
+                       channel.fRawDataWord, manuId, channelId, adc
+               );
+       if (manuId != channel.fManu or channelId != channel.fChannelAddress
+           or adc != channel.fSignal
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kDataWordDifferent;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONChannelsBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal channels data block is OK and returns true in that case.
+       /// \param [in]  block  The channels data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the channel structure that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kInvalidBusPatchId
+       ///        - kInvalidManuId
+       ///        - kInvalidChannelAddress
+       ///        - kInvalidSignal
+       ///        - kDataWordDifferent
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONChannelStruct* channel =
+               reinterpret_cast<const AliHLTMUONChannelStruct*>(&block + 1);
+
+       // Check integrity of individual channel structures.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(channel[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoTrackStruct& track,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// Manso track structure is OK and returns true in that case.
+       /// \param [in]  track  The track structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the Manso track ID has a valid value.
+       if (not (track.fId >= 0 or track.fId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the corresponding trigger record ID has a valid value.
+       if (not (track.fTrigRec >= 0 or track.fTrigRec == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidTriggerIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure that the reserved bits in the fFlags field are set
        // to zero.
-       if ((decision.fTriggerBits & 0xFFFFFFFC) != 0) return false;
-       return true;
+       if ((track.fFlags & 0x3FFFFFF0) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Make sure the sign is not invalid.
+       if ((track.fFlags & 0xC0000000) == 0xC0000000)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kParticleSignBitsNotValid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that fHit[i] is nil if the corresponding bit in the
+       // flags word is zero.
+       const AliHLTMUONRecHitStruct& nilhit
+               = AliHLTMUONConstants::NilRecHitStruct();
+       if ( ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) or
+            ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) or
+            ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) or
+            ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHitNotMarkedAsNil;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that the chi squared value is valid
+       if (not (track.fChi2 >= 0 or track.fChi2 == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kChiSquareInvalid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that if chi squared is -1 then the momentum vector is zero.
+       if (track.fChi2 == -1 and
+           not (track.fPx == 0 and track.fPy == 0 and track.fPz == 0)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kMomentumVectorNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check the individual hits
+       for (int i = 0; i < 4; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(track.fHit[i], reason + reasonCount, filledCount))
+               {
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONSinglesDecisionBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoTracksBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal Manso track data block is OK and returns true in that case.
+       /// \param [in]  block  The Manso track data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the Manso track that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kInvalidTriggerIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       ///        - kChiSquareInvalid
+       ///        - kMomentumVectorNotZero
+       ///        - kInvalidDetElementNumber
+       ///        - kInvalidChamberNumber
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONMansoTrackStruct* track =
+               reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
+       
+       // Check if any track ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = track[i].fId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == track[j].fId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+       
+       // Check that all the tracks have integrity.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(track[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
 
-       // Check that the trigger bits for each track have integrity.
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoCandidateStruct& candidate,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// Manso track candidate structure is OK and returns true in that case.
+       /// \param [in]  track  The track candidate structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       // First check the integrity of the candidate track structure.
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = IntegrityOk(candidate.fTrack, reason, reasonCount);
+       
+       // Now check that the ROIs are reasonable.
+       // The radius must be positive or -1 indicating computation error and
+       // the corresponding hit in the track must be within the ROI.
+       for (AliHLTUInt32_t i = 0; i < 4; i++)
+       {
+               if (not (candidate.fRoI[i].fRadius >= 0 or candidate.fRoI[i].fRadius == -1))
+               {
+                       if (reason != NULL and reasonCount < maxCount)
+                       {
+                               reason[reasonCount] = kRoiRadiusInvalid;
+                               reasonCount++;
+                       }
+                       result = false;
+               }
+               
+               // Check if the corresponding hit was even found in the track.
+               if ( (candidate.fTrack.fFlags & (0x1 << i)) == 0 ) continue;
+               
+               double dx = candidate.fRoI[i].fX - candidate.fTrack.fHit[i].fX;
+               double dy = candidate.fRoI[i].fY - candidate.fTrack.fHit[i].fY;
+               double dz = candidate.fRoI[i].fZ - candidate.fTrack.fHit[i].fZ;
+               double r = sqrt(dx*dx + dy*dy);
+               // Check if the projected distance between ROI centre and hit is
+               // bigger than the ROI radius. Also the difference between z
+               // coordinates should not exceed 20 cm.
+               if (r > candidate.fRoI[i].fRadius or fabs(dz) > 20.)
+               {
+                       if (reason != NULL and reasonCount < maxCount)
+                       {
+                               reason[reasonCount] = kHitNotWithinRoi;
+                               reasonCount++;
+                       }
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONMansoCandidatesBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal Manso candidates data block is OK and returns true in
+       /// that case.
+       /// \param [in]  block  The Manso track candidate data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the track candidate that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kInvalidTriggerIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       ///        - kChiSquareInvalid
+       ///        - kRoiRadiusInvalid
+       ///        - kHitNotWithinRoi
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+
+       const AliHLTMUONMansoCandidateStruct* candidate =
+               reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
+       
+       // Check if any candidate track ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = candidate[i].fTrack.fId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == candidate[j].fTrack.fId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+       
+       // Check that all the track candidates have integrity.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(candidate[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrackStruct& track,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// full track structure is OK and returns true in that case.
+       /// \param [in]  track  The track structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is
+       ///      not valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // Check that the track ID has a valid value.
+       if (not (track.fId >= 0 or track.fId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the corresponding trigger record ID has a valid value.
+       if (not (track.fTrigRec >= 0 or track.fTrigRec == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidTriggerIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure that the reserved bits in the fFlags field are set
+       // to zero.
+       if ((track.fFlags & 0x3FFF0000) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Make sure the sign is not invalid.
+       if ((track.fFlags & 0xC0000000) == 0xC0000000)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kParticleSignBitsNotValid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that fHit[i] is nil if the corresponding bit in the
+       // flags word is zero.
+       const AliHLTMUONRecHitStruct& nilhit = AliHLTMUONConstants::NilRecHitStruct();
+       for (int i = 0; i < 16; i++)
+       {
+               if ((track.fFlags & (0x1 << i)) == 0 and track.fHit[i] != nilhit)
+               {
+                       if (reason != NULL and reasonCount < maxCount)
+                       {
+                               reason[reasonCount] = kHitNotMarkedAsNil;
+                               reasonCount++;
+                       }
+                       result = false;
+                       break;
+               }
+       }
+
+       // Check that the chi squared value is valid
+       if (not (track.fChi2 >= 0 or track.fChi2 == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kChiSquareInvalid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that if chi squared is -1 then the momentum vector is zero.
+       if (track.fChi2 == -1 and
+           not (track.fPx == 0 and track.fPy == 0 and track.fPz == 0)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kMomentumVectorNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that if chi squared is -1 then the momentum parameters are zero.
+       if (track.fChi2 == -1 and
+           not (track.fInverseBendingMomentum == 0 and track.fThetaX == 0 and track.fThetaY == 0)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kMomentumParamsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       // Check that if chi squared is -1 then the momentum parameters are zero.
+       if (track.fChi2 == -1 and
+           not (track.fX == 0 and track.fY == 0 and track.fZ == 0)
+          )
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kDCAVertexNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check the individual hits
+       for (int i = 0; i < 16; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(track.fHit[i], reason + reasonCount, filledCount))
+               {
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTracksBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal track data block is OK and returns true in that case.
+       /// \param [in]  block  The track data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the Manso track that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidIdValue
+       ///        - kInvalidTriggerIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kParticleSignBitsNotValid
+       ///        - kHitNotMarkedAsNil
+       ///        - kChiSquareInvalid
+       ///        - kMomentumVectorNotZero
+       ///        - kMomentumParamsNotZero
+       ///        - kDCAVertexNotZero
+       ///        - kInvalidDetElementNumber
+       ///        - kInvalidChamberNumber
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONTrackStruct* track =
+               reinterpret_cast<const AliHLTMUONTrackStruct*>(&block + 1);
+       
+       // Check if any track ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = track[i].fId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == track[j].fId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+       
+       // Check that all the tracks have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(block.fDecision[i])) return false;
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(track[i], reason+reasonCount, filledCount))
+               {
+                       // reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
        }
        
-       return true;
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONPairDecisionStruct& decision)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONTrackDecisionStruct& decision,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
 {
+       /// This method is used to check more extensively if the integrity of the
+       /// single track trigger decision structure is OK and returns true in that case.
+       /// \param [in]  decision  The trigger decision structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       // The track ID value must be positive or -1.
+       if (not (decision.fTrackId >= 0 or decision.fTrackId == -1))
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidTrackIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
        // Make sure that the reserved bits in the fTriggerBits field are set
        // to zero.
-       if ((decision.fTriggerBits & 0xFFFFFF80) != 0) return false;
+       if ((decision.fTriggerBits & 0xFFFFFFFC) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The pT should be -1 or a positive number.
+       if (decision.fPt != -1. and decision.fPt < 0.)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kPtValueNotValid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONSinglesDecisionBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal single track trigger decision data block is OK and returns
+       /// true in that case.
+       /// \param [in]  block  The single track trigger decision data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the trigger decision that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidTrackIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kPtValueNotValid
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
        
-       // The high mass or low mass bits can only be set if unlike bit is set.
-       if ((decision.fTriggerBits & 0x00000010) == 0
-           and (decision.fTriggerBits & 0x00000060) != 0
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONTrackDecisionStruct* decision =
+               reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
+
+       // Check that there are no duplicate trigger entries.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = decision[i].fTrackId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == decision[j].fTrackId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateTriggers;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+       
+       // Check that the trigger bits for each track have integrity.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
+               {
+                       // Reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONPairDecisionStruct& decision,
+               WhyNotValid* reason,
+               AliHLTUInt32_t& reasonCount
+       )
+{
+       /// This method is used to check more extensively if the integrity of the
+       /// track pair trigger decision structure is OK and returns true in that case.
+       /// \param [in]  decision  The trigger decision structure to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the structure is not
+       ///      valid.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason'. It will be filled with the number
+       ///      of items actually filled into the reason array upon exit from this
+       ///      method.
+       /// \returns  true if there is no problem with the structure and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       reasonCount = 0;
+       bool result = true;
+       
+       //kInvalidTrackIdValue
+       
+       // The track IDs must have a positive value or -1.
+       if (not (decision.fTrackAId >= 0 or decision.fTrackAId == -1) or
+           not (decision.fTrackBId >= 0 or decision.fTrackBId == -1)
           )
-               return false;
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidTrackIdValue;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Make sure that the reserved bits in the fTriggerBits field are set
+       // to zero.
+       if ((decision.fTriggerBits & 0xFFFFFF80) != 0)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kReservedBitsNotZero;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // Check that the track IDs are not the same.
+       if (decision.fTrackAId == decision.fTrackBId)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kPairTrackIdsAreIdentical;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       
+       // The invariant mass should be -1 or a positive number.
+       if (decision.fInvMass != -1. and decision.fInvMass < 0.)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kMassValueNotValid;
+                       reasonCount++;
+               }
+               result = false;
+       }
        
        // Neither the high pt (hipt) or low pt (lopt) count bits can be > 2.
-       // And the sum must not be > 2.
        AliHLTUInt8_t lowPtCount = (decision.fTriggerBits & 0x00000003);
        AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
-       if (lowPtCount + highPtCount > 2) return false;
+       if (lowPtCount > 2)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kLowPtCountInvalid;
+                       reasonCount++;
+               }
+               result = false;
+       }
+       if (highPtCount > 2)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHighPtCountInvalid;
+                       reasonCount++;
+               }
+               result = false;
+       }
        
-       return true;
+       return result;
 }
 
 
-bool AliHLTMUONUtils::IntegrityOk(const AliHLTMUONPairsDecisionBlockStruct& block)
+bool AliHLTMUONUtils::IntegrityOk(
+               const AliHLTMUONPairsDecisionBlockStruct& block,
+               WhyNotValid* reason,
+               AliHLTUInt32_t* recordNum,
+               AliHLTUInt32_t& reasonCount
+       )
 {
-       if (not HeaderOk(block)) return false;
+       /// This method is used to check more extensively if the integrity of the
+       /// dHLT internal track pair trigger decision data block is OK and returns
+       /// true in that case.
+       /// \param [in]  block  The track pair trigger decision data block to check.
+       /// \param [out] reason  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the reason codes describing why the data block is
+       ///      not valid.
+       /// \param [out] recordNum  If this is not NULL, then it is assumed to point
+       ///      to an array of at least 'reasonCount' number of elements. It will
+       ///      be filled with the number of the trigger decision that had a problem.
+       ///      The value 'recordNum[i]' will only contain a valid value if
+       ///      the corresponding 'reason[i]' contains one of:
+       ///        - kInvalidTrackIdValue
+       ///        - kReservedBitsNotZero
+       ///        - kPairTrackIdsAreIdentical
+       ///        - kMassValueNotValid
+       ///        - kLowPtCountInvalid
+       ///        - kHighPtCountInvalid
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// \param [in,out] reasonCount  This should initially specify the size of
+       ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
+       ///      with the number of items actually filled into the arrays upon exit
+       ///      from this method.
+       /// \returns  true if there is no problem with the data and false otherwise.
+       
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
 
+       const AliHLTMUONPairDecisionStruct* decision =
+               reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
+       
+       // Check that there are no duplicate trigger entries.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t ta = decision[i].fTrackAId;
+               AliHLTInt32_t tb = decision[i].fTrackBId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateTriggers;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+       
        // Check that the trigger bits for each track pair have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(block.fDecision[i])) return false;
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
+               {
+                       // Reasons filled in IntegrityOk, now we just need to adjust
+                       // reasonCount and fill the recordNum values.
+                       if (recordNum != NULL)
+                       {
+                               for (AliHLTUInt32_t n = 0; n < filledCount; n++)
+                                       recordNum[reasonCount + n] = i;
+                       }
+                       reasonCount += filledCount;
+                       result = false;
+               }
        }
        
-       return true;
+       return result;
 }
+