Added:
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 27 May 2008 08:48:20 +0000 (08:48 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 27 May 2008 08:48:20 +0000 (08:48 +0000)
AliHLTMUONDataCheckerComponent - This is a component for testing and debugging, which performs extensive integrity and sanity checks on the dHLT raw data.

Changes:
AliHLTMUONProcessor - Extracted common code for fetching dimuon spectrometer mapping store objects into its own method FetchMappingStores.
AliHLTMUONTriggerReconstructorComponent and AliHLTMUONHitReconstructorComponent - Minor cleanup and moved common code into FetchMappingStores.
AliHLTMUONChannelsBlockStruct - Added fBusPatch member to also keep track of the bus patch for the channel.
AliHLTMUONMansoTracksBlockStruct - Fixing comments and documentation.
RunChain.C and dHLTrootify.cxx - Now optionally using AliHLTMUONDataCheckerComponent for checking data.

22 files changed:
HLT/MUON/AliHLTMUONChannelsBlockStruct.cxx
HLT/MUON/AliHLTMUONChannelsBlockStruct.h
HLT/MUON/AliHLTMUONConstants.cxx
HLT/MUON/AliHLTMUONConstants.h
HLT/MUON/AliHLTMUONMansoTracksBlockStruct.cxx
HLT/MUON/AliHLTMUONMansoTracksBlockStruct.h
HLT/MUON/AliHLTMUONProcessor.cxx
HLT/MUON/AliHLTMUONProcessor.h
HLT/MUON/AliHLTMUONUtils.cxx
HLT/MUON/AliHLTMUONUtils.h
HLT/MUON/HLTMUONLinkDef.h
HLT/MUON/OfflineInterface/AliHLTMUONAgent.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructorComponent.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructorComponent.h
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.h
HLT/MUON/macros/RunChain.C
HLT/MUON/utils/AliHLTMUONDataCheckerComponent.cxx [new file with mode: 0644]
HLT/MUON/utils/AliHLTMUONDataCheckerComponent.h [new file with mode: 0644]
HLT/MUON/utils/dHLTdumpraw.cxx
HLT/MUON/utils/dHLTrootify.cxx
HLT/libAliHLTMUON.pkg

index 709b1ce8a66e5733b468a1f0efa86a53756c9a39..46248858bbb58357e58e923106f02a60bac5be27 100644 (file)
 
 /* $Id$ */
 
-/**
- * @file   AliHLTMUONChannelsBlockStruct.cxx
- * @author Artur Szostak <artursz@iafrica.com>
- * @date   
- * @brief  Implementation of the stream and comparison operators.
- */
+///
+/// @file   AliHLTMUONChannelsBlockStruct.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   18 May 2007
+/// @brief  Implementation of the stream and comparison operators.
+///
+/// The channels blocks are internal dimuon HLT block structures containing
+/// debugging information about channels that belong to reconstructed
+/// hit clusters.
+///
 
 #include "AliHLTMUONChannelsBlockStruct.h"
 #include "AliHLTMUONUtils.h"
@@ -31,6 +35,7 @@ std::ostream& operator << (
        )
 {
        stream  << "{fClusterId = " << channel.fClusterId
+               << ", fBusPatch = " << channel.fBusPatch
                << ", fManu = " << channel.fManu
                << ", fChannelAddress = " << channel.fChannelAddress
                << ", fSignal = " << channel.fSignal
index b62fd1818000fbf01d350451c25465c7dd326bf7..0281633c08b610ec699baedbf58d2b680735ab95 100644 (file)
@@ -5,17 +5,15 @@
 
 /* $Id$ */
 
-/**
- * @file   AliHLTMUONChannelsBlockStruct.h
- * @author Artur Szostak <artursz@iafrica.com>
- * @date   
- * @brief  Definition of internal dimuon HLT block structure containing
- *         debugging information about channels that belong to reconstructed
- *         hit clusters.
- * 
- * The structures are defined with C linkage since C generally gives us more
- * binary compatibility between compilers.
- */
+///
+/// @file   AliHLTMUONChannelsBlockStruct.h
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   18 May 2007
+/// @brief  Definition of internal dHLT channels block structure corresponding to clusters.
+///
+/// The structures are defined with C linkage since C generally gives us more
+/// binary compatibility between compilers.
+///
 
 #include "AliHLTMUONDataTypes.h"
 #include <ostream>
@@ -32,6 +30,7 @@ struct AliHLTMUONChannelStruct
        AliHLTInt32_t fClusterId;   // ID corresponding to the cluster this
                                    // channel is part of. -1 == invalid.
 
+       AliHLTUInt32_t fBusPatch;    // Bus patch to which this is connected.
        AliHLTUInt16_t fManu;        // The MANU address on electronics.
        AliHLTUInt16_t fChannelAddress; // The channel address on electronics.
        AliHLTUInt32_t fSignal;      // ADC value of signal.
@@ -56,7 +55,7 @@ struct AliHLTMUONChannelsBlockStruct
 /**
  * Stream operator for usage with std::ostream classes which prints the
  * AliHLTMUONChannelStruct in the following format:
- *   {fClusterId = xx, fManu = yy, fChannelAddress = zz, fSignal = ww,
+ *   {fClusterId = xx, fBusPatch = yy, fManu = zz, fChannelAddress = uu, fSignal = ww,
  *    fRawDataWord = 0xXXXXXXXX}
  */
 std::ostream& operator << (
@@ -78,8 +77,8 @@ inline bool operator == (
                const AliHLTMUONChannelStruct& b
        )
 {
-       return a.fClusterId == b.fClusterId and a.fManu == b.fManu and
-               a.fChannelAddress == b.fChannelAddress and
+       return a.fClusterId == b.fClusterId and a.fBusPatch == b.fBusPatch and
+               a.fManu == b.fManu and a.fChannelAddress == b.fChannelAddress and
                a.fSignal == b.fSignal and a.fRawDataWord == b.fRawDataWord;
 }
 
index b7e35ef260d8df730a732df0fa2a715b8e20f581..9cc4ffe4295c3a6aada45a3ada4f15c07eeb628d 100644 (file)
@@ -179,7 +179,8 @@ const char* AliHLTMUONConstants::fgkHitReconstructorId = "MUONHitReconstructor";
 const char* AliHLTMUONConstants::fgkMansoTrackerFSMId = "MUONMansoTrackerFSM";
 const char* AliHLTMUONConstants::fgkDecisionComponentId = "MUONDecisionComponent";
 const char* AliHLTMUONConstants::fgkRootifierComponentId = "MUONRootifier";
-const char* AliHLTMUONConstants::fgkEmptyEventFilterComponentId = "MUONEmptyEventFilterComponent";
+const char* AliHLTMUONConstants::fgkEmptyEventFilterComponentId = "MUONEmptyEventFilter";
+const char* AliHLTMUONConstants::fgkDataCheckerComponentId = "MUONDataChecker";
 
 const char* AliHLTMUONConstants::fgkDecisionComponentCDBPath = "HLT/ConfigMUON/DecisionComponent";
 
index 51db0fbadfbca2826e12fdebf8da7ea06ea29333..ce01475dcd28937f39b628b069bb5b9160c97c9f 100644 (file)
@@ -212,6 +212,11 @@ public:
                return fgkEmptyEventFilterComponentId;
        }
        
+       static const char* DataCheckerComponentId()
+       {
+               return fgkDataCheckerComponentId;
+       }
+       
        static const char* DecisionComponentCDBPath()
        {
                return fgkDecisionComponentCDBPath;
@@ -261,6 +266,7 @@ private:
        static const char* fgkDecisionComponentId; // dHLT decision component name.
        static const char* fgkRootifierComponentId; // The name of the event filter debugging component.
        static const char* fgkEmptyEventFilterComponentId; // The name of the event filter debugging component.
+       static const char* fgkDataCheckerComponentId; // Name of data checking component for debugging.
        
        // CDB path entries to configuration information.
        static const char* fgkDecisionComponentCDBPath; // Path to CDB entry for trigger decision component.
index ad03f0df4247ffda3beeed0069664f92f2d0aba1..c90938c1274bbd312e062cc373d8995640982b18 100644 (file)
 
 /* $Id$ */
 
-/**
- * @file   AliHLTMUONMansoTracksBlockStruct.cxx
- * @author Artur Szostak <artursz@iafrica.com>
- * @date   
- * @brief  Implementation of useful stream and comparison operators.
- */
+///
+/// @file   AliHLTMUONMansoTracksBlockStruct.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   21 May 2007
+/// @brief  Implementation of useful stream and comparison operators.
+///
+/// The Manso tracks data block is an internal dimuon HLT data block structure
+/// generated by the Manso algorithm.
+///
 
 #include "AliHLTMUONMansoTracksBlockStruct.h"
 #include "AliHLTMUONUtils.h"
index 9877ae02cb82668ecc23149765d01fd0f21516d7..e5f4a7dfb6b8808f6feb1be7958f0016a65566e7 100644 (file)
@@ -5,16 +5,17 @@
 
 /* $Id$ */
 
-/**
- * @file   AliHLTMUONMansoTracksBlockStruct.h
- * @author Artur Szostak <artursz@iafrica.com>
- * @date   
- * @brief  Definition of internal dimuon HLT tracks data block structure
- *         generated by the Manso algorithm.
- * 
- * The structures are defined with C linkage since C generally gives us more
- * binary compatibility between compilers.
- */
+///
+/// @file   AliHLTMUONMansoTracksBlockStruct.h
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   21 May 2007
+/// @brief  Definition the Manso tracks internal dimuon HLT data block.
+///
+/// The Manso tracks data block is an internal dimuon HLT data block structure
+/// generated by the Manso algorithm.
+/// The structures are defined with C linkage since C generally gives us more
+/// binary compatibility between compilers.
+///
 
 #include "AliHLTMUONRecHitsBlockStruct.h"
 
@@ -49,7 +50,8 @@ struct AliHLTMUONMansoTrackStruct
        AliHLTFloat32_t fPy; // Particle's momentum Y component in GeV/c.
        AliHLTFloat32_t fPz; // Particle's momentum Z component in GeV/c.
        AliHLTFloat32_t fChi2; // The chi squared of the fit of fHit points to
-                              // the track model.
+                              // the track model. If -1 then no fit done and
+                              // momentum vector is invalid.
 
        // Particle hit coordinates on tracking chambers 7 to 10.
        // fHit[0] is for chamber 7 fHit[1] for chamber 8 etc...
index 7c0377585c74607fc2676296b98e39d21aa67f23..be8a1c0fa9458ca05ea4ed157a3a890588aa2cc2 100644 (file)
@@ -19,7 +19,7 @@
 ///
 /// @file   AliHLTMUONProcessor.cxx
 /// @author Artur Szostak <artursz@iafrica.com>
-/// @date   2007-12-12
+/// @date   19 May 2008
 /// @brief  Implementation of the abstract base dHLT processor component.
 ///
 /// This component is the abstract base class of dHLT specific components.
 ///
 
 #include "AliHLTMUONProcessor.h"
+#include "AliCDBManager.h"
+#include "AliCDBStorage.h"
+#include "AliMpCDB.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEStore.h"
 
 ClassImp(AliHLTMUONProcessor)
 
+
+int AliHLTMUONProcessor::FetchMappingStores(
+               const char* cdbPath, Int_t run, bool useDefault
+       ) const
+{
+       /// Fetches the DDL and detector element store objects for MUON mapping.
+       /// \param cdbPath  The CDB path to use. If set to NULL and the path has
+       ///      not been set in the CDB manager then the default path
+       ///      "local://$ALICE_ROOT" is used if the 'useDefault' flag is also true.
+       /// \param run  The run number to use. If set to -1 and the run number has
+       ///      not been set in the CDB manager then a value of zero is used if
+       ///      the 'useDefault' flag is also true.
+       /// \param useDefault  If set to true then a default CDB path and run number
+       ///      is used if they have not been set and 'cdbPath' == NULL or
+       ///      'run' == NULL.
+       /// \return Zero if the object could be loaded. Otherwise an error code is
+       ///      returned, which is compatible with the HLT framework.
+       /// \note AliMpDDLStore::Instance() and AliMpDEStore::Instance() must be used
+       ///      to fetch the objects after this method returns a code equal to zero.
+       
+       // Check if the objects are already loaded. If they are then exit early,
+       // otherwise we need to try load the objects.
+       if (AliMpDDLStore::Instance() != NULL and AliMpDEStore::Instance() != NULL)
+               return 0;
+       
+       const char* defaultPath = "local://$ALICE_ROOT";
+       Int_t defaultRun = 0;
+       
+       AliCDBManager* cdbManager = AliCDBManager::Instance();
+       if (cdbManager == NULL)
+       {
+               HLTError("CDB manager instance does not exist.");
+               return -EIO;
+       }
+       
+       // Setup the CDB path.
+       const char* cdbPathUsed = "unknown (not set)";
+       if (cdbPath != NULL)
+       {
+               cdbManager->SetDefaultStorage(cdbPath);
+               cdbPathUsed = cdbPath;
+       }
+       else
+       {
+               AliCDBStorage* store = cdbManager->GetDefaultStorage();
+               if (store == NULL)
+               {
+                       if (useDefault)
+                       {
+                               cdbManager->SetDefaultStorage(defaultPath);
+                               cdbPathUsed = defaultPath;
+                       }
+               }
+               else
+               {
+                       cdbPathUsed = store->GetURI().Data();
+               }
+       }
+       
+       // Now setup the run number.
+       if (run != -1)
+       {
+               cdbManager->SetRun(run);
+       }
+       else
+       {
+               if (useDefault) cdbManager->SetRun(defaultRun);
+       }
+       Int_t runUsed = cdbManager->GetRun();
+       
+       // Now we can try load the DDL and DE store objects.
+       Bool_t warn = kFALSE;
+       if (not AliMpCDB::LoadDDLStore(warn))
+       {
+               HLTError("Failed to load DDL or detector element store specified"
+                        " for CDB path '%s' and run no. %d.",
+                       cdbPathUsed, runUsed
+               );
+               return -ENOENT;
+       }
+       
+       if (AliMpDDLStore::Instance() == NULL or AliMpDEStore::Instance() == NULL)
+       {
+               HLTError("Could not find or load the DDL or detector element store instance.");
+               return -EIO;
+       }
+       
+       return 0;
+}
+
index db21d2c7aa44f43988be174d4ea605815de35bc1..a5546eb827ca559b6266d74f08e718371b929722 100644 (file)
@@ -9,7 +9,7 @@
 ///
 /// @file   AliHLTMUONProcessor.h
 /// @author Artur Szostak <artursz@iafrica.com>
-/// @date   2007-12-12
+/// @date   19 May 2008
 /// @brief  Declaration of a common processor component abstract interface for dHLT components.
 ///
 
  * This component class is an abstract base class for dHLT components.
  * Some common methods useful to all dHLT specific components are implemented
  * by this class.
+ *
+ * @ingroup alihlt_dimuon_component
  */
 class AliHLTMUONProcessor : public AliHLTProcessor
 {
 public:
        /// Default constructor.
        AliHLTMUONProcessor() : AliHLTProcessor() {}
+       
        /// Default destructor.
        virtual ~AliHLTMUONProcessor() {}
 
@@ -40,70 +43,124 @@ protected:
         * \param block  The lightweight block reader whose data block should be checked.
         * \param name  A string containing a descriptive name of the data block
         *          type. This name is used in the logged error messages.
+        * \param checkHeader  Indicates if the common data block header should be checked.
         * \returns  true if the structure of the block looks OK and false otherwise.
         * \note  The BlockType should be a class deriving from AliHLTMUONDataBlockReader.
         */
        template <class BlockType>
-       bool BlockStructureOk(const BlockType& block, const char* name) const;
+       bool BlockStructureOk(
+                       const BlockType& block, const char* name,
+                       bool checkHeader = true
+               ) const;
        
        /// Checks the structure of a trigger records data block.
-       bool BlockStructureOk(const AliHLTMUONTriggerRecordsBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONTriggerRecordsBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "trigger records");
+               return BlockStructureOk(block, "trigger records", checkHeader);
        }
        
        /// Checks the structure of a trigger records debug information data block.
-       bool BlockStructureOk(const AliHLTMUONTrigRecsDebugBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONTrigRecsDebugBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "trigger records debug information");
+               return BlockStructureOk(block, "trigger records debug information", checkHeader);
        }
 
        /// Checks the structure of a reconstructed hits data block.
-       bool BlockStructureOk(const AliHLTMUONRecHitsBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONRecHitsBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "reconstructed hits");
+               return BlockStructureOk(block, "reconstructed hits", checkHeader);
        }
        
        /// Checks the structure of a clusters data block.
-       bool BlockStructureOk(const AliHLTMUONClustersBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONClustersBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "clusters");
+               return BlockStructureOk(block, "clusters", checkHeader);
        }
        
        /// Checks the structure of a ADC channels data block.
