--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * 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 dHLTdumpraw.cxx
+ * @author Artur Szostak <artursz@iafrica.com>,
+ * Seforo Mohlalisi <seforomohlalisi@yahoo.co.uk>
+ * @date
+ * @brief Command line utility to dump dHLT's internal raw data blocks.
+ */
+
+// We define NDEBUG for the AliHLTMUONDataBlockReader.h header file since this
+// program by definition handles corrupt data. So we do not need the assertions
+// in the AliHLTMUONDataBlockReader class to be checked.
+#define NDEBUG
+#include "AliHLTMUONDataBlockReader.h"
+#undef NDEBUG
+#include "AliHLTMUONUtils.h"
+
+#include <endian.h>
+#ifndef LITTLE_ENDIAN
+#error Handling of internal data for non little endian machines not yet implemented.
+#endif
+
+#include <stdlib.h>
+#include <cassert>
+#include <new>
+#include <fstream>
+
+#include <iostream>
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::showbase;
+using std::noshowbase;
+using std::hex;
+using std::dec;
+
+#include <iomanip>
+using std::setw;
+using std::left;
+using std::internal;
+
+
+#define CMDLINE_ERROR 1
+#define PARSE_ERROR 2
+#define SYSTEM_ERROR 3
+#define FATAL_ERROR 4
+
+
+void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
+{
+ if (padCount == 0) return;
+
+ cerr << "ERROR: Found the following unexpected rubbish data at the"
+ " end of the data block:" << endl;
+ cerr << "Byte #\tValue\tCharacter" << endl;
+ for (AliHLTUInt32_t i = 0; i < padCount; i++)
+ {
+ short value = short(padByte[i]) & 0xFF;
+ char character = padByte[i];
+ cerr << offset + i + 1 << "\t"
+ << noshowbase << hex << "0x" << value << dec << "\t"
+ << character << endl;
+ }
+}
+
+
+template <typename FieldType>
+int CheckHeaderField(
+ FieldType& field, const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ const char* fieldptr = reinterpret_cast<const char*>(&field);
+ const char* endptr = buffer + bufferSize;
+ AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
+
+ if (bufferRemaining < sizeof(field))
+ {
+ cout << "..." << endl; // We may be half way through printing a line so end it.
+ cerr << "ERROR: The data block is too short. The header is corrupt." << endl;
+ if (continueParse)
+ {
+ AliHLTUInt32_t offset = fieldptr - buffer;
+ PrintRubbishData(offset, fieldptr, bufferRemaining);
+ }
+ return PARSE_ERROR;
+ }
+ return EXIT_SUCCESS;
+}
+
+
+template <typename FieldType>
+int CheckField(
+ FieldType& field, const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ const char* fieldptr = reinterpret_cast<const char*>(&field);
+ const char* endptr = buffer + bufferSize;
+ AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
+
+ if (bufferRemaining < sizeof(field))
+ {
+ cout << "..." << endl; // We may be half way through printing a line so end it.
+ cerr << "ERROR: The data block is too short. The data is corrupt." << endl;
+ if (continueParse)
+ {
+ AliHLTUInt32_t offset = fieldptr - buffer;
+ PrintRubbishData(offset, fieldptr, bufferRemaining);
+ }
+ return PARSE_ERROR;
+ }
+ return EXIT_SUCCESS;
+}
+
+
+template <typename BlockType>
+int CheckCommonHeader(
+ BlockType& block, const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+
+ // Check the fRecordWidth field in the common header.
+ if (block.CommonBlockHeader().fRecordWidth !=
+ sizeof(typename BlockType::ElementType))
+ {
+ cerr << "ERROR: The record width found in the header is incorrect."
+ " Found a record width of "
+ << block.CommonBlockHeader().fRecordWidth << " bytes, but expected"
+ " a value of " << sizeof(typename BlockType::ElementType)
+ << " bytes." << endl;
+ result = PARSE_ERROR;
+ if (not continueParse) return result;
+ }
+
+ if (not block.BufferSizeOk())
+ {
+ cerr << "ERROR: The size of the file is incorrect. It is "
+ << bufferSize << " bytes big, but according"
+ " to the data block header it should be " << block.BytesUsed()
+ << " bytes." << endl;
+ result = PARSE_ERROR;
+ if (not continueParse) return result;
+ }
+
+ return result;
+}
+
+
+template <typename BlockType>
+AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
+{
+ // Calculate how many entries we can display. If the buffer size is correct
+ // we just use the number of entries the block specifies. Otherwise we need
+ // to calculate it from the buffer size.
+ AliHLTUInt32_t nentries;
+ if (block.BytesUsed() == bufferSize)
+ {
+ nentries = block.Nentries();
+ }
+ else
+ {
+ AliHLTInt32_t dataSize = bufferSize
+ - sizeof(typename BlockType::HeaderType);
+ nentries = dataSize / sizeof(typename BlockType::ElementType);
+ if (dataSize % sizeof(typename BlockType::ElementType) > 0)
+ nentries++;
+ }
+ return nentries;
+}
+
+
+int DumpTriggerRecordsBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
+ // TODO
+ return EXIT_SUCCESS;
+}
+
+
+int DumpTrigRecsDebugBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
+ // TODO
+ return EXIT_SUCCESS;
+}
+
+
+int DumpTriggerChannelsBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
+ // TODO
+ return EXIT_SUCCESS;
+}
+
+
+int DumpRecHitStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONRecHitStruct* hit,
+ bool continueParse
+ )
+{
+ // Step through the fields trying to print them.
+ // At each step check if we have not overflowed the buffer. If we have
+ // not, then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << hit->fX << setw(0);
+
+ result = CheckField(hit->fY, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << hit->fY << setw(0);
+
+ result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << hit->fZ << setw(0) << endl;
+
+ return result;
+}
+
+
+int DumpRecHitsBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+ AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
+
+ result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS and not continueParse) return result;
+
+ AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
+
+ // Print the data block record entries.
+ cout << " X (cm) | Y (cm) | Z (cm)" << endl;
+ cout << "---------------------------------------" << endl;
+ const AliHLTMUONRecHitStruct* entry = block.GetArray();
+ for(AliHLTUInt32_t i = 0; i < nentries; i++)
+ {
+ int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+ }
+
+ return result;
+}
+
+
+int DumpClustersBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ AliHLTMUONClustersBlockReader block(buffer, bufferSize);
+ // TODO
+ return EXIT_SUCCESS;
+}
+
+
+int DumpChannelsBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
+ // TODO
+ return EXIT_SUCCESS;
+}
+
+
+int DumpMansoTrackStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONMansoTrackStruct* track,
+ bool continueParse
+ )
+{
+ // Step through the fields trying to print them.
+ // At each step check if we have not overflowed the buffer. If we have
+ // not, then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckField(track->fId, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Track ID: " << track->fId << "\t";
+
+ result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Trigger Record ID: " << track->fTrigRec << endl;
+
+ result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Flags: " << showbase << hex << track->fFlags << dec;
+
+ // Print the individual trigger bits.
+ AliHLTMUONParticleSign sign;
+ bool hitset[4];
+ AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
+ cout << " [Sign: " << sign << ", Hits set on chambers: ";
+ bool first = true;
+ for (AliHLTUInt32_t i = 0; i < 4; i++)
+ {
+ if (hitset[i])
+ {
+ cout << (first ? "" : ", ") << i+7;
+ first = false;
+ }
+ }
+ cout << (first ? "none]" : "]") << endl;
+
+ result = CheckField(track->fPx, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Momentum: (px = " << track->fPx << ", ";
+
+ result = CheckField(track->fPy, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "py = " << track->fPy << ", ";
+
+ result = CheckField(track->fPz, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "pz = " << track->fPz << ") GeV/c\t";
+
+ result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Chi squared fit: " << track->fChi2 << endl;
+
+ cout << "Track hits:" << endl;
+ cout << "Chamber | X (cm) | Y (cm) | Z (cm)" << endl;
+ cout << "------------------------------------------------" << endl;
+ const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
+ for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
+ {
+ cout << setw(10) << ch + 7;
+ result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ }
+
+ return result;
+}
+
+
+int DumpMansoTracksBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+ AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
+
+ result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS and not continueParse) return result;
+
+ AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
+
+ // Print the data block record entries.
+ const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
+ for(AliHLTUInt32_t i = 0; i < nentries; i++)
+ {
+ cout << "============================== Manso track number " << i+1
+ << " of " << nentries << " ==============================" << endl;
+ int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+ }
+
+ return result;
+}
+
+
+int DumpMansoRoIStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONMansoRoIStruct* roi,
+ bool continueParse
+ )
+{
+ // Step through the fields trying to print them.
+ // At each step check if we have not overflowed the buffer. If we have
+ // not, then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << roi->fX << setw(0);
+
+ result = CheckField(roi->fY, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << roi->fY << setw(0);
+
+ result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << roi->fZ << setw(0);
+
+ result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << roi->fRadius << setw(0) << endl;
+
+ return result;
+}
+
+
+int DumpMansoCandidateStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONMansoCandidateStruct* candidate,
+ bool continueParse
+ )
+{
+ int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+
+ cout << "Regions of interest:" << endl;
+ cout << "Chamber | X (cm) | Y (cm) | Z (cm) | Radius (cm)" << endl;
+ cout << "-------------------------------------------------------------" << endl;
+ const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
+ for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
+ {
+ cout << setw(10) << ch + 7;
+ result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ }
+ return result;
+}
+
+
+int DumpMansoCandidatesBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+ AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
+
+ result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS and not continueParse) return result;
+
+ AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
+
+ // Print the data block record entries.
+ const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
+ for(AliHLTUInt32_t i = 0; i < nentries; i++)
+ {
+ cout << "=========================== Manso track candidate number " << i+1
+ << " of " << nentries << " ===========================" << endl;
+ int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+ }
+
+ return result;
+}
+
+
+int DumpSinglesDecisionBlockHeader(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONSinglesDecisionBlockStruct* header,
+ bool continueParse
+ )
+{
+ // Step through the header fields trying to print them.
+ // At each step check if we have not overflowed the buffer, if we have
+ // not then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of low pt triggers: " << header->fNlowPt << endl;
+
+ result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Number of high pt triggers: " << header->fNhighPt << endl;
+
+ return result;
+}
+
+
+int DumpTrackDecisionStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONTrackDecisionStruct* decision,
+ bool continueParse
+ )
+{
+ // Step through the fields trying to print them.
+ // At each step check if we have not overflowed the buffer. If we have
+ // not, then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << decision->fTrackId << setw(0);
+
+ result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(12) << left << showbase << hex << decision->fTriggerBits
+ << setw(0) << dec;
+
+ // Print the individual trigger bits.
+ bool highPt, lowPt;
+ AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
+ cout << setw(7) << left << (highPt ? "yes" : "no");
+ cout << setw(8) << left << (lowPt ? "yes" : "no");
+ cout << setw(0) << endl;
+
+ return result;
+}
+
+
+int DumpSinglesDecisionBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+ AliHLTMUONSinglesDecisionBlockReader block(buffer, bufferSize);
+
+ result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS and not continueParse) return result;
+
+ // Dump the rest of the block header.
+ const AliHLTMUONSinglesDecisionBlockStruct* header = &block.BlockHeader();
+ int subResult = DumpSinglesDecisionBlockHeader(buffer, bufferSize, header, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+
+ AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
+
+ // Print the data block record entries.
+ cout << " | Trigger Bits" << endl;
+ cout << "Track ID | Raw HighPt LowPt" << endl;
+ cout << "--------------------------------------" << endl;
+ const AliHLTMUONTrackDecisionStruct* entry = block.GetArray();
+ for(AliHLTUInt32_t i = 0; i < nentries; i++)
+ {
+ subResult = DumpTrackDecisionStruct(buffer, bufferSize, entry++, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+ }
+
+ return result;
+}
+
+
+int DumpPairsDecisionBlockHeader(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONPairsDecisionBlockStruct* header,
+ bool continueParse
+ )
+{
+ // Step through the header fields trying to print them.
+ // At each step check if we have not overflowed the buffer, if we have
+ // not then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckHeaderField(header->fNunlikeAnyPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of unlike all pt triggers: " << header->fNunlikeAnyPt << endl;
+
+ result = CheckHeaderField(header->fNunlikeLowPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of unlike low pt triggers: " << header->fNunlikeLowPt << endl;
+
+ result = CheckHeaderField(header->fNunlikeHighPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of unlike high pt triggers: " << header->fNunlikeHighPt << endl;
+
+ result = CheckHeaderField(header->fNlikeAnyPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of like any pt triggers: " << header->fNlikeAnyPt << endl;
+
+ result = CheckHeaderField(header->fNlikeLowPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of like low pt triggers: " << header->fNlikeLowPt << endl;
+
+ result = CheckHeaderField(header->fNlikeHighPt, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of like high pt triggers: " << header->fNlikeHighPt << endl;
+
+ result = CheckHeaderField(header->fNmassAny, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of all invariant mass triggers: " << header->fNmassAny << endl;
+
+ result = CheckHeaderField(header->fNmassLow, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Number of low invariant mass triggers: " << header->fNmassLow << endl;
+
+ result = CheckHeaderField(header->fNmassHigh, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Number of high invariant mass triggers: " << header->fNmassHigh << endl;
+
+ return result;
+}
+
+
+int DumpPairDecisionStruct(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONPairDecisionStruct* decision,
+ bool continueParse
+ )
+{
+ // Step through the fields trying to print them.
+ // At each step check if we have not overflowed the buffer. If we have
+ // not, then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckField(decision->fTrackAId, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << decision->fTrackAId << setw(0);
+
+ result = CheckField(decision->fTrackBId, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(13) << left << decision->fTrackBId << setw(0);
+
+ result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << setw(12) << left << showbase << hex << decision->fTriggerBits
+ << setw(0) << dec;
+
+ // Print the individual trigger bits.
+ bool highMass, lowMass, unlike;
+ AliHLTUInt8_t highPtCount, lowPtCount;
+ AliHLTMUONUtils::UnpackPairDecisionBits(
+ decision->fTriggerBits,
+ highMass, lowMass, unlike, highPtCount, lowPtCount
+ );
+ cout << setw(7) << left << (highMass ? "yes" : "no");
+ cout << setw(7) << left << (lowMass ? "yes" : "no");
+ cout << setw(7) << left << (unlike ? "yes" : "no");
+ cout << setw(6) << left << AliHLTUInt16_t(highPtCount);
+ cout << setw(8) << left << AliHLTUInt16_t(lowPtCount);
+ cout << setw(0);
+
+ result = CheckField(decision->fInvMass, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << decision->fInvMass << endl;
+
+ return EXIT_SUCCESS;
+}
+
+
+int DumpPairsDecisionBlock(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse
+ )
+{
+ int result = EXIT_SUCCESS;
+ AliHLTMUONPairsDecisionBlockReader block(buffer, bufferSize);
+
+ result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS and not continueParse) return result;
+
+ // Dump the rest of the block header.
+ const AliHLTMUONPairsDecisionBlockStruct* header = &block.BlockHeader();
+ int subResult = DumpPairsDecisionBlockHeader(buffer, bufferSize, header, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+
+ AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
+
+ // Print the data block record entries.
+ cout << " | | Trigger Bits |" << endl;
+ cout << "Track A ID | Track B ID | Raw HiMass LoMass Unlike HiPt# LoPt# | Invariant mass" << endl;
+ cout << "----------------------------------------------------------------------------------------" << endl;
+ const AliHLTMUONPairDecisionStruct* entry = block.GetArray();
+ for(AliHLTUInt32_t i = 0; i < nentries; i++)
+ {
+ subResult = DumpPairDecisionStruct(buffer, bufferSize, entry++, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+ }
+
+ return result;
+}
+
+
+int DumpCommonHeader(
+ const char* buffer, unsigned long bufferSize,
+ const AliHLTMUONDataBlockHeader* header, bool continueParse
+ )
+{
+ // Step through the header fields trying to print them.
+ // At each step check if we have not overflowed the buffer, if we have
+ // not then we can print the field, otherwise we print the left over
+ // bytes assumed to be corrupted rubbish.
+ int result = CheckHeaderField(header->fType, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ AliHLTMUONDataBlockType type = AliHLTMUONDataBlockType(header->fType);
+ cout << " Block type: " << type << endl;
+
+ result = CheckHeaderField(header->fRecordWidth, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << " Record width: " << header->fRecordWidth << endl;
+
+ result = CheckHeaderField(header->fNrecords, buffer, bufferSize, continueParse);
+ if (result != EXIT_SUCCESS) return result;
+ cout << "Number of entries: " << header->fNrecords << endl;
+
+ return result;
+}
+
+
+int ParseBuffer(
+ const char* buffer, unsigned long bufferSize,
+ bool continueParse, AliHLTMUONDataBlockType type
+ )
+{
+ assert( buffer != NULL );
+ int result = EXIT_SUCCESS;
+
+ if (bufferSize < sizeof(AliHLTMUONDataBlockHeader))
+ {
+ cerr << "ERROR: The size of the file is too small to contain a"
+ " valid data block." << endl;
+ result = PARSE_ERROR;
+ if (not continueParse) return result;
+ }
+ const AliHLTMUONDataBlockHeader* header =
+ reinterpret_cast<const AliHLTMUONDataBlockHeader*>(buffer);
+
+ int subResult = DumpCommonHeader(buffer, bufferSize, header, continueParse);
+ if (subResult != EXIT_SUCCESS) return subResult;
+
+
+ // Check if the block type in the header corresponds to the type given
+ // by the '-type' command line parameter. If they do not then print an
+ // error or big fat warning message and force interpretation of the data
+ // block with the type given by '-type'.
+ AliHLTMUONDataBlockType headerType = AliHLTMUONDataBlockType(header->fType);
+
+ if (type == kUnknownDataBlock)
+ {
+ // -type not used in the command line so just use what is given
+ // by the data block header.
+ type = headerType;
+ }
+ else if (type != headerType)
+ {
+ cerr << "WARNING: The data block header indicates a type"
+ " different from what was specified on the command line."
+ " The data could be corrupt."
+ << endl;
+ cerr << "WARNING: The type value in the file is "
+ << showbase << hex << header->fType
+ << " (" << headerType << "), but on the command line it is "
+ << showbase << hex << int(type) << dec
+ << " (" << type << ")."
+ << endl;
+ cerr << "WARNING: Will force the interpretation of the data block"
+ " with a type of " << type << "." << endl;
+ }
+
+ // Now we know what type the data block is supposed to be so we can
+ // dump it to screen with the appropriate dump routine.
+ switch (type)
+ {
+ case kTriggerRecordsDataBlock:
+ subResult = DumpTriggerRecordsBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kTrigRecsDebugDataBlock:
+ subResult = DumpTrigRecsDebugBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kTriggerChannelsDataBlock:
+ subResult = DumpTriggerChannelsBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kRecHitsDataBlock:
+ subResult = DumpRecHitsBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kClustersDataBlock:
+ subResult = DumpClustersBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kChannelsDataBlock:
+ return DumpChannelsBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kMansoTracksDataBlock:
+ subResult = DumpMansoTracksBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kMansoCandidatesDataBlock:
+ subResult = DumpMansoCandidatesBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kSinglesDecisionDataBlock:
+ subResult = DumpSinglesDecisionBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ case kPairsDecisionDataBlock:
+ return DumpPairsDecisionBlock(buffer, bufferSize, continueParse);
+ if (subResult != EXIT_SUCCESS) result = subResult;
+ break;
+ default :
+ cout << "ERROR: Unknown data block type. Found a type number of "
+ << showbase << hex << int(type) << dec
+ << " (" << int(type) << ")." << endl;
+ result = PARSE_ERROR;
+ }
+
+ return result;
+}
+
+
+/**
+ * The caller is responsible for freeing memory allocated for buffer with a call
+ * to delete [] buffer.
+ */
+int ReadFile(const char* filename, char*& buffer, unsigned long& bufferSize)
+{
+ assert( filename != NULL );
+
+ // Open the file and find its size.
+ fstream file;
+ file.open(filename, ios::in);
+ if (not file)
+ {
+ cerr << "ERROR: Could not open the file: " << filename << endl;
+ return SYSTEM_ERROR;
+ }
+ file.seekg(0, ios::end);
+ if (not file)
+ {
+ cerr << "ERROR: Could not seek in the file: " << filename << endl;
+ return SYSTEM_ERROR;
+ }
+ bufferSize = file.tellg();
+ if (not file)
+ {
+ cerr << "ERROR: Could not get file size for the file: " <<
+ filename << endl;
+ return SYSTEM_ERROR;
+ }
+ file.seekg(0, ios::beg);
+ if (not file)
+ {
+ cerr << "ERROR: Could not seek in the file: " << filename << endl;
+ return SYSTEM_ERROR;
+ }
+
+ // Allocate the memory for the file.
+ try
+ {
+ buffer = new char[bufferSize];
+ }
+ catch (const std::bad_alloc&)
+ {
+ cerr << "ERROR: Out of memory. Tried to allocate " << bufferSize
+ << " bytes." << endl;
+ return SYSTEM_ERROR;
+ }
+
+ file.read(buffer, bufferSize);
+ if (not file)
+ {
+ delete [] buffer;
+ buffer = NULL;
+ bufferSize = 0;
+ cerr << "ERROR: Could not read from file: " << filename << endl;
+ return SYSTEM_ERROR;
+ }
+
+ file.close();
+ if (not file)
+ {
+ delete [] buffer;
+ buffer = NULL;
+ bufferSize = 0;
+ cerr << "ERROR: Could not close the file: " << filename << endl;
+ return SYSTEM_ERROR;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/**
+ * Prints the command line usage of this program to standard error.
+ */
+void PrintUsage()
+{
+ cerr << "Usage: dHLTdumpraw [-help|-h] [-continue] [-type <typename>] <filename>" << endl;
+ cerr << "Where <filename> is the name of a file containing a raw data block." << endl;
+ cerr << "Options:" << endl;
+ cerr << " -help | -h" << endl;
+ cerr << " Displays this message." << endl;
+ cerr << " -continue" << endl;
+ cerr << " If specified, the program will try to continue parsing the data block" << endl;
+ cerr << " as much as possible rather than stopping at the first error." << endl;
+ cerr << " -type <typename>" << endl;
+ cerr << " Forces the contents of the file to be interpreted as a specific" << endl;
+ cerr << " type of data block. Where <typename> can be one of:" << endl;
+ cerr << " trigrecs - trigger records data." << endl;
+ cerr << " trigrecsdebug - debugging information about trigger records." << endl;
+ cerr << " trigchannels - channel debugging in." << endl;
+ cerr << " rechits - reconstructed hits data." << endl;
+ cerr << " channels - channel debugging information from hit reconstruction." << endl;
+ cerr << " clusters - cluster debugging information from hit reconstruction." << endl;
+ cerr << " mansotracks - partial tracks from Manso algorithm." << endl;
+ cerr << " mansocandidates - track candidates considered in the Manso algorithm." << endl;
+ cerr << " singlesdecision - trigger decisions for single tracks." << endl;
+ cerr << " pairsdecision - trigger decisions for track pairs." << endl;
+}
+
+/**
+ * Parse the string passed as the type of the block and return the corresponding
+ * AliHLTMUONDataBlockType value.
+ */
+AliHLTMUONDataBlockType ParseCommandLineType(const char* type)
+{
+ if (strcmp(type, "trigrecs") == 0)
+ {
+ return kTriggerRecordsDataBlock;
+ }
+ else if (strcmp(type, "trigrecsdebug") == 0)
+ {
+ return kTrigRecsDebugDataBlock;
+ }
+ else if (strcmp(type, "trigchannels") == 0)
+ {
+ return kTriggerChannelsDataBlock;
+ }
+ else if (strcmp(type, "rechits") == 0)
+ {
+ return kRecHitsDataBlock;
+ }
+ else if (strcmp(type,"channels") == 0)
+ {
+ return kChannelsDataBlock;
+ }
+ else if (strcmp(type,"clusters") == 0)
+ {
+ return kClustersDataBlock;
+ }
+ else if (strcmp(type, "mansotracks") == 0)
+ {
+ return kMansoTracksDataBlock;
+ }
+ else if (strcmp(type, "mansocandidates") == 0)
+ {
+ return kMansoCandidatesDataBlock;
+ }
+ else if (strcmp(type, "singlesdecision") == 0)
+ {
+ return kSinglesDecisionDataBlock;
+ }
+ else if (strcmp(type, "pairsdecision") == 0)
+ {
+ return kPairsDecisionDataBlock;
+ }
+
+ cerr << "ERROR: Invalid type name '" << type << "' specified for argument -type."
+ << endl << endl;
+ PrintUsage();
+ return kUnknownDataBlock;
+}
+
+/**
+ * Parses the command line.
+ * @param argc Number of arguments as given in main().
+ * @param argv Array of arguments as given in main().
+ * @param filename Receives the pointer to the file name string.
+ * @param type Receives the type of the data block expected, i.e. the
+ * value of the -type flag.
+ * @return A status flag suitable for returning from main(), containing either
+ * EXIT_SUCCESS or CMDLINE_ERROR.
+ */
+int ParseCommandLine(
+ int argc, const char** argv,
+ const char*& filename, bool& continueParse,
+ AliHLTMUONDataBlockType& type
+ )
+{
+ filename = NULL;
+ continueParse = false;
+
+ // Parse the command line.
+ for (int i = 1; i < argc; i++)
+ {
+ if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0)
+ {
+ PrintUsage();
+ return EXIT_SUCCESS;
+ }
+ else if (strcmp(argv[i], "-continue") == 0)
+ {
+ continueParse = true;
+ }
+ else if (strcmp(argv[i], "-type") == 0)
+ {
+ // Now we need to parse the typename in the command line.
+ type = ParseCommandLineType(argv[++i]);
+ if (type == kUnknownDataBlock) return CMDLINE_ERROR;
+ }
+ else
+ {
+ if (filename != NULL)
+ {
+ cerr << "ERROR: Only one file can be specified, but got '"
+ << argv[i] << "', with '" << filename
+ << "' specified earlier." << endl << endl;
+ PrintUsage();
+ return CMDLINE_ERROR;
+ }
+ else
+ filename = argv[i];
+ }
+ }
+
+ // Now check that we have the filename and all the flags we need.
+ if (filename == NULL)
+ {
+ cerr << "ERROR: Missing a file name. You must specify a file to process."
+ << endl << endl;
+ PrintUsage();
+ return CMDLINE_ERROR;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+int main(int argc, const char** argv)
+{
+ const char* filename = NULL;
+ bool continueParse = false;
+ int returnCode = EXIT_SUCCESS;
+ AliHLTMUONDataBlockType type = kUnknownDataBlock;
+ char* buffer = NULL;
+
+ try
+ {
+ returnCode = ParseCommandLine(argc, argv, filename, continueParse, type);
+
+ if (returnCode == EXIT_SUCCESS)
+ {
+ unsigned long bufferSize = 0;
+ returnCode = ReadFile(filename, buffer, bufferSize);
+ if (returnCode == EXIT_SUCCESS)
+ returnCode = ParseBuffer(buffer, bufferSize, continueParse, type);
+ if (buffer != NULL) delete [] buffer;
+ }
+
+ }
+ catch (...)
+ {
+ cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
+ returnCode = FATAL_ERROR;
+ if (buffer != NULL) delete [] buffer;
+ }
+
+ return returnCode;
+}