-       bool BlockStructureOk(const AliHLTMUONChannelsBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONChannelsBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "channels");
+               return BlockStructureOk(block, "channels", checkHeader);
        }
 
        /// Checks the structure of a Manso tracks data block.
-       bool BlockStructureOk(const AliHLTMUONMansoTracksBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONMansoTracksBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "Manso tracks");
+               return BlockStructureOk(block, "Manso tracks", checkHeader);
        }
        
        /// Checks the structure of a Manso track candidates data block.
-       bool BlockStructureOk(const AliHLTMUONMansoCandidatesBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONMansoCandidatesBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "Manso track candidates");
+               return BlockStructureOk(block, "Manso track candidates", checkHeader);
        }
 
        /// Checks the structure of a single track trigger decision data block.
-       bool BlockStructureOk(const AliHLTMUONSinglesDecisionBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONSinglesDecisionBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "singles decision");
+               return BlockStructureOk(block, "singles decision", checkHeader);
        }
 
        /// Checks the structure of a track pairs trigger decision data block.
-       bool BlockStructureOk(const AliHLTMUONPairsDecisionBlockReader& block) const
+       bool BlockStructureOk(
+                       const AliHLTMUONPairsDecisionBlockReader& block,
+                       bool checkHeader = true
+               ) const
        {
-               return BlockStructureOk(block, "pairs decision");
+               return BlockStructureOk(block, "pairs decision", checkHeader);
        }
        
+       /**
+        * Fetches the DDL and detector element store objects for MUON mapping.
+        * \param cdbPath  The CDB path to use. If set to NULL and the path has
+        *      not been set in the CDB manager then the default path
+        *      "local://$ALICE_ROOT" is used if the 'useDefault' flag is also true.
+        * \param run  The run number to use. If set to -1 and the run number has
+        *      not been set in the CDB manager then a value of zero is used if
+        *      the 'useDefault' flag is also true.
+        * \param useDefault  If set to true then a default CDB path and run number
+        *      is used if they have not been set and 'cdbPath' == NULL or
+        *      'run' == NULL.
+        * \return Zero if the object could be loaded. Otherwise an error code is
+        *      returned, which is compatible with the HLT framework.
+        * \note AliMpDDLStore::Instance() and AliMpDEStore::Instance() must be used
+        *      to fetch the objects after this method returns a code equal to zero.
+        */
+       int FetchMappingStores(
+                       const char* cdbPath = NULL, Int_t run = -1,
+                       bool useDefault = true
+               ) const;
+       
 private:
 
        // Do not allow copying of this class.
+       /// Not implemented.
        AliHLTMUONProcessor(const AliHLTMUONProcessor& /*obj*/);
+       /// Not implemented.
        AliHLTMUONProcessor& operator = (const AliHLTMUONProcessor& /*obj*/);
        
        ClassDef(AliHLTMUONProcessor, 0)  // Abstract base class for dHLT specific components.
@@ -112,7 +169,9 @@ private:
 //______________________________________________________________________________
 
 template <class BlockType>
-bool AliHLTMUONProcessor::BlockStructureOk(const BlockType& block, const char* name) const
+bool AliHLTMUONProcessor::BlockStructureOk(
+               const BlockType& block, const char* name, bool checkHeader
+       ) const
 {
        /// Performs basic checks to see if the input data block structure is OK,
        /// that it is not corrupt, too short etc...
@@ -151,13 +210,16 @@ bool AliHLTMUONProcessor::BlockStructureOk(const BlockType& block, const char* n
                return false;
        }
        
-       AliHLTMUONUtils::WhyNotValid reason;
-       if (not AliHLTMUONUtils::HeaderOk(block.BlockHeader(), &reason))
+       if (checkHeader)
        {
-               HLTError("Received a %s data block which might be corrupt. %s",
-                       name, AliHLTMUONUtils::FailureReasonToMessage(reason)
-               );
-               return false;
+               AliHLTMUONUtils::WhyNotValid reason;
+               if (not AliHLTMUONUtils::HeaderOk(block.BlockHeader(), &reason))
+               {
+                       HLTError("Received a %s data block which might be corrupt. %s",
+                               name, AliHLTMUONUtils::FailureReasonToMessage(reason)
+                       );
+                       return false;
+               }
        }
        
        return true;
index 1ac4a169c770d981de90627f4fe170d5810a57f1..c9f797d847aeefd6594000745044bc8685986feb 100644 (file)
@@ -18,7 +18,7 @@
 ///
 /// @file   AliHLTMUONUtils.cxx
 /// @author Artur Szostak <artursz@iafrica.com>
-/// @date   
+/// @date   17 May 2007
 /// @brief  Implementation of AliHLTMUONUtils utility routines.
 ///
 
@@ -34,7 +34,9 @@
 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
 #include "AliHLTMUONPairsDecisionBlockStruct.h"
+#include "AliMUONTrackerDDLDecoderEventHandler.h"
 #include <cstring>
+#include <cmath>
 #include <cassert>
 
 
@@ -435,16 +437,32 @@ const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid 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 kFoundDuplicateIDs: return "kFoundDuplicateIDs";
+       case kInvalidDetElementNumber: return "kInvalidDetElementNumber";
+       case kHitIsNil: return "kHitIsNil";
+       case kInvalidChannelCount: return "kInvalidChannelCount";
+       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 kRoiRadiusInvalid: return "kRoiRadiusInvalid";
+       case kHitNotWithinRoi: return "kHitNotWithinRoi";
        case kPtValueNotValid: return "kPtValueNotValid";
-       case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
        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";
        }
 }
@@ -460,9 +478,19 @@ const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
        case kNoReason:
                return "There was no problem with the data block.";
        case kHeaderContainsWrongType:
-               return "The common data header contains an incorrect type identifier.";
+               return "The common data header contains an incorrect type"
+                       " identifier.";
        case kHeaderContainsWrongRecordWidth:
-               return "The common data header contains an incorrect data record width.";
+               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:
@@ -470,85 +498,193 @@ const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
        case kHitNotMarkedAsNil:
                return "A hit was marked as not found, but the corresponding hit"
                        " structure was not set to nil.";
-       case kFoundDuplicateIDs:
-               return "Found duplicate data record identifiers, but they should all be unique.";
+       case kInvalidDetElementNumber:
+               return "An invalid detector element ID was found.";
+       case kHitIsNil:
+               return "The hit cannot be set to a nil value.";
+       case kInvalidChannelCount:
+               return "The number of channels indicated is zero or outside"
+                       " the valid range.";
+       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 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 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 kFoundDuplicateTriggers:
-               return "Found duplicate trigger decisions.";
+               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.";
+               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.";
+               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.";
+               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::RecordNumberWasSet(WhyNotValid reason)
+{
+       /// 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 kHitIsNil:
+       case kInvalidChannelCount:
+       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::HeaderOk(
                const AliHLTMUONTriggerRecordsBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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)
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongType;
-               return false;
+               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(AliHLTMUONTriggerRecordStruct))
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONTrigRecsDebugBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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)
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongType;
-               return false;
+               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(AliHLTMUONTrigRecInfoStruct))
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
@@ -585,247 +721,395 @@ bool AliHLTMUONUtils::HeaderOk(
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONRecHitsBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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)
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongType;
-               return false;
+               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(AliHLTMUONRecHitStruct))
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONClustersBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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 (reason != NULL) *reason = kHeaderContainsWrongType;
-               return false;
+               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(AliHLTMUONClusterStruct))
        {
-               if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONChannelsBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kHeaderContainsWrongType;
-               return false;
+               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) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONMansoTracksBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kHeaderContainsWrongType;
-               return false;
+               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) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONMansoCandidatesBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kHeaderContainsWrongType;
-               return false;
+               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) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONSinglesDecisionBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kHeaderContainsWrongType;
-               return false;
+               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) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::HeaderOk(
                const AliHLTMUONPairsDecisionBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason, AliHLTUInt32_t& reasonCount
        )
 {
        /// Method used to check if the header information corresponds to the
        /// supposed type of the raw dHLT data block.
        /// [in]  \param block  The data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the header is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kHeaderContainsWrongType;
-               return false;
+               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) *reason = kHeaderContainsWrongRecordWidth;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHeaderContainsWrongRecordWidth;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONTriggerRecordStruct& tr,
-               WhyNotValid* reason
+               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.
        /// [in] \param tr  The trigger record structure to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the structure is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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) *reason = kReservedBitsNotZero;
-               return false;
+               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) *reason = kParticleSignBitsNotValid;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kParticleSignBitsNotValid;
+                       reasonCount++;
+               }
+               result = false;
        }
 
        // Check that fHit[i] is nil if the corresponding bit in the
@@ -838,35 +1122,51 @@ bool AliHLTMUONUtils::IntegrityOk(
             ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
           )
        {
-               if (reason != NULL) *reason = kHitNotMarkedAsNil;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHitNotMarkedAsNil;
+                       reasonCount++;
+               }
+               result = false;
        }
 
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONTriggerRecordsBlockStruct& block,
                WhyNotValid* reason,
-               AliHLTUInt32_t* recordNum
+               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.
        /// [in] \param block  The trigger record data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
-       /// [out] \param recordNum  If this is not NULL, then it will be filled with
-       ///      the number of the trigger record that had a problem. This value will
-       ///      only contain a valid value if 'reason' contains one of:
+       /// [out] \param 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.
+       /// [out] \param 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
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
        
        const AliHLTMUONTriggerRecordStruct* triggerRecord =
                reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
@@ -875,12 +1175,16 @@ bool AliHLTMUONUtils::IntegrityOk(
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = triggerRecord[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (id == triggerRecord[j].fId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateIDs;
-                               return false;
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
                        }
                }
        }
@@ -888,32 +1192,152 @@ bool AliHLTMUONUtils::IntegrityOk(
        // Check integrity of individual trigger records.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(triggerRecord[i], reason))
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(triggerRecord[i], reason+reasonCount, filledCount))
                {
-                       if (recordNum != NULL) *recordNum = i;
-                       return false;
+                       // 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 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.
+       /// [in] \param trigInfo  The trigger record debug information structure to check.
+       /// [out] \param 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.
+       /// [in/out] \param 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] >= 0 or trigInfo.fDetElemId[0] == -1) or
+            not (trigInfo.fDetElemId[1] >= 0 or trigInfo.fDetElemId[1] == -1) or
+            not (trigInfo.fDetElemId[2] >= 0 or trigInfo.fDetElemId[2] == -1) or
+            not (trigInfo.fDetElemId[3] >= 0 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
+               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.
-       /// [in] \param block  The trigger record debugging information data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [in] \param block  The trigger record debugging information data block
+       ///      to check.
+       /// [out] \param 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.
+       /// [out] \param 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.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
-       return true;
+       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;
 }
 
 
@@ -937,36 +1361,157 @@ bool AliHLTMUONUtils::IntegrityOk(
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONRecHitsBlockStruct& block,
-               WhyNotValid* reason
+               WhyNotValid* reason,
+               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.
        /// [in] \param block  The reconstructed hits data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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 data and false otherwise.
        
-       if (not HeaderOk(block, reason)) return false;
-       return true;
+       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;
+                       }
+               }
+       }
+       
+       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.
+       /// [in] \param cluster  The cluster structure to check.
+       /// [out] \param 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.
+       /// [in/out] \param 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 >= 0 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.
+       // between 1 and the maximum number of channels per DDL.
+       // 1<<17 taken from the 11 bits MANU ID + 6 bits channel address.
+       if (cluster.fNchannels < 1 or (1<<17) < cluster.fNchannels)
+       {
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kInvalidChannelCount;
+                       reasonCount++;
+               }
+               result = false;
+       }
+
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONClustersBlockStruct& block,
-               WhyNotValid* reason
+               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.
+       /// dHLT internal clusters data block is OK and returns true in that case.
        /// [in] \param block  The clusters data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [out] \param 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
+       ///        - kInvalidChannelCount
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
 
        const AliHLTMUONClusterStruct* cluster =
                reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
@@ -975,64 +1520,305 @@ bool AliHLTMUONUtils::IntegrityOk(
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = cluster[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (id == cluster[j].fId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateIDs;
-                               return false;
+                               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 true;
+       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.
+       /// [in] \param cluster  The channel structure to check.
+       /// [out] \param 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.
+       /// [in/out] \param 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
+               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.
-       /// [in] \param block  The ADC channels data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
+       /// dHLT internal channels data block is OK and returns true in that case.
+       /// [in] \param block  The channels data block to check.
+       /// [out] \param 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.
+       /// [out] \param 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.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
-       return true;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
+       const AliHLTMUONChannelStruct* channel =
+               reinterpret_cast<const AliHLTMUONChannelStruct*>(&block + 1);
+       
+       // Check if any cluster ID is duplicated.
+       for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
+       {
+               AliHLTInt32_t id = channel[i].fClusterId;
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
+               {
+                       if (id == channel[j].fClusterId)
+                       {
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
+                       }
+               }
+       }
+
+       // 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
+               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.
        /// [in] \param track  The track structure to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the structure is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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 ((track.fFlags & 0x3FFFFFF0) != 0)
        {
-               if (reason != NULL) *reason = kReservedBitsNotZero;
-               return false;
+               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) *reason = kParticleSignBitsNotValid;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kParticleSignBitsNotValid;
+                       reasonCount++;
+               }
+               result = false;
        }
 
        // Check that fHit[i] is nil if the corresponding bit in the
@@ -1045,36 +1831,79 @@ bool AliHLTMUONUtils::IntegrityOk(
             ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
           )
        {
-               if (reason != NULL) *reason = kHitNotMarkedAsNil;
-               return false;
+               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;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONMansoTracksBlockStruct& block,
                WhyNotValid* reason,
-               AliHLTUInt32_t* recordNum
+               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.
+       /// dHLT internal Manso track data block is OK and returns true in that case.
        /// [in] \param block  The Manso track data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
-       /// [out] \param recordNum  If this is not NULL, then it will be filled with
-       ///      the number of the track that had a problem. This value will only
-       ///      contain a valid value if 'reason' contains one of:
+       /// [out] \param 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.
+       /// [out] \param 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
+       /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
+       ///      was set and is valid or not.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
-
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
+       
        const AliHLTMUONMansoTrackStruct* track =
                reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
        
@@ -1082,51 +1911,143 @@ bool AliHLTMUONUtils::IntegrityOk(
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = track[i].fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (id == track[j].fId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateIDs;
-                               return false;
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
                        }
                }
        }
-
-       // Check that the tracks have integrity.
+       
+       // Check that all the tracks have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(track[i], reason))
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(track[i], reason+reasonCount, filledCount))
                {
-                       if (recordNum != NULL) *recordNum = i;
-                       return false;
+                       // 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;
+}
 
-       return true;
+
+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.
+       /// [in] \param track  The track candidate structure to check.
+       /// [out] \param 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.
+       /// [in/out] \param 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* 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.
+       /// dHLT internal Manso candidates data block is OK and returns true in
+       /// that case.
        /// [in] \param block  The Manso track candidate data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
-       /// [out] \param recordNum  If this is not NULL, then it will be filled with
-       ///      the number of the track candidate that had a problem. This value will
-       ///      only contain a valid value if 'reason' contains one of:
+       /// [out] \param 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.
+       /// [out] \param 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.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
 
        const AliHLTMUONMansoCandidateStruct* candidate =
                reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
@@ -1135,82 +2056,136 @@ bool AliHLTMUONUtils::IntegrityOk(
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = candidate[i].fTrack.fId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (id == candidate[j].fTrack.fId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateIDs;
-                               return false;
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateIDs;
+                                       reasonCount++;
+                               }
+                               result = false;
                        }
                }
        }
        
-       // Check that the tracks have integrity.
+       // Check that all the track candidates have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(candidate[i].fTrack, reason))
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(candidate[i], reason+reasonCount, filledCount))
                {
-                       if (recordNum != NULL) *recordNum = i;
-                       return false;
+                       // 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 AliHLTMUONTrackDecisionStruct& decision,
-               WhyNotValid* reason
+               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.
        /// [in] \param decision  The trigger decision structure to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the structure is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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 & 0xFFFFFFFC) != 0)
        {
-               if (reason != NULL) *reason = kReservedBitsNotZero;
-               return false;
+               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) *reason = kPtValueNotValid;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kPtValueNotValid;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONSinglesDecisionBlockStruct& block,
                WhyNotValid* reason,
-               AliHLTUInt32_t* recordNum
+               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.
+       /// dHLT internal single track trigger decision data block is OK and returns
+       /// true in that case.
        /// [in] \param block  The single track trigger decision data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
-       /// [out] \param recordNum  If this is not NULL, then it will be filled with
-       ///      the number of the trigger decisions that had a problem. This value will
-       ///      only contain a valid value if 'reason' contains one of:
+       /// [out] \param 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.
+       /// [out] \param 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.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
        
        const AliHLTMUONTrackDecisionStruct* decision =
                reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
@@ -1219,12 +2194,16 @@ bool AliHLTMUONUtils::IntegrityOk(
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
                AliHLTInt32_t id = decision[i].fTrackId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (id == decision[j].fTrackId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateTriggers;
-                               return false;
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateTriggers;
+                                       reasonCount++;
+                               }
+                               result = false;
                        }
                }
        }
@@ -1232,50 +2211,95 @@ bool AliHLTMUONUtils::IntegrityOk(
        // Check that the trigger bits for each track have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(decision[i], reason))
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
                {
-                       if (recordNum != NULL) *recordNum = i;
-                       return false;
+                       // 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,
-               WhyNotValid* reason
+               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.
        /// [in] \param decision  The trigger decision structure to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the structure is not valid, if and
-       ///      only if a problem is found with the data.
+       /// [out] \param 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.
+       /// [in/out] \param 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)
+          )
+       {
+               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) *reason = kReservedBitsNotZero;
-               return false;
+               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) *reason = kPairTrackIdsAreIdentical;
-               return false;
+               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) *reason = kMassValueNotValid;
-               return false;
+               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.
@@ -1283,42 +2307,63 @@ bool AliHLTMUONUtils::IntegrityOk(
        AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
        if (lowPtCount > 2)
        {
-               if (reason != NULL) *reason = kLowPtCountInvalid;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kLowPtCountInvalid;
+                       reasonCount++;
+               }
+               result = false;
        }
        if (highPtCount > 2)
        {
-               if (reason != NULL) *reason = kHighPtCountInvalid;
-               return false;
+               if (reason != NULL and reasonCount < maxCount)
+               {
+                       reason[reasonCount] = kHighPtCountInvalid;
+                       reasonCount++;
+               }
+               result = false;
        }
        
-       return true;
+       return result;
 }
 
 
 bool AliHLTMUONUtils::IntegrityOk(
                const AliHLTMUONPairsDecisionBlockStruct& block,
                WhyNotValid* reason,
-               AliHLTUInt32_t* recordNum
+               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.
+       /// dHLT internal track pair trigger decision data block is OK and returns
+       /// true in that case.
        /// [in] \param block  The track pair trigger decision data block to check.
-       /// [out] \param reason  If this is not NULL, then it will be filled with
-       ///      the reason code describing why the data block is not valid, if and
-       ///      only if a problem is found with the data.
-       /// [out] \param recordNum  If this is not NULL, then it will be filled with
-       ///      the number of the trigger decisions that had a problem. This value will
-       ///      only contain a valid value if 'reason' contains one of:
+       /// [out] \param 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.
+       /// [out] \param 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.
+       /// [in/out] \param 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.
        
-       if (not HeaderOk(block, reason)) return false;
+       AliHLTUInt32_t maxCount = reasonCount;
+       bool result = HeaderOk(block, reason, reasonCount);
 
        const AliHLTMUONPairDecisionStruct* decision =
                reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
@@ -1328,12 +2373,16 @@ bool AliHLTMUONUtils::IntegrityOk(
        {
                AliHLTInt32_t ta = decision[i].fTrackAId;
                AliHLTInt32_t tb = decision[i].fTrackBId;
-               for (AliHLTUInt32_t j = i+1; i < block.fHeader.fNrecords; j++)
+               for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
                {
                        if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
                        {
-                               if (reason != NULL) *reason = kFoundDuplicateTriggers;
-                               return false;
+                               if (reason != NULL and reasonCount < maxCount)
+                               {
+                                       reason[reasonCount] = kFoundDuplicateTriggers;
+                                       reasonCount++;
+                               }
+                               result = false;
                        }
                }
        }
@@ -1341,12 +2390,21 @@ bool AliHLTMUONUtils::IntegrityOk(
        // Check that the trigger bits for each track pair have integrity.
        for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
        {
-               if (not IntegrityOk(decision[i], reason))
+               AliHLTUInt32_t filledCount = maxCount - reasonCount;
+               if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
                {
-                       if (recordNum != NULL) *recordNum = i;
-                       return false;
+                       // 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;
 }
+
index 648d906623ff49ca4444698b16a56210db6b917b..a2e0764c32cf1af477723cedf1ba4dcddf6eca14 100644 (file)
@@ -8,7 +8,7 @@
 ///
 /// @file   AliHLTMUONUtils.h
 /// @author Artur Szostak <artursz@iafrica.com>
-/// @date   
+/// @date   17 May 2007
 /// @brief  Class containing various dimuon HLT utility routines and macros.
 ///
 
 extern "C" {
 struct AliHLTMUONTriggerRecordStruct;
 struct AliHLTMUONTriggerRecordsBlockStruct;
+struct AliHLTMUONTrigRecInfoStruct;
 struct AliHLTMUONTrigRecsDebugBlockStruct;
 struct AliHLTMUONTriggerChannelsBlockStruct;
 struct AliHLTMUONRecHitsBlockStruct;
+struct AliHLTMUONClusterStruct;
 struct AliHLTMUONClustersBlockStruct;
+struct AliHLTMUONChannelStruct;
 struct AliHLTMUONChannelsBlockStruct;
 struct AliHLTMUONMansoTrackStruct;
 struct AliHLTMUONMansoTracksBlockStruct;
+struct AliHLTMUONMansoCandidateStruct;
 struct AliHLTMUONMansoCandidatesBlockStruct;
 struct AliHLTMUONTrackDecisionStruct;
 struct AliHLTMUONSinglesDecisionBlockStruct;
@@ -268,6 +272,36 @@ public:
                AliHLTInt32_t ddl = SpecToDDLNumber(spec);
                return (0 <= ddl and ddl <= 19);
        }
+
+       /**
+        * Returns true if the given specification is in principle valid.
+        * It checks if the bits that should be zero are indeed zero.
+        */
+       static bool IsSpecValid(AliHLTUInt32_t spec)
+       {
+               AliHLTUInt32_t mask = ~((1 << 22) - 1);  // First 22 bits indicate DDL number.
+               return (spec & mask) == 0x0;
+       }
+
+       /**
+        * Returns true if the data specification indicates the data block contains
+        * information generated from a trigger DDL or data fragments thereof.
+        */
+       static bool ContainsDataFromTrigger(AliHLTUInt32_t spec)
+       {
+               AliHLTUInt32_t mask = ((1 << 22) - 1) & ~((1 << 20) - 1);
+               return (spec & mask) != 0x0;
+       }
+
+       /**
+        * Returns true if the data specification indicates the data block contains
+        * information generated from a tracker DDL or data fragments thereof.
+        */
+       static bool ContainsDataFromTracker(AliHLTUInt32_t spec)
+       {
+               AliHLTUInt32_t mask = ((1 << 20) - 1);
+               return (spec & mask) != 0x0;
+       }
        
        /**
        * Parses the string containing the type name of a dHLT data block and
@@ -277,7 +311,7 @@ public:
        *      is invalid.
        */
        static AliHLTMUONDataBlockType ParseCommandLineTypeString(const char* type);
-
+       
        /**
         * These codes indicate the reason why a data block failed its
         * validity check.
@@ -287,16 +321,32 @@ public:
                kNoReason,   ///< There was no reason for failure.
                kHeaderContainsWrongType,  ///< The common header contains an incorrect type ID.
                kHeaderContainsWrongRecordWidth,  ///< The common header contains an incorrect data record width.
+               kInvalidIdValue,  ///< The structure identifier does not have a valid value.
+               kInvalidTriggerIdValue,  ///< The trigger structure identifier does not have a valid value.
+               kInvalidTrackIdValue,  ///< The track structure identifier does not have a valid value.
                kReservedBitsNotZero,  ///< Reserved bits have not been set to zero.
                kParticleSignBitsNotValid,  ///< The particle sign bits are not a valid value.
                kHitNotMarkedAsNil,  ///< A hit was marked as not found, but the corresponding hit structure was not set to nil.
-               kFoundDuplicateIDs,  ///< Found duplicate identifiers, but they should all be unique.
+               kInvalidDetElementNumber,  ///< An invalid detector element ID was found.
+               kHitIsNil,  ///< The hit cannot be set to a nil value.
+               kInvalidChannelCount,  ///< The number of channels indicated is zero or outside the valid range.
+               kInvalidBusPatchId,  ///< The bus patch ID is outside the valid range.
+               kInvalidManuId,  ///< The MANU ID is outside the valid range.
+               kInvalidChannelAddress,  ///< The MANU channel address is outside the valid range.
+               kInvalidSignal,  ///< The ADC signal value is outside the valid range.
+               kDataWordDifferent, ///< The raw data word is different from the unpacked values.
+               kChiSquareInvalid,  ///< The chi squared value must be a positive value or -1 indicating a fitting error.
+               kMomentumVectorNotZero, ///< The chi sqaured value is set to -1, but momentum vector not zero.
+               kRoiRadiusInvalid, ///< The region of interest radius is invalid.
+               kHitNotWithinRoi, ///< A tracks hit is not within the corresponding region of interest.
                kPtValueNotValid,  ///< The pT value is not positive nor -1 indicating an invalid value.
-               kFoundDuplicateTriggers,  ///< Found duplicate trigger decisions.
                kPairTrackIdsAreIdentical,  ///< The track IDs of the track pair are identical.
                kMassValueNotValid,  ///< The invariant mass value is not positive nor -1 indicating an invalid value.
                kLowPtCountInvalid,  ///< The low pT trigger count is greater than 2, which is invalid.
-               kHighPtCountInvalid  ///< The high pT trigger count is greater than 2, which is invalid.
+               kHighPtCountInvalid,  ///< The high pT trigger count is greater than 2, which is invalid.
+               kFoundDuplicateIDs,  ///< Found duplicate identifiers, but they should all be unique.
+               kFoundDuplicateHits,  ///< Found duplicate hits.
+               kFoundDuplicateTriggers  ///< Found duplicate trigger decisions.
        };
        
        /**
@@ -310,68 +360,673 @@ public:
         */
        static const char* FailureReasonToMessage(WhyNotValid reason);
 
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the trigger records data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONTriggerRecordsBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the trigger debug information data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       // this method is deprecated.
+       static bool HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the reconstructed hits data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONRecHitsBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the clusters data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONClustersBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the channels data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONChannelsBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the Manso tracks data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the Manso candidates data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the single tracks dHLT trigger decision data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+       
+       /**
+        * Method used to check if the header information corresponds to the
+        * supposed type of the track pairs dHLT trigger decision data block.
+        * This method will return either kHeaderContainsWrongType or
+        * kHeaderContainsWrongRecordWidth as the reason code.
+        * [in]  \param block  The data block to check.
+        * [out] \param reason  If this is not NULL, then the variable pointed to
+        *      by this pointer will be filled with the reason code describing why
+        *      the header is not valid, if and only if a problem is found with
+        *      the data.
+        * \returns  true if there is no problem with the header and false otherwise.
+        */
+       static bool HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block, WhyNotValid* reason = NULL)
+       {
+               AliHLTUInt32_t count = 1;
+               return HeaderOk(block, reason, count);
+       }
+
        /**
         * Methods used to check if the header information corresponds to the
         * supposed type of the data block.
-        * If the 'reason' parameter is not NULL then these methods will fill the
-        * memory pointed to by reason with a code describing why the header is
-        * not valid, if and only if a problem is found with the data.
-        * These methods will return either kHeaderContainsWrongType or
-        * kHeaderContainsWrongRecordWidth as the reason.
-        */
-       static bool HeaderOk(const AliHLTMUONTriggerRecordsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONTrigRecsDebugBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONRecHitsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONClustersBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONChannelsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONMansoTracksBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONMansoCandidatesBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONSinglesDecisionBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool HeaderOk(const AliHLTMUONPairsDecisionBlockStruct& block, WhyNotValid* reason = NULL);
+        * If the 'reason' parameter should point to an array which will store
+        * the reason codes indicating the problems with the data block.
+        * The 'reasonCount' parameter should initialy contain the number of
+        * elements that can be stored in reason. When the method exits it will
+        * store the number of elements in the 'reason' array actually filled.
+        */
+       static bool HeaderOk(
+                       const AliHLTMUONTriggerRecordsBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONTrigRecsDebugBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONRecHitsBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONClustersBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONChannelsBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONMansoTracksBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONMansoCandidatesBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONSinglesDecisionBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool HeaderOk(
+                       const AliHLTMUONPairsDecisionBlockStruct& block,
+                       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.
+        * [in] \param tr  The trigger record structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONTriggerRecordStruct& tr,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(tr, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The trigger record data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the trigger record that had a problem. This value will
+        *      only contain a valid value if the method RecordNumberWasSet(*reason)
+        *      returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONTriggerRecordsBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param trigInfo  The trigger record debug information structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONTrigRecInfoStruct& trigInfo,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(trigInfo, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The trigger record debugging information data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the trigger record debug information structure that had
+        *      a problem. This value will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONTrigRecsDebugBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       // this method is deprecated.
+       static bool IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
+       
+       /**
+        * 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.
+        * [in] \param block  The reconstructed hits data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONRecHitsBlockStruct& block,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, count);
+       }
+       
+       /**
+        * This method is used to check more extensively if the integrity of the
+        * cluster data structure is OK and returns true in that case.
+        * [in] \param cluster  The cluster structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONClusterStruct& cluster,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(cluster, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The clusters data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the cluster structure that had a problem. This value
+        *      will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONClustersBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * This method is used to check more extensively if the integrity of the
+        * channel data structure is OK and returns true in that case.
+        * [in] \param cluster  The channel structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONChannelStruct& channel,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(channel, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The ADC channels data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the channel structure that had a problem. This value
+        *      will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONChannelsBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * This method is used to check more extensively if the integrity of the
+        * Manso track structure is OK and returns true in that case.
+        * [in] \param track  The Manso track structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoTrackStruct& track,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(track, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The Manso track data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the Manso track structure that had a problem.
+        *      This value will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoTracksBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param candidate  The Manso track candidate structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoCandidateStruct& candidate,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(candidate, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The Manso track candidate data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the Manso track candidate structure that had a problem.
+        *      This value will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoCandidatesBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param decision  The trigger decision structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONTrackDecisionStruct& decision,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(decision, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The single track trigger decision data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the single track trigger decision structure that had
+        *      a problem. This value will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONSinglesDecisionBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param decision  The trigger decision structure to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the structure is not valid, if and
+        *      only if a problem is found with the data.
+        * \returns  true if there is no problem with the structure and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONPairDecisionStruct& decision,
+                       WhyNotValid* reason = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(decision, reason, count);
+       }
+       
+       /**
+        * 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.
+        * [in] \param block  The track pair trigger decision data block to check.
+        * [out] \param reason  If this is not NULL, then it will be filled with
+        *      the reason code describing why the data block is not valid, if and
+        *      only if a problem is found with the data.
+        * [out] \param recordNum  If this is not NULL, then it will be filled with
+        *      the number of the track pairs trigger decision structure that had
+        *      a problem. This value will only contain a valid value if the method
+        *      RecordNumberWasSet(*reason) returns true. Thus, 'reason' must be set.
+        * \returns  true if there is no problem with the data and false otherwise.
+        */
+       static bool IntegrityOk(
+                       const AliHLTMUONPairsDecisionBlockStruct& block,
+                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+               )
+       {
+               AliHLTUInt32_t count = 1;
+               return IntegrityOk(block, reason, recordNum, count);
+       }
 
        /**
         * Methods used to check more extensively if the integrity of various
         * types of data blocks are Ok and returns true in that case.
         * These can be slow and should generally only be used for debugging.
+        * The methods are able to return multiple reasons for the problems related
+        * to the data block under test.
         */
-       static bool IntegrityOk(const AliHLTMUONTriggerRecordStruct& tr, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(
+                       const AliHLTMUONTriggerRecordStruct& tr,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
        
        static bool IntegrityOk(
                        const AliHLTMUONTriggerRecordsBlockStruct& block,
-                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONTrigRecInfoStruct& trigInfo,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONTrigRecsDebugBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONRecHitsBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONClusterStruct& cluster,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONClustersBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONChannelStruct& channel,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONChannelsBlockStruct& block,
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoTrackStruct& track,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
                );
-               
-       static bool IntegrityOk(const AliHLTMUONTrigRecsDebugBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool IntegrityOk(const AliHLTMUONTriggerChannelsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool IntegrityOk(const AliHLTMUONRecHitsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool IntegrityOk(const AliHLTMUONClustersBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool IntegrityOk(const AliHLTMUONChannelsBlockStruct& block, WhyNotValid* reason = NULL);
-       static bool IntegrityOk(const AliHLTMUONMansoTrackStruct& track, WhyNotValid* reason = NULL);
        
        static bool IntegrityOk(
                        const AliHLTMUONMansoTracksBlockStruct& block,
-                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
+               );
+       
+       static bool IntegrityOk(
+                       const AliHLTMUONMansoCandidateStruct& candidate,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
                );
        
        static bool IntegrityOk(
                        const AliHLTMUONMansoCandidatesBlockStruct& block,
-                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
                );
        
-       static bool IntegrityOk(const AliHLTMUONTrackDecisionStruct& decision, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(
+                       const AliHLTMUONTrackDecisionStruct& decision,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
        
        static bool IntegrityOk(
                        const AliHLTMUONSinglesDecisionBlockStruct& block,
-                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
                );
        
-       static bool IntegrityOk(const AliHLTMUONPairDecisionStruct& decision, WhyNotValid* reason = NULL);
+       static bool IntegrityOk(
+                       const AliHLTMUONPairDecisionStruct& decision,
+                       WhyNotValid* reason, AliHLTUInt32_t& reasonCount
+               );
        
        static bool IntegrityOk(
                        const AliHLTMUONPairsDecisionBlockStruct& block,
-                       WhyNotValid* reason = NULL, AliHLTUInt32_t* recordNum = NULL
+                       WhyNotValid* reason, AliHLTUInt32_t* recordNum,
+                       AliHLTUInt32_t& reasonCount
                );
+       
+       /**
+        * 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.
+        */
+       static bool RecordNumberWasSet(WhyNotValid reason);
 
 private:
        // Should never have to create or destroy this object.
index c40a7d0452b6348f00b29eacc63380d972f78581..b5f04278536b7f8affbbd49a6f09e7c3fb0f713d 100644 (file)
@@ -55,5 +55,6 @@
 #pragma link C++ class AliHLTMUONEvent+;
 #pragma link C++ class AliHLTMUONRootifierComponent+;
 #pragma link C++ class AliHLTMUONEmptyEventFilterComponent+;
+#pragma link C++ class AliHLTMUONDataCheckerComponent+;
 
 #endif // __CINT__
index 341d388a95b61801cdd4fd0b9e114a00849857bf..29d9ea8e68ab04f376b254ae68708258eaa60c22 100644 (file)
@@ -31,6 +31,7 @@
 #include "AliHLTMUONMansoTrackerFSMComponent.h"
 #include "AliHLTMUONDecisionComponent.h"
 #include "AliHLTMUONEmptyEventFilterComponent.h"
+#include "AliHLTMUONDataCheckerComponent.h"
 #include "AliRunLoader.h"
 
 // The single global instance of the dimuon HLT agent.
@@ -121,6 +122,7 @@ int AliHLTMUONAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
        pHandler->AddComponent(new AliHLTMUONMansoTrackerFSMComponent);
        pHandler->AddComponent(new AliHLTMUONDecisionComponent);
        pHandler->AddComponent(new AliHLTMUONEmptyEventFilterComponent);
+       pHandler->AddComponent(new AliHLTMUONDataCheckerComponent);
        return 0;
 }
 
index 1ee6a7720847656f433c9ad5b2a5d2017f41293c..05662229c475459ca65a516d72705e76a9864b38 100644 (file)
@@ -373,9 +373,7 @@ int AliHLTMUONHitReconstructorComponent::DoEvent(
                
                if (fDDL != -1)
                {
-                       bool ddl[22];
-                       AliHLTMUONUtils::UnpackSpecBits(blocks[n].fSpecification, ddl);
-                       if (not ddl[fDDL])
+                       if (AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification) != fDDL)
                        {
                                HLTWarning("Received raw data from an unexpected DDL.");
                        }
@@ -571,8 +569,7 @@ int AliHLTMUONHitReconstructorComponent::ReadLookUpTable(const char* lutFileName
 
 int AliHLTMUONHitReconstructorComponent::ReadCDB(const char* cdbPath, Int_t run)
 {
-       // Reads LUT from CDB.
-       // TODO: merge this with CreateHitRecoLookupTables.C, make this static and use in the macro for example.
+       /// Reads LUT from CDB.
 
        assert( fLut == NULL );
        assert( fLutSize == 0 );
@@ -582,43 +579,11 @@ int AliHLTMUONHitReconstructorComponent::ReadCDB(const char* cdbPath, Int_t run)
        AliHLTMUONHitRecoLutRow lut;
        AliHLTUInt32_t iEntry = 0;
        
-       Bool_t warn = kFALSE;
-       
-       AliCDBManager* cdbManager = AliCDBManager::Instance();
-       if (cdbManager == NULL)
-       {
-               HLTError("CDB manager instance does not exist.");
-               return -EIO;
-       }
-       
-       const char* cdbPathUsed = "unknown (not set)";
-       if (cdbPath != NULL)
-       {
-               cdbManager->SetDefaultStorage(cdbPath);
-               cdbPathUsed = cdbPath;
-       }
-       else
-       {
-               AliCDBStorage* store = cdbManager->GetDefaultStorage();
-               if (store != NULL) cdbPathUsed = store->GetURI().Data();
-       }
-       
-       if (run != -1) cdbManager->SetRun(run);
-       Int_t runUsed = cdbManager->GetRun();
-       
-       if (not AliMpCDB::LoadDDLStore(warn))
-       {
-               HLTError("Failed to load DDL store specified for CDB path '%s' and run no. %d",
-                       cdbPathUsed, runUsed
-               );
-               return -ENOENT;
-       }
+       int result = FetchMappingStores(cdbPath, run);
+       // Error message already generated in FetchMappingStores.
+       if (result != 0) return result;
        AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
-       if (ddlStore == NULL)
-       {
-               HLTError("Could not find DDL store instance.");
-               return -EIO;
-       }
+       
        AliMpSegmentation* mpSegFactory = AliMpSegmentation::Instance();
        if (mpSegFactory == NULL)
        {
index 4853e780d9271d14458178e35ce7bea7da8f800f..82cbbdc4a52aa55c7342256f0780a9047e14b6fd 100644 (file)
@@ -43,7 +43,7 @@ public:
        virtual AliHLTComponent* Spawn();
        
        /**
-        * Generates a ASCII text file containing the lookup table (LUT) from
+        * Generates an ASCII text file containing the lookup table (LUT) from
         * the CDB, which can be used for the hit reconstructor component later.
         * @param ddl  Must be the DDL for which to generate the DDL,
         *             in the range [12..19].
@@ -61,7 +61,7 @@ protected:
        
        // Protected functions to implement AliHLTComponent's interface.
        // These functions provide initialization as well as the actual processing
-       // capabilities of the component. 
+       // capabilities of the component.
 
        virtual int DoInit(int argc, const char** argv);
        virtual int DoDeinit();
@@ -79,7 +79,9 @@ protected:
 private:
 
        // Do not allow copying of this class.
+       /// Not implemented.
        AliHLTMUONHitReconstructorComponent(const AliHLTMUONHitReconstructorComponent& /*obj*/);
+       /// Not implemented.
        AliHLTMUONHitReconstructorComponent& operator = (const AliHLTMUONHitReconstructorComponent& /*obj*/);
        
        void FreeMemory();
index 1ec60126fe18e6e8d98f8430a6f34fe6386a1ec1..dd84ecfb1850e73615083ffe901b74bcc79c1f41 100644 (file)
@@ -391,9 +391,7 @@ int AliHLTMUONTriggerReconstructorComponent::DoEvent(
                
                if (fDDL != -1)
                {
-                       bool ddl[22];
-                       AliHLTMUONUtils::UnpackSpecBits(blocks[n].fSpecification, ddl);
-                       if (not ddl[fDDL])
+                       if (AliHLTMUONUtils::SpecToDDLNumber(blocks[n].fSpecification) != fDDL)
                        {
                                HLTWarning("Received raw data from an unexpected DDL.");
                        }
@@ -522,43 +520,11 @@ int AliHLTMUONTriggerReconstructorComponent::ReadCDB(const char* cdbPath, Int_t
                return -EINVAL;
        }
 
-       Bool_t warn = kFALSE;
-       
-       AliCDBManager* cdbManager = AliCDBManager::Instance();
-       if (cdbManager == NULL)
-       {
-               HLTError("CDB manager instance does not exist.");
-               return -EIO;
-       }
-       
-       const char* cdbPathUsed = "unknown (not set)";
-       if (cdbPath != NULL)
-       {
-               cdbManager->SetDefaultStorage(cdbPath);
-               cdbPathUsed = cdbPath;
-       }
-       else
-       {
-               AliCDBStorage* store = cdbManager->GetDefaultStorage();
-               if (store != NULL) cdbPathUsed = store->GetURI().Data();
-       }
-       
-       if (run != -1) cdbManager->SetRun(run);
-       Int_t runUsed = cdbManager->GetRun();
-       
-       if (not AliMpCDB::LoadDDLStore(warn))
-       {
-               HLTError("Failed to load DDL store specified for CDB path '%s' and run no. %d",
-                       cdbPathUsed, runUsed
-               );
-               return -ENOENT;
-       }
+       int result = FetchMappingStores(cdbPath, run);
+       // Error message already generated in FetchMappingStores.
+       if (result != 0) return result;
        AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
-       if (ddlStore == NULL)
-       {
-               HLTError("Could not find DDL store instance.");
-               return -EIO;
-       }
+       
        AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
        if (segmentation == NULL)
        {
index 266bd82b66e4dd23f3186fd6f80b4bd0e9cb50dc..440f371fcf8d0959f4a31c576b504f211e3c82a0 100644 (file)
@@ -79,7 +79,9 @@ protected:
 private:
 
        // Do not allow copying of this class.
+       /// Not implemented.
        AliHLTMUONTriggerReconstructorComponent(const AliHLTMUONTriggerReconstructorComponent& /*obj*/);
+       /// Not implemented.
        AliHLTMUONTriggerReconstructorComponent& operator = (const AliHLTMUONTriggerReconstructorComponent& /*obj*/);
 
        int ReadLookUpTable(const char* lutpath);
index 01e431a6f8bf6b0cfd91525dd5a52050c5fc10ca..0befa32a39f0f8a2683591557fa83b03d0fb46f7 100644 (file)
@@ -93,6 +93,8 @@ using std::endl;
  * @param lutDir  This is the directory in which the LUTs can be found.
  *      If it is set to "CDB" (case sensitive) then the LUTs will be loaded from
  *      CDB instead. The default behaviour is to read from the local CDB store.
+ * @param checkData  A flag for indicating if the event data should be checked
+ *      for consistency with the AliHLTMUONDataCheckerComponent.
  */
 void RunChain(
                const char* chainType = "full",
@@ -101,7 +103,8 @@ void RunChain(
                const char* output = "bin",
                const char* dataSource = "sim",
                const char* logLevel = "normal",
-               const char* lutDir = "CDB"
+               const char* lutDir = "CDB",
+               bool checkData = false
        )
 {
        // Setup the CDB default storage and run number if nothing was set.
@@ -406,6 +409,14 @@ void RunChain(
                // Add the trigger decision component if it was enabled.
                sources += " decision";
        }
+       
+       // Build the data checker component if so requested.
+       if (checkData)
+       {
+               AliHLTConfiguration checker("checker", "MUONDataChecker", sources, "-warn_on_unexpected_block");
+               sources = "checker";
+       }
+       
        if (useRootWriter)
        {
                AliHLTConfiguration convert("convert", "MUONRootifier", sources, "");
diff --git a/HLT/MUON/utils/AliHLTMUONDataCheckerComponent.cxx b/HLT/MUON/utils/AliHLTMUONDataCheckerComponent.cxx
new file mode 100644 (file)
index 0000000..ceab784
--- /dev/null
@@ -0,0 +1,3623 @@
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * All rights reserved.                                                   *
+ *                                                                        *
+ * Primary Authors:                                                       *
+ *   Artur Szostak <artursz@iafrica.com>                                  *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id: $ */
+
+///
+/// @file   AliHLTMUONDataCheckerComponent.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   2007-12-12
+/// @brief  Implementation of the dHLT data integrity checker component.
+///
+/// This component is used to check the data integrity of dHLT raw internal data
+/// blocks. If there are any problems found then an appropriate error message is
+/// logged.
+///
+
+#include "AliHLTMUONDataCheckerComponent.h"
+#include "AliHLTMUONConstants.h"
+#include "AliHLTLogging.h"
+#include "AliHLTSystem.h"
+#include "AliHLTDefinitions.h"
+#include "AliRawDataHeader.h"
+#include "AliMUONConstants.h"
+#include "AliMUONTrackerDDLDecoder.h"
+#include "AliMUONTrackerDDLDecoderEventHandler.h"
+#include "AliMUONTriggerDDLDecoder.h"
+#include "AliMUONTriggerDDLDecoderEventHandler.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEStore.h"
+#include "AliMpDEManager.h"
+#include "AliMpBusPatch.h"
+#include "AliMpDetElement.h"
+#include "AliMpSegmentation.h"
+#include "AliMpVSegmentation.h"
+#include "AliMpPad.h"
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+#include <cerrno>
+#include <cassert>
+
+
+namespace
+{
+       /**
+        * Routine to check if at least one corresponding DDL has been marked
+        * for a particular chamber.
+        */
+       bool ChamberMarkedInDDLList(AliHLTInt32_t chamber, bool ddl[22])
+       {
+               if (chamber < 0 or chamber > 21) return false;
+               switch (chamber)
+               {
+               case 0:  return ddl[0] or ddl[1];
+               case 1:  return ddl[2] or ddl[3];
+               case 2:  return ddl[4] or ddl[5];
+               case 3:  return ddl[6] or ddl[7];
+               case 4:  return ddl[8] or ddl[9] or ddl[10] or ddl[11];
+               case 5:  return ddl[8] or ddl[9] or ddl[10] or ddl[11];
+               case 6:  return ddl[12] or ddl[13];
+               case 7:  return ddl[14] or ddl[15];
+               case 8:  return ddl[16] or ddl[17];
+               case 9:  return ddl[18] or ddl[19];
+               case 10: return ddl[20] or ddl[21];
+               case 11: return ddl[20] or ddl[21];
+               case 12: return ddl[20] or ddl[21];
+               case 13: return ddl[20] or ddl[21];
+               default: return false;
+               }
+       }
+
+} // end of namespace
+
+
+ClassImp(AliHLTMUONDataCheckerComponent)
+
+
+AliHLTMUONDataCheckerComponent::AliHLTMUONDataCheckerComponent() :
+       AliHLTMUONProcessor(),
+       fIgnoreType(false),
+       fIgnoreSpec(false),
+       fDontForward(false),
+       fFilterBadBlocks(false),
+       fNoGlobalChecks(false),
+       fWarnForUnexpecedBlock(false)
+{
+       /// Default constructor.
+}
+
+
+AliHLTMUONDataCheckerComponent::~AliHLTMUONDataCheckerComponent()
+{
+       /// Default destructor.
+}
+
+const char* AliHLTMUONDataCheckerComponent::GetComponentID()
+{
+       /// Inherited from AliHLTComponent. Returns the component ID.
+       
+       return AliHLTMUONConstants::DataCheckerComponentId();
+}
+
+
+void AliHLTMUONDataCheckerComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
+{
+       /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
+       /// At the moment this list is "any data type" since it is not known before
+       /// hand what kind of input blocks we will get.
+       
+       assert( list.empty() );
+       list.push_back( kAliHLTAnyDataType );
+}
+
+
+AliHLTComponentDataType AliHLTMUONDataCheckerComponent::GetOutputDataType()
+{
+       /// Inherited from AliHLTComponent. Returns the output data type of
+       /// "any data type" with MUON origin.
+       
+       return kAliHLTAnyDataType | kAliHLTDataOriginMUON;
+}
+
+
+void AliHLTMUONDataCheckerComponent::GetOutputDataSize(
+               unsigned long& constBase, double& inputMultiplier
+       )
+{
+       /// Inherited from AliHLTComponent.
+       /// Returns an estimate of the expected output data size.
+       
+       // Both of these are zero because we will only ever pass on input data blocks
+       // and never generate data in this component.
+       constBase = 0;
+       inputMultiplier = 0;
+}
+
+
+AliHLTComponent* AliHLTMUONDataCheckerComponent::Spawn()
+{
+       /// Inherited from AliHLTComponent. Creates a new object instance.
+       
+       return new AliHLTMUONDataCheckerComponent;
+}
+
+
+int AliHLTMUONDataCheckerComponent::DoInit(int argc, const char** argv)
+{
+       /// Inherited from AliHLTComponent.
+       /// Parses the command line parameters and initialises the component.
+       
+       HLTInfo("Initialising dHLT data checker component.");
+
+       // Initialise flags with default values.
+       fIgnoreType = false;
+       fIgnoreSpec = false;
+       fDontForward = false;
+       fFilterBadBlocks = false;
+       fNoGlobalChecks = false;
+       fWarnForUnexpecedBlock = false;
+
+       for (int i = 0; i < argc; i++)
+       {
+               if (strcmp(argv[i], "-ignoretype") == 0)
+               {
+                       fIgnoreType = true;
+                       HLTInfo("Ignoring data type of data blocks as given by framework.");
+                       continue;
+               }
+               if (strcmp(argv[i], "-ignorespec") == 0)
+               {
+                       fIgnoreSpec = true;
+                       HLTInfo("Ignoring data specification of data blocks as given by framework.");
+                       continue;
+               }
+               if (strcmp(argv[i], "-dontforward") == 0)
+               {
+                       fDontForward = true;
+                       HLTInfo("Not forwarding input data blocks.");
+                       continue;
+               }
+               if (strcmp(argv[i], "-filter") == 0)
+               {
+                       fFilterBadBlocks = true;
+                       HLTInfo("Passing only bad blocks to output.");
+                       continue;
+               }
+               if (strcmp(argv[i], "--no_global_check") == 0)
+               {
+                       fNoGlobalChecks = true;
+                       HLTInfo("Only per block data consistancy checks will be applied,"
+                               "but no global checks will be made."
+                       );
+                       continue;
+               }
+               if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
+               {
+                       fWarnForUnexpecedBlock = true;
+                       continue;
+               }
+               
+               HLTError("Unknown option '%s'.", argv[i]);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+int AliHLTMUONDataCheckerComponent::DoDeinit()
+{
+       /// Inherited from AliHLTComponent. Performs a cleanup of the component.
+       
+       HLTInfo("Deinitialising dHLT data checker component.");
+       return 0;
+}
+
+
+int AliHLTMUONDataCheckerComponent::DoEvent(
+               const AliHLTComponentEventData& evtData,
+               const AliHLTComponentBlockData* blocks,
+               AliHLTComponentTriggerData& /*trigData*/,
+               AliHLTUInt8_t* /*outputPtr*/,
+               AliHLTUInt32_t& size,
+               std::vector<AliHLTComponentBlockData>& outputBlocks
+       )
+{
+       /// Inherited from AliHLTProcessor. Processes the new event data.
+       /// Here we go through the list of input data blocks and apply extensive
+       /// data integrity checking on the data found.
+       
+       HLTDebug("Processing event %llu with %u input data blocks.",
+               evtData.fEventID, evtData.fBlockCnt
+       );
+       
+       // Allocate an array of flags indicating if the data block is OK or not,
+       // also arrays to store specific 
+       bool* blockOk = NULL;
+       typedef const AliHLTComponentBlockData* PAliHLTComponentBlockData;
+       PAliHLTComponentBlockData* trigRecBlocks = NULL;
+       PAliHLTComponentBlockData* trigRecDebugBlocks = NULL;
+       PAliHLTComponentBlockData* hitBlocks = NULL;
+       PAliHLTComponentBlockData* clusterBlocks = NULL;
+       PAliHLTComponentBlockData* channelBlocks = NULL;
+       PAliHLTComponentBlockData* mansoTrackBlocks = NULL;
+       PAliHLTComponentBlockData* mansoCandidateBlocks = NULL;
+       PAliHLTComponentBlockData* singleDecisionBlocks = NULL;
+       PAliHLTComponentBlockData* pairDecisionBlocks = NULL;
+       AliHLTUInt32_t trigRecBlocksCount = 0;
+       AliHLTUInt32_t trigRecDebugBlocksCount = 0;
+       AliHLTUInt32_t hitBlocksCount = 0;
+       AliHLTUInt32_t clusterBlocksCount = 0;
+       AliHLTUInt32_t channelBlocksCount = 0;
+       AliHLTUInt32_t mansoTrackBlocksCount = 0;
+       AliHLTUInt32_t mansoCandidateBlocksCount = 0;
+       AliHLTUInt32_t singleDecisionBlocksCount = 0;
+       AliHLTUInt32_t pairDecisionBlocksCount = 0;
+       try
+       {
+               blockOk = new bool[evtData.fBlockCnt];
+               trigRecBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               trigRecDebugBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               hitBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               clusterBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               channelBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               mansoTrackBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               mansoCandidateBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               singleDecisionBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+               pairDecisionBlocks = new PAliHLTComponentBlockData[evtData.fBlockCnt];
+       }
+       catch (const std::bad_alloc&)
+       {
+               HLTError("Could not allocate more memory for internal arrays.");
+               // Make sure to clean up if partially allocated memory.
+               if (blockOk != NULL) delete [] blockOk;
+               if (trigRecBlocks != NULL) delete [] trigRecBlocks;
+               if (trigRecDebugBlocks != NULL) delete [] trigRecDebugBlocks;
+               if (hitBlocks != NULL) delete [] hitBlocks;
+               if (clusterBlocks != NULL) delete [] clusterBlocks;
+               if (channelBlocks != NULL) delete [] channelBlocks;
+               if (mansoTrackBlocks != NULL) delete [] mansoTrackBlocks;
+               if (mansoCandidateBlocks != NULL) delete [] mansoCandidateBlocks;
+               if (singleDecisionBlocks != NULL) delete [] singleDecisionBlocks;
+               if (pairDecisionBlocks != NULL) delete [] pairDecisionBlocks;
+               return -ENOMEM;
+       }
+       
+       try
+       {
+               // Clear all the flags indicating if the blocks are ok.
+               for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
+               {
+                       blockOk[n] = false;
+               }
+       
+               for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
+               {
+                       HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
+                               n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
+                       );
+                       
+                       AliHLTMUONDataBlockType blockType = kUnknownDataBlock;
+                       
+                       if (fIgnoreType)
+                       {
+                               // Decode the block type of we must ignore the block type
+                               // as given by the HLT framework.
+                               if (blocks[n].fSize >= sizeof(AliHLTMUONDataBlockHeader))
+                               {
+                                       const AliHLTMUONDataBlockHeader* header =
+                                               reinterpret_cast<const AliHLTMUONDataBlockHeader*>(blocks[n].fPtr);
+                                       blockType = AliHLTMUONDataBlockType(header->fType);
+                               }
+                       }
+                       else
+                       {
+                               if (blocks[n].fDataType == AliHLTMUONConstants::DDLRawDataType())
+                               {
+                                       blockOk[n] = CheckRawDataBlock(blocks[n], n);
+                                       continue;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
+                               {
+                                       blockType = kTriggerRecordsDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::TrigRecsDebugBlockDataType())
+                               {
+                                       blockType = kTrigRecsDebugDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
+                               {
+                                       blockType = kRecHitsDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::ClusterBlockDataType())
+                               {
+                                       blockType = kClustersDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::ChannelBlockDataType())
+                               {
+                                       blockType = kChannelsDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
+                               {
+                                       blockType = kMansoTracksDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::MansoCandidatesBlockDataType())
+                               {
+                                       blockType = kMansoCandidatesDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::SinglesDecisionBlockDataType())
+                               {
+                                       blockType = kSinglesDecisionDataBlock;
+                               }
+                               else if (blocks[n].fDataType == AliHLTMUONConstants::PairsDecisionBlockDataType())
+                               {
+                                       blockType = kPairsDecisionDataBlock;
+                               }
+                               else
+                               {
+                                       // Log a message indicating that we got a data block that we
+                                       // do not know how to handle.
+                                       if (fWarnForUnexpecedBlock)
+                                               HLTWarning("Received a data block of a type we cannot"
+                                                       " handle: '%s', spec: 0x%8.8X",
+                                                       DataType2Text(blocks[n].fDataType).c_str(),
+                                                       blocks[n].fSpecification
+                                               );
+                                       else
+                                               HLTDebug("Received a data block of a type we cannot"
+                                                       " handle: '%s', spec: 0x%8.8X",
+                                                       DataType2Text(blocks[n].fDataType).c_str(),
+                                                       blocks[n].fSpecification
+                                               );
+                               }
+                       }
+                       
+                       switch (blockType)
+                       {
+                       case kTriggerRecordsDataBlock:
+                               blockOk[n] = CheckTriggerRecordsBlock(blocks[n], n);
+                               trigRecBlocks[trigRecBlocksCount++] = &blocks[n];
+                               break;
+                       case kTrigRecsDebugDataBlock:
+                               blockOk[n] = CheckTrigRecsDebugBlock(blocks[n], n);
+                               trigRecDebugBlocks[trigRecDebugBlocksCount++] = &blocks[n];
+                               break;
+                       case kRecHitsDataBlock:
+                               blockOk[n] = CheckRecHitsBlock(blocks[n], n);
+                               hitBlocks[hitBlocksCount++] = &blocks[n];
+                               break;
+                       case kClustersDataBlock:
+                               blockOk[n] = CheckClustersBlock(blocks[n], n);
+                               clusterBlocks[clusterBlocksCount++] = &blocks[n];
+                               break;
+                       case kChannelsDataBlock:
+                               blockOk[n] = CheckChannelsBlock(blocks[n], n);
+                               channelBlocks[channelBlocksCount++] = &blocks[n];
+                               break;
+                       case kMansoTracksDataBlock:
+                               blockOk[n] = CheckMansoTracksBlock(blocks[n], n);
+                               mansoTrackBlocks[mansoTrackBlocksCount++] = &blocks[n];
+                               break;
+                       case kMansoCandidatesDataBlock:
+                               blockOk[n] = CheckMansoCandidatesBlock(blocks[n], n);
+                               mansoCandidateBlocks[mansoCandidateBlocksCount++] = &blocks[n];
+                               break;
+                       case kSinglesDecisionDataBlock:
+                               blockOk[n] = CheckSinglesDecisionBlock(blocks[n], n);
+                               singleDecisionBlocks[singleDecisionBlocksCount++] = &blocks[n];
+                               break;
+                       case kPairsDecisionDataBlock:
+                               blockOk[n] = CheckPairsDecisionBlock(blocks[n], n);
+                               pairDecisionBlocks[pairDecisionBlocksCount++] = &blocks[n];
+                               break;
+                       default:
+                               HLTDebug("Received a data block for which we could not decode the data type."
+                                       " fDataType = '%s', fSpecification = 0x%8.8X, fSize = %u bytes.",
+                                       DataType2Text(blocks[n].fDataType).c_str(),
+                                       blocks[n].fSpecification,
+                                       blocks[n].fSize
+                               );
+                               break;
+                       }
+               }
+               
+               // Apply the global data consistancy checks if not suppressed by the user.
+               if (not fNoGlobalChecks)
+               {
+                       MakeGlobalChecks(
+                               blocks, blockOk, evtData.fBlockCnt,
+                               trigRecBlocks, trigRecBlocksCount,
+                               trigRecDebugBlocks, trigRecDebugBlocksCount,
+                               hitBlocks, hitBlocksCount,
+                               clusterBlocks, clusterBlocksCount,
+                               channelBlocks, channelBlocksCount,
+                               mansoTrackBlocks, mansoTrackBlocksCount,
+                               mansoCandidateBlocks, mansoCandidateBlocksCount,
+                               singleDecisionBlocks, singleDecisionBlocksCount,
+                               pairDecisionBlocks, pairDecisionBlocksCount
+                       );
+               }
+               
+               // Forward the input data blocks if we have not been asked to drop them.
+               // Also remember to filter for bad blocks if so specified.
+               if (not fDontForward)
+               {
+                       for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
+                       {
+                               if (fFilterBadBlocks and blockOk[n]) continue;
+                               outputBlocks.push_back(blocks[n]);
+                       }
+               }
+       }
+       finally
+       (
+               // make sure to cleanup memory
+               delete [] blockOk;
+               delete [] trigRecBlocks;
+               delete [] trigRecDebugBlocks;
+               delete [] hitBlocks;
+               delete [] clusterBlocks;
+               delete [] channelBlocks;
+               delete [] mansoTrackBlocks;
+               delete [] mansoCandidateBlocks;
+               delete [] singleDecisionBlocks;
+               delete [] pairDecisionBlocks;
+       )
+       
+       // Finally we set the total size of output memory we consumed, which is
+       // zero since we just copied the input descriptors to output if anything.
+       size = 0;
+       return 0;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsSpecificationValid(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name
+       ) const
+{
+       /// Checks if the specification bits are valid.
+       /// \param  block The block whose specification should be checked.
+       /// \param  blockNumber The block index number being checked.
+       /// \param  name The name of the type of block being checked.
+       /// \returns true if the specification is valid and false otherwise.
+
+       if (AliHLTMUONUtils::IsSpecValid(block.fSpecification))
+               return true;
+       
+       HLTError("Problem found with data block %d, fDataType = '%s',"
+                " fPtr = %p and fSize = %u bytes."
+                " Assuming this is a %s data block."
+                " Problem: The specification does not contain a valid pattern,"
+                " received 0x%8.8X for the specification.",
+               blockNumber,
+               DataType2Text(block.fDataType).c_str(),
+               block.fPtr,
+               block.fSize,
+               name,
+               block.fSpecification
+       );
+       return false;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsFromTrackerOnly(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name
+       ) const
+{
+       /// Checks if the specification bits are valid and indicate the block
+       /// contains data or information only from the tracker DDLs.
+       /// \param  block The block whose specification should be checked.
+       /// \param  blockNumber The block index number being checked.
+       /// \param  name The name of the type of block being checked.
+       /// \returns true if the specification indicates data is only from tracker.
+       
+       bool result = IsSpecificationValid(block, blockNumber, name);
+       
+       if (AliHLTMUONUtils::ContainsDataFromTracker(block.fSpecification) and
+           not AliHLTMUONUtils::ContainsDataFromTrigger(block.fSpecification)
+          )
+       {
+               return result;
+       }
+       
+       HLTError("Problem found with data block %d, fDataType = '%s',"
+                " fPtr = %p and fSize = %u bytes."
+                " Assuming this is a %s data block."
+                " Problem: The data block does not contain data only from the"
+                " tracker DDLs as expected."
+                " Received 0x%8.8X for the specification.",
+               blockNumber,
+               DataType2Text(block.fDataType).c_str(),
+               block.fPtr,
+               block.fSize,
+               name,
+               block.fSpecification
+       );
+       return false;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsFromTriggerOnly(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name
+       ) const
+{
+       /// Checks if the specification bits are valid and indicate the block
+       /// contains data or information only from the trigger DDLs.
+       /// \param  block The block whose specification should be checked.
+       /// \param  blockNumber The block index number being checked.
+       /// \param  name The name of the type of block being checked.
+       /// \returns true if the specification indicates data is only from trigger.
+       
+       bool result = IsSpecificationValid(block, blockNumber, name);
+       
+       if (AliHLTMUONUtils::ContainsDataFromTrigger(block.fSpecification) and
+           not AliHLTMUONUtils::ContainsDataFromTracker(block.fSpecification)
+          )
+       {
+               return result;
+       }
+       
+       HLTError("Problem found with data block %d, fDataType = '%s',"
+                " fPtr = %p and fSize = %u bytes."
+                " Assuming this is a %s data block."
+                " Problem: The data block does not contain data only from the"
+                " trigger DDLs as expected."
+                " Received 0x%8.8X for the specification.",
+               blockNumber,
+               DataType2Text(block.fDataType).c_str(),
+               block.fPtr,
+               block.fSize,
+               name,
+               block.fSpecification
+       );
+       return false;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsMomentumVectorOk(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name,
+               AliHLTUInt32_t entryNumber,
+               AliHLTFloat32_t px,
+               AliHLTFloat32_t py,
+               AliHLTFloat32_t pz
+       ) const
+{
+       /// Checks if the momentum vector is reasonable.
+       /// \param  block The block from which the momentum vector data comes from.
+       /// \param  blockNumber The block index number.
+       /// \param  name The name of the type of block.
+       /// \param  entryNumber The entry index number of the structure holding
+       ///      the momentum vector data.
+       /// \param  px The X coordinate of the momentum vector (GeV/c).
+       /// \param  py The Y coordinate of the momentum vector (GeV/c).
+       /// \param  pz The Z coordinate of the momentum vector (GeV/c).
+       /// \returns true if the momentum vector is valid and false otherwise.
+       
+       // If the momentum vector is nil then ignore it.
+       if (px == 0 and py == 0 and pz == 0) return true;
+       
+       bool result = true;
+       
+       // If the momentum vector is sane then we should not have a particle with
+       // more energy than 14 TeV and momentum should be in the negative direction.
+       double momentum = sqrt(px*px + py*py + pz*pz);
+       if (momentum > 14e3)
+       {
+               // Just warn since this is a data sanity problem rather
+               // than a data integrity problem.
+               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The momentum vector"
+                       " p = {%f, %f, %f}, |p| = %f looks too big.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       px, py, pz,
+                       momentum
+               );
+               result = false;
+       }
+       
+       if (pz > 0.)
+       {
+               // Just warn since this is a data sanity problem rather
+               // than a data integrity problem.
+               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The momentum vector"
+                       " p = {%f, %f, %f} points away from the dimuon"
+                       " spectrometer (p_z > 0).",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       px, py, pz
+               );
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::AreMomentumCalcParamsOk(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name,
+               AliHLTUInt32_t entryNumber,
+               AliHLTFloat32_t zmiddle,
+               AliHLTFloat32_t bl
+       ) const
+{
+       /// Checks if the parameters for the momentum calculation are reasonable.
+       /// \param  block The block from which the parameter data comes from.
+       /// \param  blockNumber The block index number.
+       /// \param  name The name of the type of block.
+       /// \param  entryNumber The entry index number of the structure holding
+       ///      the parameter data data.
+       /// \param  zmiddle The z-coordinate of the middle of the magnetic field (cm).
+       /// \param  bl The integrated magnetic field (T.m).
+       /// \returns true if the parameters are valid and false otherwise.
+       
+       bool result = true;
+       
+       // Check that the value of the fZmiddle value is somewhere
+       // within the tracking / dipole magnetic field area.
+       if (zmiddle < AliMUONConstants::AbsZEnd() or
+               zmiddle < AliMUONConstants::MuonFilterZBeg()
+               )
+       {
+               // Just warn since this is a data sanity problem rather
+               // than a data integrity problem.
+               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The Z coordinate %f cm"
+                       " used as the middle of the magnetic field in the momentum"
+                       " calculation is outside the dimuon spectrometers dipole"
+                       " magnetic field volume.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       zmiddle
+               );
+               result = false;
+       }
+       
+       // Also check that the value of the 'bl' value is within a
+       // reasonable range: |bl| < Lmax * Bmax, where
+       // Lmax = max length from vertex to end of spectrometer, and
+       // Bmax = max magnetic field of dipole, taken as 1 tesla.
+       // Approximating Lmax * Bmax as 20 T.m
+       if (fabs(bl) > 20.)
+       {
+               // Just warn since this is a data sanity problem rather
+               // than a data integrity problem.
+               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The integrated magnetic"
+                       " field value %f T.m used in the momentum calculation"
+                       " has an unreasonably large absolute value.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       bl
+               );
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsHitCoordinateOk(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name,
+               AliHLTUInt32_t entryNumber,
+               const AliHLTMUONRecHitStruct& hit,
+               AliHLTInt32_t minChamber,
+               AliHLTInt32_t maxChamber,
+               AliHLTInt32_t expectedChamber,
+               bool ddl[22]
+       ) const
+{
+       /// Checks if the hit coordinate is compatible with a the location of a
+       /// dimuon spectrometer chamber. Also, if expectedChamber is not -1, then
+       /// the hit coordinate is checked if to comes from that chamber.
+       /// \param  block The block from which the hit data comes from.
+       /// \param  blockNumber The block index number.
+       /// \param  name The name of the type of block.
+       /// \param  entryNumber The entry index number of the hit.
+       /// \param  hit The hit data being checked.
+       /// \param  minChamber The minimum valid chamber number to check for.
+       /// \param  maxChamber The maximum valid chamber number to check for.
+       /// \param  expectedChamber If not -1 then this is the chamber number to
+       ///      check against.
+       /// \param  ddl  The array decoded by AliHLTMUONUtils::UnpackSpecBits.
+       /// \returns true if the hit is valid and false otherwise.
+       
+       assert( 0 <= minChamber and minChamber < 14 );
+       assert( 0 <= maxChamber and maxChamber < 14 );
+       
+       bool result = true;
+       
+       Int_t chamber = AliMUONConstants::ChamberNumber(hit.fZ, false); // false = do not warn.
+       if (chamber < minChamber or maxChamber < chamber)
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The hit {x = %f, y = %f,"
+                       " z = %f} cm has a z-coordinate that does not correspond"
+                       " to the nominal position of any chambers in the range"
+                       " [%d..%d].",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       hit.fX, hit.fY, hit.fZ,
+                       minChamber+1,
+                       maxChamber+1
+               );
+               return false;
+       }
+       
+       if (expectedChamber != -1 and chamber != expectedChamber)
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The hit {x = %f, y = %f,"
+                       " z = %f} cm has a position that corresponds to chamber %d,"
+                       " but expected it to be on chamber %d.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       hit.fX, hit.fY, hit.fZ,
+                       chamber+1,
+                       expectedChamber+1
+               );
+               result = false;
+       }
+       
+       AliHLTFloat32_t rmin = AliMUONConstants::Rmin(chamber / 2);
+       AliHLTFloat32_t rmax = AliMUONConstants::Rmax(chamber / 2);
+       AliHLTFloat32_t radius = sqrt(hit.fX*hit.fX + hit.fY*hit.fY);
+       if (radius < rmin or rmax < radius)
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The hit {x = %f, y = %f,"
+                       " z = %f} cm has a position in the X-Y plane that does not"
+                       " correspond to the nominal position of chamber %d.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       hit.fX, hit.fY, hit.fZ,
+                       chamber+1
+               );
+               result = false;
+       }
+       
+       if (not fIgnoreSpec and not ChamberMarkedInDDLList(chamber, ddl))
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The hit {x = %f, y = %f,"
+                       " z = %f} cm has a position that corresponds to chamber %d"
+                       " but the data block specification 0x%8.8X does have a"
+                       " corresponding DDL bit set.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       hit.fX, hit.fY, hit.fZ,
+                       chamber+1,
+                       block.fSpecification
+               );
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::IsMansoTrackOk(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber,
+               const char* name,
+               AliHLTUInt32_t entryNumber,
+               const AliHLTMUONMansoTrackStruct& track,
+               bool ddl[22]
+       ) const
+{
+       /// Checks if the Manso track structure is Ok.
+       /// \param  block The block from which the track data comes from.
+       /// \param  blockNumber The block index number.
+       /// \param  name The name of the type of block.
+       /// \param  entryNumber The entry index number of the structure in the
+       ///      block being checked.
+       /// \param  track The Manso track data being checked.
+       /// \param  ddl  The array decoded by AliHLTMUONUtils::UnpackSpecBits.
+       /// \returns true if the hit is valid and false otherwise.
+       
+       bool result = true;
+       
+       // Chi^2 should not be greater than the worst fit possible, estimated
+       // as the diameter of largest chamber times the number of points
+       // findable in a track. Max points is 10 tracker chambers times
+       // 2 cathodes + 4 trigger chambers.
+       if (track.fChi2 > AliMUONConstants::Dmax(6)*AliMUONConstants::Dmax(6)*(10*2+4))
+       {
+               // Just a warning since this is not technically an
+               // integrity problem.
+               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                       " fPtr = %p and fSize = %u bytes."
+                       " Assuming this is a %s data block."
+                       " Problem with entry %d in block: The Manso track has"
+                       " the chi squared value of %f that unreasonably big.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       name,
+                       entryNumber,
+                       track.fChi2
+               );
+               result = false;
+       }
+       
+       // Check if the momentum vector is reasonable.
+       bool momOk = IsMomentumVectorOk(
+                       block, blockNumber, name, entryNumber,
+                       track.fPx, track.fPy, track.fPz
+               );
+       if (not momOk) result = false;
+       
+       AliHLTMUONParticleSign sign;
+       bool hitset[4];
+       AliHLTMUONUtils::UnpackMansoTrackFlags(track.fFlags, sign, hitset);
+       
+       // Min and max allowed chamber numbers for hits:
+       Int_t minCh = 0;
+       Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
+       
+       // Check that this hit coordinates are OK.
+       for (AliHLTUInt32_t i = 0; i < 4; i++)
+       {
+               if (not hitset[i]) continue; // ignore hits that are not initialised.
+               bool hitOk = IsHitCoordinateOk(
+                               block, blockNumber, name, entryNumber, track.fHit[i],
+                               minCh, maxCh, i+6, ddl
+                       );
+               if (not hitOk) result = false;
+       }
+       
+       return result;
+}
+
+
+namespace
+{
+       /**
+        * Class for logging errors found in raw DDL data.
+        */
+       class AliHLTMUONDecoderHandler : public AliHLTLogging
+       {
+       public:
+       
+               /// Default constructor
+               AliHLTMUONDecoderHandler() :
+                       AliHLTLogging(),
+                       fBufferStart(NULL),
+                       fDescriptor(NULL),
+                       fBlockNumber(0)
+               {
+               }
+               
+               /// Default destructor.
+               virtual ~AliHLTMUONDecoderHandler() {}
+               
+               /// Sets the DDL raw data block descriptor.
+               void SetDescriptor(const AliHLTComponentBlockData* b) { fDescriptor = b; }
+               
+               /// Sets the block number of the raw data block descriptor.
+               void SetBlockNumber(AliHLTUInt32_t n) { fBlockNumber = n; }
+               
+               /// Logs an error message describing the problem with the DDL raw data.
+               template <typename ErrorCode, class DecoderHandler>
+               void LogError(ErrorCode code, const void* location, DecoderHandler& handler);
+       
+       protected:
+               // Do not allow copying of this class.
+               /// Not implemented
+               AliHLTMUONDecoderHandler(const AliHLTMUONDecoderHandler& rhs); // copy constructor
+               /// Not implemented
+               AliHLTMUONDecoderHandler& operator = (const AliHLTMUONDecoderHandler& rhs); // assignment operator
+               
+               const void* fBufferStart; ///< Pointer to the start of the current DDL payload buffer.
+               const AliHLTComponentBlockData* fDescriptor; ///< Descriptor for the DDL raw data block corresponding to the buffer.
+               AliHLTUInt32_t fBlockNumber;  ///< The number / index of the block descriptor.
+       };
+       
+       
+       template <typename ErrorCode, class DecoderHandler>
+       void AliHLTMUONDecoderHandler::LogError(ErrorCode code, const void* location, DecoderHandler& handler)
+       {
+               /// Logs a HLT error message describing the problem with the raw DDL data.
+               /// \param code  The error code describing the problem.
+               /// \param location  A pointer to the location in the raw data buffer
+               ///      where the problem was found.
+               /// \param handler  The decoder handler object.
+               
+               long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
+               
+               // create data type string.
+               char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
+               memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
+               strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
+               strcat( dataType, ":" );
+               strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
+               
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                        " fPtr = %p and fSize = %u bytes."
+                        " Assuming this is a DDL raw data block."
+                        " Problem: %s (Error code: %d, at byte %d)",
+                       fBlockNumber,
+                       &dataType[0],
+                       fDescriptor->fPtr,
+                       fDescriptor->fSize,
+                       handler.ErrorCodeToMessage(code),
+                       code,
+                       bytepos
+               );
+       };
+       
+       
+       /**
+        * Class for logging decoding errors when checking tracker raw DDL data.
+        * Used in the AliHLTMUONDataCheckerComponent::CheckRawDataBlock method.
+        */
+       class AliHLTMUONTrackerDecoderHandler :
+               public AliMUONTrackerDDLDecoderEventHandler, public AliHLTMUONDecoderHandler
+       {
+       public:
+               AliHLTMUONTrackerDecoderHandler() :
+                       AliMUONTrackerDDLDecoderEventHandler(),
+                       AliHLTMUONDecoderHandler(),
+                       fMaxDigits(0),
+                       fDigitCount(0),
+                       fDigits(NULL),
+                       fCurrentBusPatch(0),
+                       fDataProblems(false)
+               {}
+               
+               virtual ~AliHLTMUONTrackerDecoderHandler()
+               {
+                       if (fDigits != NULL) delete [] fDigits;
+               }
+               
+               /// Structure to store raw data words found in the raw data.
+               struct AliDigit
+               {
+                       UInt_t fBusPatchId;  ///< Bus patch ID for the data word.
+                       UInt_t fDataWord;   ///< Raw data word found in the DDL payload.
+               };
+               
+               /// Returns the number of digits found.
+               UInt_t DigitCount() const { return fDigitCount; }
+               
+               /// Returns the array of digits found.
+               const AliDigit* Digits() const { return fDigits; }
+               
+               /// Returns true if there were problems with the data.
+               bool DataProblems() const { return fDataProblems; }
+               
+               // Methods inherited from AliMUONTrackerDDLDecoderEventHandler:
+               
+               /// Called for each new buffer.
+               void OnNewBuffer(const void* buffer, UInt_t bufferSize);
+               
+               /// Called for each new bus patch. Just marks the current bus patch ID.
+               void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/)
+               {
+                       fCurrentBusPatch = header->fBusPatchId;
+               }
+               
+               /// Called for each new data word found.
+               void OnData(UInt_t data, bool /*parityError*/);
+               
+               /// Logs an error message if there was a decoding problem with the DDL payload.
+               void OnError(ErrorCode code, const void* location)
+               {
+                       fDataProblems = true;
+                       LogError(code, location, *this);
+               }
+       
+       private:
+       
+               // Do not allow copying of this object.
+               /// Not implemented.
+               AliHLTMUONTrackerDecoderHandler(const AliHLTMUONTrackerDecoderHandler& obj);
+               /// Not implemented.
+               AliHLTMUONTrackerDecoderHandler& operator = (const AliHLTMUONTrackerDecoderHandler& obj);
+               
+               UInt_t fMaxDigits;  ///< Maximum number of digits that can be stored in fDigits.
+               UInt_t fDigitCount;  ///< The number of digits currently stored in fDigits.
+               AliDigit* fDigits;  ///< The array of digits found in the DDL data.
+               UInt_t fCurrentBusPatch;  ///< The current bus patch ID being processed.
+               bool fDataProblems;  ///< flag indicating there were problems with the data.
+       };
+       
+       
+       void AliHLTMUONTrackerDecoderHandler::OnNewBuffer(const void* buffer, UInt_t bufferSize)
+       {
+               /// Called for a new buffer. It will reset internal counters and
+               /// resize the digits array if necessary.
+               
+               fDataProblems = false;
+               fDigitCount = 0;
+               fBufferStart = buffer;
+               
+               // Resize the fDigits array to be able to store
+               // all the digits in the data buffer.
+               UInt_t maxSize = bufferSize / sizeof(UInt_t) + 1;
+               if (maxSize > fMaxDigits)
+               {
+                       if (fDigits != NULL)
+                       {
+                               delete [] fDigits;
+                               fDigits = NULL;
+                               fMaxDigits = 0;
+                       }
+                       try
+                       {
+                               fDigits = new AliDigit[maxSize];
+                               fMaxDigits = maxSize;
+                       }
+                       catch (const std::bad_alloc&)
+                       {
+                               HLTError("Could not allocate enough buffer space for internal arrays.");
+                               return;
+                       }
+               }
+       }
+       
+       
+       void AliHLTMUONTrackerDecoderHandler::OnData(UInt_t data, bool /*parityError*/)
+       {
+               /// Called for each new data word found. This method will add
+               /// these to the list of digits and check if they are not duplicated.
+               
+               assert( fDigits != NULL );
+               
+               // Check if the data word + bus patch have been duplicated.
+               for (UInt_t i = 0; i < fDigitCount; i++)
+               {
+                       if (fDigits[i].fDataWord == data and fDigits[i].fBusPatchId == fCurrentBusPatch)
+                       {
+                               // create data type string.
+                               char dataType[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2];
+                               memset( dataType, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
+                               strncat( dataType, fDescriptor->fDataType.fOrigin, kAliHLTComponentDataTypefOriginSize );
+                               strcat( dataType, ":" );
+                               strncat( dataType, fDescriptor->fDataType.fID, kAliHLTComponentDataTypefIDsize );
+                               
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a tracker DDL raw data block."
+                                       " Problem: Found a duplicate data word 0x%8.8X for bus patch %d.",
+                                       fBlockNumber,
+                                       &dataType[0],
+                                       fDescriptor->fPtr,
+                                       fDescriptor->fSize,
+                                       data,
+                                       fCurrentBusPatch
+                               );
+                               fDataProblems = true;
+                               return;
+                       }
+               }
+               
+               // Add the data word + bus patch to the list of decoded digits.
+               if (fDigitCount < fMaxDigits)
+               {
+                       fDigits[fDigitCount].fBusPatchId = fCurrentBusPatch;
+                       fDigits[fDigitCount].fDataWord = data;
+                       fDigitCount++;
+               }
+       }
+       
+       /**
+        * Class for logging decoding errors when checking trigger raw DDL data.
+        * Used in the AliHLTMUONDataCheckerComponent::CheckRawDataBlock method.
+        */
+       class AliHLTMUONTriggerDecoderHandler :
+               public AliMUONTriggerDDLDecoderEventHandler, public AliHLTMUONDecoderHandler
+       {
+       public:
+               // Methods inherited from AliMUONTriggerDDLDecoderEventHandler:
+               
+               /// Called for each new buffer.
+               void OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
+               {
+                       fBufferStart = buffer;
+               }
+               
+               /// Logs an error message if there was a decoding problem with the DDL payload.
+               void OnError(ErrorCode code, const void* location)
+               {
+                       LogError(code, location, *this);
+               }
+       };
+       
+} // end of namespace
+
+
+bool AliHLTMUONDataCheckerComponent::CheckRawDataBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a raw data block.
+       
+       bool result = true;
+
+       if (fIgnoreSpec)
+       {
+               HLTWarning("Not able to check DDL raw data if -ignorespec is specified.");
+               return false;
+       }
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       // Check that only one DDL was marked in the specification.
+       int ddlIndex = -1;
+       for (int i = 0; i < 22; i++)
+       {
+               if (not ddl[i]) continue;
+               
+               if (ddlIndex == -1)
+               {
+                       ddlIndex = i;
+                       continue;
+               }
+               
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                        " fPtr = %p and fSize = %u bytes."
+                        " Assuming this is a DDL raw data block."
+                        " Problem: The specification indicates multiple"
+                        " DDL sources, DDL %d and %d.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       ddlIndex,
+                       i
+               );
+               result = false;
+       }
+       
+       // Check the DDL common data header.
+       AliHLTUInt32_t totalDDLSize = block.fSize;
+       if (totalDDLSize < sizeof(AliRawDataHeader))
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                        " fPtr = %p and fSize = %u bytes."
+                        " Assuming this is a DDL raw data block."
+                        " Problem: The size of the data block is too short to contain"
+                        " a valid common DDL data header. Size of buffer is only %d"
+                        " bytes, but expected at least %d bytes.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       totalDDLSize,
+                       sizeof(AliRawDataHeader)
+               );
+               return false;
+       }
+       
+       const AliRawDataHeader* header =
+               reinterpret_cast<const AliRawDataHeader*>(block.fPtr);
+       
+       AliHLTUInt32_t payloadSize = block.fSize - sizeof(AliRawDataHeader);
+       const AliHLTUInt8_t* payload =
+               reinterpret_cast<const AliHLTUInt8_t*>(header + 1);
+       
+       if (AliHLTMUONUtils::IsTriggerDDL(block.fSpecification))
+       {
+               bool scalarEvent = header->GetL1TriggerMessage() == 0x1;
+               AliMUONTriggerDDLDecoder<AliHLTMUONTriggerDecoderHandler> decoder;
+               decoder.ExitOnError(false);
+               decoder.TryRecover(false);
+               decoder.AutoDetectScalars(false);
+               decoder.GetHandler().SetDescriptor(&block);
+               decoder.GetHandler().SetBlockNumber(blockNumber);
+               result = decoder.Decode(payload, payloadSize, scalarEvent);
+       }
+       else if (AliHLTMUONUtils::IsTrackerDDL(block.fSpecification))
+       {
+               AliMUONTrackerDDLDecoder<AliHLTMUONTrackerDecoderHandler> decoder;
+               decoder.ExitOnError(false);
+               decoder.TryRecover(false);
+               decoder.SendDataOnParityError(true);
+               decoder.AutoDetectTrailer(true);
+               decoder.CheckForTrailer(true);
+               decoder.GetHandler().SetDescriptor(&block);
+               decoder.GetHandler().SetBlockNumber(blockNumber);
+               result = decoder.Decode(payload, payloadSize);
+               if (decoder.GetHandler().DataProblems()) result = false;
+               
+               if (FetchMappingStores() == 0)  // are stores loaded?
+               {
+                       Bool_t warn = kFALSE;
+                       AliMpDDLStore* ddlStore = AliMpDDLStore::Instance(warn);
+                       
+                       // Check that the bus patch, manu ID and channel addresses are valid
+                       // for each raw data word.
+                       for (UInt_t i = 0; i < decoder.GetHandler().DigitCount(); i++)
+                       {
+                               UInt_t busPatchId = decoder.GetHandler().Digits()[i].fBusPatchId;
+                               UInt_t dataWord = decoder.GetHandler().Digits()[i].fDataWord;
+                               
+                               UShort_t manuId; UChar_t channelId; UShort_t adc;
+                               AliMUONTrackerDDLDecoderEventHandler::UnpackADC(
+                                               dataWord, manuId, channelId, adc
+                                       );
+                               
+                               // Check if the bus patch is valid.
+                               AliMpBusPatch* busPatch = ddlStore->GetBusPatch(busPatchId, warn);
+                               if (busPatch == NULL)
+                               {
+                                       HLTError("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a bus patch identifier %d that"
+                                                " is not valid.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               busPatchId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               // We can check that the bus patch is for the DDL
+                               // which is also indicated by the specification bits.
+                               if (not fIgnoreSpec and busPatch->GetDdlId() != ddlIndex)
+                               {
+                                       HLTError("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a bus patch identifier %d for"
+                                                " DDL %d, but the data block specification 0x%8.8X"
+                                                " indicates a different DDL of %d.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               busPatchId,
+                                               busPatch->GetDdlId(),
+                                               block.fSpecification,
+                                               ddlIndex
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               // Check if the MANU ID is valid.
+                               if (not busPatch->HasManu(manuId))
+                               {
+                                       HLTError("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a MANU identifier %d on bus patch %d"
+                                                " that is not valid.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               manuId,
+                                               busPatchId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               // Now try to fetch the detector element to check the MANU channel.
+                               AliMpDetElement* de = ddlStore->GetDetElement(busPatch->GetDEId(), warn);
+                               if (de == NULL)
+                               {
+                                       HLTError("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a bus patch identifier %d that"
+                                                " does not correspond to a detector element.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               busPatchId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               if (not de->IsConnectedChannel(manuId, channelId))
+                               {
+                                       // Just a warning because this is marked not
+                                       // to be an error in the AliMUONDigitMaker.
+                                       HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a channel with address %d on"
+                                                " MANU ID %d and bus patch %d that is not connected.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               channelId,
+                                               manuId,
+                                               busPatchId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               // Need to also load the correct segmentation to check the channel.
+                               const AliMpVSegmentation* seg =
+                                       AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(
+                                               busPatch->GetDEId(), manuId
+                                       );
+                               if (seg == NULL)
+                               {
+                                       HLTError("Could not load segmentation for detector element %d"
+                                                " and MANU ID %d.",
+                                               busPatch->GetDEId(), manuId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                               
+                               AliMpPad pad = seg->PadByLocation(AliMpIntPair(manuId, channelId), warn);
+                               if (not pad.IsValid())
+                               {
+                                       HLTError("Problem found with data block %d, fDataType = '%s',"
+                                                " fPtr = %p and fSize = %u bytes."
+                                                " Assuming this is a tracker DDL raw data block."
+                                                " Problem: Found a channel with address %d on"
+                                                " MANU ID %d and bus patch %d that is not valid.",
+                                               blockNumber,
+                                               DataType2Text(block.fDataType).c_str(),
+                                               block.fPtr,
+                                               block.fSize,
+                                               channelId,
+                                               manuId,
+                                               busPatchId
+                                       );
+                                       result = false;
+                                       continue;
+                               }
+                       }
+               }
+               else
+               {
+                       HLTWarning("Cannot check if the bus patch IDs, MANU ID and"
+                               " channel addresses for DDL raw data are valid without"
+                               " being able to load the mapping from CDB."
+                       );
+                       result = false;
+               }
+       }
+       else
+       {
+               HLTError("Problem found with data block %d, fDataType = '%s',"
+                        " fPtr = %p and fSize = %u bytes."
+                        " Assuming this is a DDL raw data block."
+                        " Problem: The specification does not contain a valid pattern,"
+                        " received 0x%8.8X for the specification.",
+                       blockNumber,
+                       DataType2Text(block.fDataType).c_str(),
+                       block.fPtr,
+                       block.fSize,
+                       block.fSpecification
+               );
+               result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckTriggerRecordsBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a trigger records block.
+
+       bool result = true;
+       const char* name = "trigger records";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsFromTriggerOnly(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONTriggerRecordsBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       // Min and max allowed chamber numbers for hits:
+       Int_t minCh = AliMUONConstants::NCh() - AliMUONConstants::NTriggerCh();
+       Int_t maxCh = AliMUONConstants::NCh() - 1;
+       
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               // Check that each hit in each trigger record has a reasonable coordinate.
+               AliHLTMUONParticleSign sign;
+               bool hitset[4];
+               AliHLTMUONUtils::UnpackTriggerRecordFlags(inblock[i].fFlags, sign, hitset);
+       
+               for (Int_t j = 0; j < 4; j++)  // loop over 4 trigger chamber hits.
+               {
+                       if (not hitset[i]) continue; // ignore hits that are not initialised.
+                       bool hitOk = IsHitCoordinateOk(
+                                       block, blockNumber, name, i, inblock[i].fHit[j],
+                                       minCh, maxCh, j+10, ddl
+                               );
+                       if (not hitOk) result = false;
+               }
+               
+               // We can also check the momentum vector.
+               bool momOk = IsMomentumVectorOk(
+                               block, blockNumber, name, i,
+                               inblock[i].fPx, inblock[i].fPy, inblock[i].fPz
+                       );
+               if (not momOk) result = false;
+       }
+       
+       // Need to check that no entries have duplicated data but with a different
+       // ID number.
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               AliHLTMUONTriggerRecordStruct ti = inblock[i];
+               ti.fId = -1;
+               for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
+               {
+                       AliHLTMUONTriggerRecordStruct tj = inblock[j];
+                       tj.fId = ti.fId;
+                       
+                       if (ti == tj)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: The trigger records %d and %d contain the"
+                                       " same data. The data might have been duplicated.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       i, j
+                               );
+                               result = false;
+                       }
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckTrigRecsDebugBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a trigger records debug block.
+       
+       bool result = true;
+       const char* name = "trigger records debug information";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsFromTriggerOnly(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONTrigRecsDebugBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       // Check that each detector element ID is valid and the corresponding DDL
+       // bit is set in the data block specification.
+       if (FetchMappingStores() == 0)  // are stores loaded?
+       {
+               Bool_t warn = kFALSE;
+               AliMpDEStore* store = AliMpDEStore::Instance(warn);
+               for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+               for (AliHLTUInt32_t j = 0; j < 4; j++)
+               {
+                       const AliHLTMUONTrigRecInfoStruct& trig = inblock[i];
+                       AliMpDetElement* de = store->GetDetElement(trig.fDetElemId[j], warn);
+                       if (de == NULL)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d on chamber"
+                                        " %d for trigger record debug structure %d is not valid.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       trig.fDetElemId[j],
+                                       j+11,
+                                       i
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // Check that the chamber number from the detector element number
+                       // has the expected value.
+                       Int_t chamber = AliMpDEManager::GetChamberId(trig.fDetElemId[j], warn);
+                       if (chamber != Int_t(j+10))
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d for trigger"
+                                        " record debug structure %d, corresponds to chamber"
+                                        " %d, but we expected a hit for chamber %d.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       trig.fDetElemId[j],
+                                       i,
+                                       chamber+1,
+                                       j+11
+                               );
+                               result = false;
+                       }
+                       
+                       if (fIgnoreSpec) continue;
+                       if (0 <= de->GetDdlId() and de->GetDdlId() < 22 and ddl[de->GetDdlId()])
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d for trigger"
+                                        " record %d corresponds to DDL number %d, but the"
+                                        " data block specification 0x%8.8X does not have the"
+                                        " corresponding bit set.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       trig.fDetElemId[j],
+                                       i,
+                                       de->GetDdlId(),
+                                       block.fSpecification
+                               );
+                               result = false;
+                       }
+               }
+       }
+       else
+       {
+               HLTWarning("Cannot check trigger record debug information without"
+                       " being able to load the mapping from CDB."
+               );
+               result = false;
+       }
+       
+       // Need to check that no entries have duplicated data but with a different
+       // ID number.
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               AliHLTMUONTrigRecInfoStruct ti = inblock[i];
+               ti.fTrigRecId = -1;
+               for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
+               {
+                       AliHLTMUONTrigRecInfoStruct tj = inblock[j];
+                       tj.fTrigRecId = ti.fTrigRecId;
+                       
+                       if (ti == tj)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: The trigger record debug information"
+                                       " structures %d and %d contain the same data."
+                                       " The data might have been duplicated.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       i, j
+                               );
+                               result = false;
+                       }
+               }
+               
+               // Can also check that the value of the fZmiddle and fBl.
+               bool paramsOk = AreMomentumCalcParamsOk(
+                               block, blockNumber, name, i, ti.fZmiddle, ti.fBl
+                       );
+               if (not paramsOk) result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckRecHitsBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a reconstructed hits block.
+
+       bool result = true;
+       const char* name = "reconstructed hits";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsFromTrackerOnly(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONRecHitsBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockHeaderOnly(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       // Check that each hit has a reasonable coordinate.
+       Int_t minCh = 0;
+       Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               bool hitOk = IsHitCoordinateOk(
+                               block, blockNumber, name, i, inblock[i],
+                               minCh, maxCh, -1, ddl
+                       );
+               if (not hitOk) result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckClustersBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a clusters block.
+
+       bool result = true;
+       const char* name = "clusters";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsFromTrackerOnly(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONClustersBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       if (FetchMappingStores() == 0)  // are stores loaded?
+       {
+               Bool_t warn = kFALSE;
+               AliMpDEStore* store = AliMpDEStore::Instance(warn);
+               for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+               {
+                       const AliHLTMUONClusterStruct& cluster = inblock[i];
+                       
+                       // Check that the detector element ID is valid.
+                       AliMpDetElement* de = store->GetDetElement(cluster.fDetElemId, warn);
+                       if (de == NULL)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d for cluster"
+                                        " %d is not valid.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       cluster.fDetElemId,
+                                       i
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // Check that the chamber number found from the hit coordinate and
+                       // that from the detector element number are the same.
+                       Int_t chamberFromHit = AliMUONConstants::ChamberNumber(cluster.fHit.fZ, warn);
+                       Int_t chamberFromDE = AliMpDEManager::GetChamberId(cluster.fDetElemId, warn);
+                       if (chamberFromHit != chamberFromDE)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d for"
+                                        " cluster %d, corresponds to chamber %d, but"
+                                        " found a different chamber number %d for the"
+                                        " corresponding hit coordinate {x = %f, y = %f,"
+                                        " z = %f}.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       cluster.fDetElemId,
+                                       i,
+                                       chamberFromDE+1,
+                                       chamberFromHit+1,
+                                       cluster.fHit.fX,
+                                       cluster.fHit.fY,
+                                       cluster.fHit.fZ
+                               );
+                               result = false;
+                       }
+                       
+                       // Make sure the corresponding DDL bit is set in the data
+                       // block specification.
+                       if (fIgnoreSpec) continue;
+                       if (0 <= de->GetDdlId() and de->GetDdlId() < 22 and ddl[de->GetDdlId()])
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: The detector element number %d for cluster"
+                                        " %d corresponds to DDL number %d, but the data"
+                                        " block specification 0x%8.8X does not have the"
+                                        " corresponding bit set.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       cluster.fDetElemId,
+                                       i,
+                                       de->GetDdlId(),
+                                       block.fSpecification
+                               );
+                               result = false;
+                       }
+               }
+       }
+       else
+       {
+               HLTWarning("Cannot check cluster information without being able"
+                       " to load the mapping from CDB."
+               );
+               result = false;
+       }
+       
+       // Min and max chamber numbers allowed for the cluster hits.
+       Int_t minCh = 0;
+       Int_t maxCh = AliMUONConstants::NTrackingCh() - 1;
+       
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               // Need to check that no cluster data has duplicated data but with
+               // a different ID number.
+               AliHLTMUONClusterStruct ci = inblock[i];
+               ci.fId = -1;
+               for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
+               {
+                       AliHLTMUONClusterStruct cj = inblock[j];
+                       cj.fId = ci.fId;
+                       
+                       if (ci == cj)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: The cluster structures %d and %d contain"
+                                       " the same data. The data might have been duplicated.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       i, j
+                               );
+                               result = false;
+                       }
+               }
+               
+               // Check that the hit structure in the cluster corresponds
+               // to a tracker chamber.
+               bool hitOk = IsHitCoordinateOk(
+                               block, blockNumber, name, i, ci.fHit,
+                               minCh, maxCh, -1, ddl
+                       );
+               if (not hitOk) result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckChannelsBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a channels block.
+
+       bool result = true;
+       const char* name = "channels";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsFromTrackerOnly(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONChannelsBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       if (FetchMappingStores() == 0)  // are stores loaded?
+       {
+               Bool_t warn = kFALSE;
+               AliMpDDLStore* store = AliMpDDLStore::Instance(warn);
+               
+               for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+               {
+                       const AliHLTMUONChannelStruct& channel = inblock[i];
+                       
+                       // Check if the bus patch is valid.
+                       AliMpBusPatch* busPatch = store->GetBusPatch(channel.fBusPatch, warn);
+                       if (busPatch == NULL)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: Found a bus patch identifier %d that"
+                                       " is not valid.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fBusPatch
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // We can check that the bus patch is for a DDL
+                       // which is also indicated by the specification bits.
+                       if (not fIgnoreSpec and (
+                            not (0 <= busPatch->GetDdlId() and busPatch->GetDdlId() < 20)
+                            or  (0 <= busPatch->GetDdlId() and busPatch->GetDdlId() < 20
+                                 and not ddl[busPatch->GetDdlId()])
+                          ))
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: Found a bus patch identifier %d for"
+                                        " DDL %d, but the data block specification 0x%8.8X"
+                                        " does not have the corresponding bit set.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fBusPatch,
+                                       busPatch->GetDdlId(),
+                                       block.fSpecification
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // Check if the MANU ID is valid.
+                       if (not busPatch->HasManu(channel.fManu))
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: Found a MANU identifier %d on bus patch %d"
+                                        " that is not valid.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fManu,
+                                       channel.fBusPatch
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // Now try to fetch the detector element to check the MANU channel.
+                       AliMpDetElement* de = store->GetDetElement(busPatch->GetDEId(), warn);
+                       if (de == NULL)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                        " fPtr = %p and fSize = %u bytes."
+                                        " Assuming this is a %s data block."
+                                        " Problem: Found a bus patch identifier %d that"
+                                        " does not correspond to a detector element.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fBusPatch
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       if (not de->IsConnectedChannel(channel.fManu, channel.fChannelAddress))
+                       {
+                               // Just a warning because this is marked not
+                               // to be an error in the AliMUONDigitMaker.
+                               HLTWarning("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: Found a channel with address %d on"
+                                       " MANU ID %d and bus patch %d that is not connected.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fChannelAddress,
+                                       channel.fManu,
+                                       channel.fBusPatch
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       // Need to also load the correct segmentation to check the channel.
+                       const AliMpVSegmentation* seg =
+                               AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(
+                                       busPatch->GetDEId(), channel.fManu
+                               );
+                       if (seg == NULL)
+                       {
+                               HLTError("Could not load segmentation for detector element %d"
+                                        " and MANU ID %d.",
+                                       busPatch->GetDEId(), channel.fManu
+                               );
+                               result = false;
+                               continue;
+                       }
+                       
+                       AliMpPad pad = seg->PadByLocation(
+                                       AliMpIntPair(channel.fManu, channel.fChannelAddress),
+                                       warn
+                               );
+                       if (not pad.IsValid())
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: Found a channel with address %d on"
+                                       " MANU ID %d and bus patch %d that is not valid.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       channel.fChannelAddress,
+                                       channel.fManu,
+                                       channel.fBusPatch
+                               );
+                               result = false;
+                               continue;
+                       }
+               }
+       }
+       else
+       {
+               HLTWarning("Cannot check channel information without being able"
+                       " to load the mapping from CDB."
+               );
+               result = false;
+       }
+       
+       // Need to check that no channel data has duplicated data but with
+       // a different cluster ID number.
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               AliHLTMUONChannelStruct ci = inblock[i];
+               ci.fClusterId = -1;
+               for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
+               {
+                       AliHLTMUONChannelStruct cj = inblock[j];
+                       cj.fClusterId = ci.fClusterId;
+                       
+                       if (ci == cj)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: The channel structures %d and %d contain"
+                                       " the same data. The data might have been duplicated.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       i, j
+                               );
+                               result = false;
+                       }
+               }
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckMansoTracksBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a Manso tracks block.
+
+       bool result = true;
+       const char* name = "Manso tracks";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsSpecificationValid(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONMansoTracksBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               // Need to check that no entries have duplicated data but with
+               // a different track ID number.
+               AliHLTMUONMansoTrackStruct ti = inblock[i];
+               ti.fId = -1;
+               for (AliHLTUInt32_t j = i+1; j < inblock.Nentries(); j++)
+               {
+                       AliHLTMUONMansoTrackStruct tj = inblock[j];
+                       tj.fId = ti.fId;
+                       
+                       if (ti == tj)
+                       {
+                               HLTError("Problem found with data block %d, fDataType = '%s',"
+                                       " fPtr = %p and fSize = %u bytes."
+                                       " Assuming this is a %s data block."
+                                       " Problem: The Manso tracks %d and %d contain the"
+                                       " same data. The data might have been duplicated.",
+                                       blockNumber,
+                                       DataType2Text(block.fDataType).c_str(),
+                                       block.fPtr,
+                                       block.fSize,
+                                       name,
+                                       i, j
+                               );
+                               result = false;
+                       }
+               }
+               
+               bool trackOk = IsMansoTrackOk(block, blockNumber, name, i, ti, ddl);
+               if (not trackOk) result = false;
+       }
+       
+       return result;
+}
+
+
+bool AliHLTMUONDataCheckerComponent::CheckMansoCandidatesBlock(
+               const AliHLTComponentBlockData& block,
+               AliHLTUInt32_t blockNumber
+       ) const
+{
+       /// Checks the validity of a Manso candidates block.
+
+       bool result = true;
+       const char* name = "Manso track candidates";
+       
+       if (not fIgnoreSpec)
+       {
+               if (not IsSpecificationValid(block, blockNumber, name))
+                       result = false;
+       }
+       
+       AliHLTMUONMansoCandidatesBlockReader inblock(block.fPtr, block.fSize);
+       if (not CheckBlockIntegrity(block, blockNumber, inblock, name))
+               return false;
+       
+       bool ddl[22];
+       AliHLTMUONUtils::UnpackSpecBits(block.fSpecification, ddl);
+       
+       for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
+       {
+               // Need to check that no entries have duplicated data but with a
+               // different track ID number.