1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
19 * @file dHLTdumpraw.cxx
20 * @author Artur Szostak <artursz@iafrica.com>,
21 * Seforo Mohlalisi <seforomohlalisi@yahoo.co.uk>
23 * @brief Command line utility to dump dHLT's internal raw data blocks.
26 // We define NDEBUG for the AliHLTMUONDataBlockReader.h header file since this
27 // program by definition handles corrupt data. So we do not need the assertions
28 // in the AliHLTMUONDataBlockReader class to be checked.
32 #include "AliHLTMUONDataBlockReader.h"
33 #if defined(DEBUG) && defined(NDEBUG)
37 #include "AliHLTMUONUtils.h"
49 using std::noshowbase;
59 #define CMDLINE_ERROR 1
61 #define SYSTEM_ERROR 3
65 void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
67 if (padCount == 0) return;
69 cerr << "ERROR: Found the following unexpected rubbish data at the"
70 " end of the data block:" << endl;
71 cerr << "Byte #\tValue\tCharacter" << endl;
72 for (AliHLTUInt32_t i = 0; i < padCount; i++)
74 short value = short(padByte[i]) & 0xFF;
75 char character = padByte[i];
76 cerr << offset + i + 1 << "\t"
77 << noshowbase << hex << "0x" << value << dec << "\t"
83 template <typename FieldType>
85 FieldType& field, const char* buffer, unsigned long bufferSize,
89 const char* fieldptr = reinterpret_cast<const char*>(&field);
90 const char* endptr = buffer + bufferSize;
91 AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
93 if (bufferRemaining < sizeof(field))
95 cout << "..." << endl; // We may be half way through printing a line so end it.
96 cerr << "ERROR: The data block is too short. The header is corrupt." << endl;
99 AliHLTUInt32_t offset = fieldptr - buffer;
100 PrintRubbishData(offset, fieldptr, bufferRemaining);
108 template <typename FieldType>
110 FieldType& field, const char* buffer, unsigned long bufferSize,
114 const char* fieldptr = reinterpret_cast<const char*>(&field);
115 const char* endptr = buffer + bufferSize;
116 AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
118 if (bufferRemaining < sizeof(field))
120 cout << "..." << endl; // We may be half way through printing a line so end it.
121 cerr << "ERROR: The data block is too short. The data is corrupt." << endl;
124 AliHLTUInt32_t offset = fieldptr - buffer;
125 PrintRubbishData(offset, fieldptr, bufferRemaining);
133 template <typename BlockType>
134 int CheckCommonHeader(
135 BlockType& block, const char* /*buffer*/, unsigned long bufferSize,
139 int result = EXIT_SUCCESS;
141 // Check the fRecordWidth field in the common header.
142 if (block.CommonBlockHeader().fRecordWidth !=
143 sizeof(typename BlockType::ElementType))
145 cerr << "ERROR: The record width found in the header is incorrect."
146 " Found a record width of "
147 << block.CommonBlockHeader().fRecordWidth << " bytes, but expected"
148 " a value of " << sizeof(typename BlockType::ElementType)
149 << " bytes." << endl;
150 result = PARSE_ERROR;
151 if (not continueParse) return result;
154 if (not block.BufferSizeOk())
156 cerr << "ERROR: The size of the file is incorrect. It is "
157 << bufferSize << " bytes big, but according"
158 " to the data block header it should be " << block.BytesUsed()
159 << " bytes." << endl;
160 result = PARSE_ERROR;
161 if (not continueParse) return result;
168 template <typename BlockType>
169 AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
171 // Calculate how many entries we can display. If the buffer size is correct
172 // we just use the number of entries the block specifies. Otherwise we need
173 // to calculate it from the buffer size.
174 AliHLTUInt32_t nentries;
175 if (block.BytesUsed() == bufferSize)
177 nentries = block.Nentries();
181 AliHLTInt32_t dataSize = bufferSize
182 - sizeof(typename BlockType::HeaderType);
183 nentries = dataSize / sizeof(typename BlockType::ElementType);
184 if (dataSize % sizeof(typename BlockType::ElementType) > 0)
191 int DumpRecHitStruct(
192 const char* buffer, unsigned long bufferSize,
193 const AliHLTMUONRecHitStruct* hit,
197 // Step through the fields trying to print them.
198 // At each step check if we have not overflowed the buffer. If we have
199 // not, then we can print the field, otherwise we print the left over
200 // bytes assumed to be corrupted rubbish.
201 int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
202 if (result != EXIT_SUCCESS) return result;
203 cout << setw(13) << left << hit->fX << setw(0);
205 result = CheckField(hit->fY, buffer, bufferSize, continueParse);
206 if (result != EXIT_SUCCESS) return result;
207 cout << setw(13) << left << hit->fY << setw(0);
209 result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
210 if (result != EXIT_SUCCESS) return result;
211 cout << hit->fZ << setw(0) << endl;
217 int DumpRecHitsBlock(
218 const char* buffer, unsigned long bufferSize,
222 int result = EXIT_SUCCESS;
223 AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
225 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
226 if (result != EXIT_SUCCESS and not continueParse) return result;
228 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
230 // Print the data block record entries.
231 cout << " X (cm) | Y (cm) | Z (cm)" << endl;
232 cout << "---------------------------------------" << endl;
233 const AliHLTMUONRecHitStruct* entry = block.GetArray();
234 for(AliHLTUInt32_t i = 0; i < nentries; i++)
236 int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
237 if (subResult != EXIT_SUCCESS) return subResult;
244 int DumpTriggerRecordStruct(
245 const char* buffer, unsigned long bufferSize,
246 const AliHLTMUONTriggerRecordStruct* record,
250 // Step through the fields trying to print them.
251 // At each step check if we have not overflowed the buffer. If we have
252 // not, then we can print the field, otherwise we print the left over
253 // bytes assumed to be corrupted rubbish.
254 int result = CheckField(record->fId, buffer, bufferSize, continueParse);
255 if (result != EXIT_SUCCESS) return result;
256 cout << "Trigger Record ID: " << record->fId <<endl;
258 result = CheckField(record->fFlags, buffer, bufferSize, continueParse);
259 if (result != EXIT_SUCCESS) return result;
260 cout << "Flags: " << showbase << hex << record->fFlags << dec;
262 // Print the individual trigger bits.
263 AliHLTMUONParticleSign sign;
265 AliHLTMUONUtils::UnpackTriggerRecordFlags(record->fFlags, sign, hitset);
266 cout << " [Sign: " << sign << ", Hits set on chambers: ";
268 for (AliHLTUInt32_t i = 0; i < 4; i++)
272 cout << (first ? "" : ", ") << i+11;
276 cout << (first ? "none]" : "]") << endl;
278 result = CheckField(record->fPx, buffer, bufferSize, continueParse);
279 if (result != EXIT_SUCCESS) return result;
280 cout << "Momentum: (px = " << record->fPx << ", ";
282 result = CheckField(record->fPy, buffer, bufferSize, continueParse);
283 if (result != EXIT_SUCCESS) return result;
284 cout << "py = " << record->fPy << ", ";
286 result = CheckField(record->fPz, buffer, bufferSize, continueParse);
287 if (result != EXIT_SUCCESS) return result;
288 cout << "pz = " << record->fPz << ") GeV/c"<<endl;
290 cout << "Track hits:" << endl;
291 cout << "Chamber | X (cm) | Y (cm) | Z (cm)" << endl;
292 cout << "------------------------------------------------" << endl;
293 const AliHLTMUONRecHitStruct* hit = &record->fHit[0];
294 for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
296 cout << setw(10) << left << ch + 11 << setw(0);
297 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
298 if (result != EXIT_SUCCESS) return result;
306 int DumpTriggerRecordsBlock(
307 const char* buffer, unsigned long bufferSize,
311 AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
313 int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
314 if (result != EXIT_SUCCESS and not continueParse) return result;
316 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
318 // Print the data block record entries.
319 const AliHLTMUONTriggerRecordStruct* entry = block.GetArray();
320 for(AliHLTUInt32_t i = 0; i < nentries; i++)
322 cout << "============================== Trigger Record number " << i+1
323 << " of " << nentries << " ==============================" << endl;
324 int subResult = DumpTriggerRecordStruct(buffer, bufferSize, entry++, continueParse);
325 if (subResult != EXIT_SUCCESS) return subResult;
332 int DumpTrigRecInfoStruct(const char* buffer, unsigned long bufferSize,
333 const AliHLTMUONTrigRecInfoStruct* debuginfo,
337 // Step through the fields trying to print them.
338 // At each step check if we have not overflowed the buffer. If we have
339 // not, then we can print the field, otherwise we print the left over
340 // bytes assumed to be corrupted rubbish.
341 int result = CheckField(debuginfo->fTrigRecId, buffer, bufferSize, continueParse);
342 if (result != EXIT_SUCCESS) return result;
343 cout << setw(22) << left << debuginfo->fTrigRecId << setw(0);
345 result = CheckField(debuginfo->fDetElemId, buffer, bufferSize, continueParse);
346 if (result != EXIT_SUCCESS) return result;
347 cout << setw(20) << left << debuginfo->fDetElemId << setw(0);
349 result = CheckField(debuginfo->fZmiddle, buffer, bufferSize, continueParse);
350 if(result != EXIT_SUCCESS) return result;
351 cout << setw(30) << left << debuginfo->fZmiddle << setw(0);
353 result = CheckField(debuginfo->fBl, buffer, bufferSize, continueParse);
354 if (result != EXIT_SUCCESS) return result;
355 cout <<debuginfo->fBl << setw(0) << endl;
361 int DumpTrigRecsDebugBlock(
362 const char* buffer, unsigned long bufferSize,
366 AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
368 int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
369 if (result != EXIT_SUCCESS and not continueParse) return result;
371 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
373 // Print the data block record entries.
374 cout << "Trigger Record ID | Detector ID | Momentum X Component (Gev/c) | Integrated Magnetic Field (T.m)" << endl;
375 cout << "--------------------------------------------------------------------------------------------------" << endl;
376 const AliHLTMUONTrigRecInfoStruct* entry = block.GetArray();
377 for(AliHLTUInt32_t i = 0; i < nentries; i++)
379 int subResult = DumpTrigRecInfoStruct(buffer, bufferSize, entry++, continueParse);
380 if (subResult != EXIT_SUCCESS) return subResult;
387 int DumpTriggerChannelStruct(const char* buffer, unsigned long bufferSize,
388 const AliHLTMUONTriggerChannelStruct* triggerchannel,
392 // Step through the fields trying to print them.
393 // At each step check if we have not overflowed the buffer. If we have
394 // not, then we can print the field, otherwise we print the left over
395 // bytes assumed to be corrupted rubbish.
396 int result = CheckField(triggerchannel->fTrigRecId, buffer, bufferSize, continueParse);
397 if (result != EXIT_SUCCESS) return result;
398 cout << setw(25) << left << triggerchannel->fTrigRecId << setw(0);
400 result = CheckField(triggerchannel->fChamber, buffer, bufferSize, continueParse);
401 if (result != EXIT_SUCCESS) return result;
402 cout << setw(13) << left << triggerchannel->fChamber << setw(0);
404 result = CheckField(triggerchannel->fSignal, buffer, bufferSize, continueParse);
405 if (result != EXIT_SUCCESS) return result;
406 cout << setw(10) << left << triggerchannel->fSignal << setw(0);
408 result = CheckField(triggerchannel->fRawDataWord, buffer, bufferSize, continueParse);
409 if(result != EXIT_SUCCESS) return result;
410 cout << showbase << hex << triggerchannel->fRawDataWord << dec << setw(0) << endl;
415 int DumpTriggerChannelsBlock(
416 const char* buffer, unsigned long bufferSize,
420 int result = EXIT_SUCCESS;
421 AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
423 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
424 if (result != EXIT_SUCCESS and not continueParse) return result;
426 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
428 // Print the data block record entries.
429 cout << " Trigger Record ID | Chamber | Signal | Raw Data Word " << endl;
430 cout << "--------------------------------------------------------------" << endl;
431 const AliHLTMUONTriggerChannelStruct* entry = block.GetArray();
432 for(AliHLTUInt32_t i = 0; i < nentries; i++)
434 int subResult = DumpTriggerChannelStruct(buffer, bufferSize, entry++, continueParse);
435 if (subResult != EXIT_SUCCESS) return subResult;
442 int DumpClusterStruct(
443 const char* buffer, unsigned long bufferSize,
444 const AliHLTMUONClusterStruct* cluster,
448 // Step through the fields trying to print them.
449 // At each step check if we have not overflowed the buffer. If we have
450 // not, then we can print the field, otherwise we print the left over
451 // bytes assumed to be corrupted rubbish.
452 int result = CheckField(cluster->fId, buffer, bufferSize, continueParse);
453 if (result != EXIT_SUCCESS) return result;
454 cout << "cluster->fId: " << cluster->fId << "\t";
456 result = CheckField(cluster->fDetElemId, buffer, bufferSize, continueParse);
457 if (result != EXIT_SUCCESS) return result;
458 cout << "cluster->fDetElemId: " << cluster->fDetElemId << "\t";
460 result = CheckField(cluster->fNchannels, buffer, bufferSize, continueParse);
461 if(result != EXIT_SUCCESS) return result;
462 cout << "cluster->fNchannels: " << cluster->fNchannels <<endl;
464 cout << " Corresponding Hit: "<< endl;
465 cout << " X (cm) | Y (cm) | Z (cm)" << endl;
466 cout << "---------------------------------------" << endl;
467 const AliHLTMUONRecHitStruct * hit = & cluster->fHit;
468 result = DumpRecHitStruct(buffer, bufferSize, hit, continueParse);
474 int DumpClustersBlock(
475 const char* buffer, unsigned long bufferSize,
479 int result = EXIT_SUCCESS;
480 AliHLTMUONClustersBlockReader block(buffer, bufferSize);
482 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
483 if (result != EXIT_SUCCESS and not continueParse) return result;
485 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
487 // Print the data block record entries.
488 const AliHLTMUONClusterStruct* entry = block.GetArray();
489 for(AliHLTUInt32_t i = 0; i < nentries; i++)
491 cout << " ===================================================== Cluster Number "
492 << i+1 << "==================================================" << endl;
493 int subResult = DumpClusterStruct(buffer, bufferSize, entry++, continueParse);
494 if (subResult != EXIT_SUCCESS) return subResult;
501 int DumpChannelStruct(
502 const char* buffer, unsigned long bufferSize,
503 const AliHLTMUONChannelStruct* channel,
507 // Step through the fields trying to print them.
508 // At each step check if we have not overflowed the buffer. If we have
509 // not, then we can print the field, otherwise we print the left over
510 // bytes assumed to be corrupted rubbish.
511 int result = CheckField(channel->fClusterId, buffer, bufferSize, continueParse);
512 if (result != EXIT_SUCCESS) return result;
513 cout << setw(16) << left << channel->fClusterId << setw(0);
515 result = CheckField(channel->fManu, buffer, bufferSize, continueParse);
516 if (result != EXIT_SUCCESS) return result;
517 cout << setw(16) << left << channel->fManu << setw(0);
519 result = CheckField(channel->fChannelAddress, buffer, bufferSize, continueParse);
520 if (result != EXIT_SUCCESS) return result;
521 cout << setw(19) << left << channel->fChannelAddress << setw(0);
523 result = CheckField(channel->fSignal, buffer, bufferSize, continueParse);
524 if(result != EXIT_SUCCESS) return result;
525 cout << setw(16) << left << channel->fSignal << setw(0);
527 result = CheckField(channel->fRawDataWord, buffer, bufferSize, continueParse);
528 if(result != EXIT_SUCCESS) return result;
529 cout << showbase << hex << channel->fRawDataWord << dec << setw(0) <<endl;
535 int DumpChannelsBlock(
536 const char* buffer, unsigned long bufferSize,
540 int result = EXIT_SUCCESS;
541 AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
543 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
544 if (result != EXIT_SUCCESS and not continueParse) return result;
546 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
548 // Print the data block record entries.
549 cout << "Cluster Id | Manu Address | Channel Address | Signal Value | Raw Data Word " <<endl;
550 cout << "-------------------------------------------------------------------------------" <<endl;
551 const AliHLTMUONChannelStruct* entry = block.GetArray();
552 for(AliHLTUInt32_t i = 0; i < nentries; i++)
554 int subResult = DumpChannelStruct(buffer, bufferSize, entry++, continueParse);
555 if (subResult != EXIT_SUCCESS) return subResult;
561 int DumpMansoTrackStruct(
562 const char* buffer, unsigned long bufferSize,
563 const AliHLTMUONMansoTrackStruct* track,
567 // Step through the fields trying to print them.
568 // At each step check if we have not overflowed the buffer. If we have
569 // not, then we can print the field, otherwise we print the left over
570 // bytes assumed to be corrupted rubbish.
571 int result = CheckField(track->fId, buffer, bufferSize, continueParse);
572 if (result != EXIT_SUCCESS) return result;
573 cout << "Track ID: " << track->fId << "\t";
575 result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
576 if (result != EXIT_SUCCESS) return result;
577 cout << "Trigger Record ID: " << track->fTrigRec << endl;
579 result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
580 if (result != EXIT_SUCCESS) return result;
581 cout << "Flags: " << showbase << hex << track->fFlags << dec;
583 // Print the individual trigger bits.
584 AliHLTMUONParticleSign sign;
586 AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
587 cout << " [Sign: " << sign << ", Hits set on chambers: ";
589 for (AliHLTUInt32_t i = 0; i < 4; i++)
593 cout << (first ? "" : ", ") << i+7;
597 cout << (first ? "none]" : "]") << endl;
599 result = CheckField(track->fPx, buffer, bufferSize, continueParse);
600 if (result != EXIT_SUCCESS) return result;
601 cout << "Momentum: (px = " << track->fPx << ", ";
603 result = CheckField(track->fPy, buffer, bufferSize, continueParse);
604 if (result != EXIT_SUCCESS) return result;
605 cout << "py = " << track->fPy << ", ";
607 result = CheckField(track->fPz, buffer, bufferSize, continueParse);
608 if (result != EXIT_SUCCESS) return result;
609 cout << "pz = " << track->fPz << ") GeV/c\t";
611 result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
612 if (result != EXIT_SUCCESS) return result;
613 cout << "Chi squared fit: " << track->fChi2 << endl;
615 cout << "Track hits:" << endl;
616 cout << "Chamber | X (cm) | Y (cm) | Z (cm)" << endl;
617 cout << "------------------------------------------------" << endl;
618 const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
619 for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
621 cout << setw(10) << left << ch + 7 << setw(0);
622 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
623 if (result != EXIT_SUCCESS) return result;
630 int DumpMansoTracksBlock(
631 const char* buffer, unsigned long bufferSize,
635 int result = EXIT_SUCCESS;
636 AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
638 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
639 if (result != EXIT_SUCCESS and not continueParse) return result;
641 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
643 // Print the data block record entries.
644 const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
645 for(AliHLTUInt32_t i = 0; i < nentries; i++)
647 cout << "============================== Manso track number " << i+1
648 << " of " << nentries << " ==============================" << endl;
649 int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
650 if (subResult != EXIT_SUCCESS) return subResult;
657 int DumpMansoRoIStruct(
658 const char* buffer, unsigned long bufferSize,
659 const AliHLTMUONMansoRoIStruct* roi,
663 // Step through the fields trying to print them.
664 // At each step check if we have not overflowed the buffer. If we have
665 // not, then we can print the field, otherwise we print the left over
666 // bytes assumed to be corrupted rubbish.
667 int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
668 if (result != EXIT_SUCCESS) return result;
669 cout << setw(13) << left << roi->fX << setw(0);
671 result = CheckField(roi->fY, buffer, bufferSize, continueParse);
672 if (result != EXIT_SUCCESS) return result;
673 cout << setw(13) << left << roi->fY << setw(0);
675 result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
676 if (result != EXIT_SUCCESS) return result;
677 cout << setw(13) << left << roi->fZ << setw(0);
679 result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
680 if (result != EXIT_SUCCESS) return result;
681 cout << roi->fRadius << setw(0) << endl;
687 int DumpMansoCandidateStruct(
688 const char* buffer, unsigned long bufferSize,
689 const AliHLTMUONMansoCandidateStruct* candidate,
693 int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
694 if (result != EXIT_SUCCESS) return result;
696 cout << "Regions of interest:" << endl;
697 cout << "Chamber | X (cm) | Y (cm) | Z (cm) | Radius (cm)" << endl;
698 cout << "-------------------------------------------------------------" << endl;
699 const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
700 for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
702 cout << setw(10) << ch + 7;
703 result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
704 if (result != EXIT_SUCCESS) return result;
710 int DumpMansoCandidatesBlock(
711 const char* buffer, unsigned long bufferSize,
715 int result = EXIT_SUCCESS;
716 AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
718 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
719 if (result != EXIT_SUCCESS and not continueParse) return result;
721 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
723 // Print the data block record entries.
724 const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
725 for(AliHLTUInt32_t i = 0; i < nentries; i++)
727 cout << "=========================== Manso track candidate number " << i+1
728 << " of " << nentries << " ===========================" << endl;
729 int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
730 if (subResult != EXIT_SUCCESS) return subResult;
737 int DumpSinglesDecisionBlockHeader(
738 const char* buffer, unsigned long bufferSize,
739 const AliHLTMUONSinglesDecisionBlockStruct* header,
743 // Step through the header fields trying to print them.
744 // At each step check if we have not overflowed the buffer, if we have
745 // not then we can print the field, otherwise we print the left over
746 // bytes assumed to be corrupted rubbish.
747 int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
748 if (result != EXIT_SUCCESS) return result;
749 cout << " Number of low pt triggers: " << header->fNlowPt << endl;
751 result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
752 if (result != EXIT_SUCCESS) return result;
753 cout << "Number of high pt triggers: " << header->fNhighPt << endl;
759 int DumpTrackDecisionStruct(
760 const char* buffer, unsigned long bufferSize,
761 const AliHLTMUONTrackDecisionStruct* decision,
765 // Step through the fields trying to print them.
766 // At each step check if we have not overflowed the buffer. If we have
767 // not, then we can print the field, otherwise we print the left over
768 // bytes assumed to be corrupted rubbish.
769 int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
770 if (result != EXIT_SUCCESS) return result;
771 cout << setw(13) << left << decision->fTrackId << setw(0);
773 result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
774 if (result != EXIT_SUCCESS) return result;
775 cout << setw(12) << left << showbase << hex << decision->fTriggerBits
778 // Print the individual trigger bits.
780 AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
781 cout << setw(7) << left << (highPt ? "yes" : "no");
782 cout << setw(8) << left << (lowPt ? "yes" : "no");
784 result = CheckField(decision->fPt, buffer, bufferSize, continueParse);
785 if (result != EXIT_SUCCESS) return result;
786 cout << setw(0) << decision->fPt << endl;
792 int DumpSinglesDecisionBlock(
793 const char* buffer, unsigned long bufferSize,
797 int result = EXIT_SUCCESS;
798 AliHLTMUONSinglesDecisionBlockReader block(buffer, bufferSize);
800 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
801 if (result != EXIT_SUCCESS and not continueParse) return result;
803 // Dump the rest of the block header.
804 const AliHLTMUONSinglesDecisionBlockStruct* header = &block.BlockHeader();
805 int subResult = DumpSinglesDecisionBlockHeader(buffer, bufferSize, header, continueParse);
806 if (subResult != EXIT_SUCCESS) return subResult;
808 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
810 // Print the data block record entries.
811 cout << " | Trigger Bits |" << endl;
812 cout << "Track ID | Raw HighPt LowPt | pT" << endl;
813 cout << "----------------------------------------------------" << endl;
814 const AliHLTMUONTrackDecisionStruct* entry = block.GetArray();
815 for(AliHLTUInt32_t i = 0; i < nentries; i++)
817 subResult = DumpTrackDecisionStruct(buffer, bufferSize, entry++, continueParse);
818 if (subResult != EXIT_SUCCESS) return subResult;
825 int DumpPairsDecisionBlockHeader(
826 const char* buffer, unsigned long bufferSize,
827 const AliHLTMUONPairsDecisionBlockStruct* header,
831 // Step through the header fields trying to print them.
832 // At each step check if we have not overflowed the buffer, if we have
833 // not then we can print the field, otherwise we print the left over
834 // bytes assumed to be corrupted rubbish.
835 int result = CheckHeaderField(header->fNunlikeAnyPt, buffer, bufferSize, continueParse);
836 if (result != EXIT_SUCCESS) return result;
837 cout << " Number of unlike all pt triggers: " << header->fNunlikeAnyPt << endl;
839 result = CheckHeaderField(header->fNunlikeLowPt, buffer, bufferSize, continueParse);
840 if (result != EXIT_SUCCESS) return result;
841 cout << " Number of unlike low pt triggers: " << header->fNunlikeLowPt << endl;
843 result = CheckHeaderField(header->fNunlikeHighPt, buffer, bufferSize, continueParse);
844 if (result != EXIT_SUCCESS) return result;
845 cout << " Number of unlike high pt triggers: " << header->fNunlikeHighPt << endl;
847 result = CheckHeaderField(header->fNlikeAnyPt, buffer, bufferSize, continueParse);
848 if (result != EXIT_SUCCESS) return result;
849 cout << " Number of like any pt triggers: " << header->fNlikeAnyPt << endl;
851 result = CheckHeaderField(header->fNlikeLowPt, buffer, bufferSize, continueParse);
852 if (result != EXIT_SUCCESS) return result;
853 cout << " Number of like low pt triggers: " << header->fNlikeLowPt << endl;
855 result = CheckHeaderField(header->fNlikeHighPt, buffer, bufferSize, continueParse);
856 if (result != EXIT_SUCCESS) return result;
857 cout << " Number of like high pt triggers: " << header->fNlikeHighPt << endl;
859 result = CheckHeaderField(header->fNmassAny, buffer, bufferSize, continueParse);
860 if (result != EXIT_SUCCESS) return result;
861 cout << " Number of all invariant mass triggers: " << header->fNmassAny << endl;
863 result = CheckHeaderField(header->fNmassLow, buffer, bufferSize, continueParse);
864 if (result != EXIT_SUCCESS) return result;
865 cout << " Number of low invariant mass triggers: " << header->fNmassLow << endl;
867 result = CheckHeaderField(header->fNmassHigh, buffer, bufferSize, continueParse);
868 if (result != EXIT_SUCCESS) return result;
869 cout << "Number of high invariant mass triggers: " << header->fNmassHigh << endl;
875 int DumpPairDecisionStruct(
876 const char* buffer, unsigned long bufferSize,
877 const AliHLTMUONPairDecisionStruct* decision,
881 // Step through the fields trying to print them.
882 // At each step check if we have not overflowed the buffer. If we have
883 // not, then we can print the field, otherwise we print the left over
884 // bytes assumed to be corrupted rubbish.
885 int result = CheckField(decision->fTrackAId, buffer, bufferSize, continueParse);
886 if (result != EXIT_SUCCESS) return result;
887 cout << setw(13) << left << decision->fTrackAId << setw(0);
889 result = CheckField(decision->fTrackBId, buffer, bufferSize, continueParse);
890 if (result != EXIT_SUCCESS) return result;
891 cout << setw(13) << left << decision->fTrackBId << setw(0);
893 result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
894 if (result != EXIT_SUCCESS) return result;
895 cout << setw(12) << left << showbase << hex << decision->fTriggerBits
898 // Print the individual trigger bits.
899 bool highMass, lowMass, unlike;
900 AliHLTUInt8_t highPtCount, lowPtCount;
901 AliHLTMUONUtils::UnpackPairDecisionBits(
902 decision->fTriggerBits,
903 highMass, lowMass, unlike, highPtCount, lowPtCount
905 cout << setw(7) << left << (highMass ? "yes" : "no");
906 cout << setw(7) << left << (lowMass ? "yes" : "no");
907 cout << setw(7) << left << (unlike ? "yes" : "no");
908 cout << setw(6) << left << AliHLTUInt16_t(highPtCount);
909 cout << setw(8) << left << AliHLTUInt16_t(lowPtCount);
912 result = CheckField(decision->fInvMass, buffer, bufferSize, continueParse);
913 if (result != EXIT_SUCCESS) return result;
914 cout << decision->fInvMass << endl;
920 int DumpPairsDecisionBlock(
921 const char* buffer, unsigned long bufferSize,
925 int result = EXIT_SUCCESS;
926 AliHLTMUONPairsDecisionBlockReader block(buffer, bufferSize);
928 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
929 if (result != EXIT_SUCCESS and not continueParse) return result;
931 // Dump the rest of the block header.
932 const AliHLTMUONPairsDecisionBlockStruct* header = &block.BlockHeader();
933 int subResult = DumpPairsDecisionBlockHeader(buffer, bufferSize, header, continueParse);
934 if (subResult != EXIT_SUCCESS) return subResult;
936 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
938 // Print the data block record entries.
939 cout << " | | Trigger Bits |" << endl;
940 cout << "Track A ID | Track B ID | Raw HiMass LoMass Unlike HiPt# LoPt# | Invariant mass" << endl;
941 cout << "----------------------------------------------------------------------------------------" << endl;
942 const AliHLTMUONPairDecisionStruct* entry = block.GetArray();
943 for(AliHLTUInt32_t i = 0; i < nentries; i++)
945 subResult = DumpPairDecisionStruct(buffer, bufferSize, entry++, continueParse);
946 if (subResult != EXIT_SUCCESS) return subResult;
953 int DumpCommonHeader(
954 const char* buffer, unsigned long bufferSize,
955 const AliHLTMUONDataBlockHeader* header, bool continueParse
958 // Step through the header fields trying to print them.
959 // At each step check if we have not overflowed the buffer, if we have
960 // not then we can print the field, otherwise we print the left over
961 // bytes assumed to be corrupted rubbish.
962 int result = CheckHeaderField(header->fType, buffer, bufferSize, continueParse);
963 if (result != EXIT_SUCCESS) return result;
964 AliHLTMUONDataBlockType type = AliHLTMUONDataBlockType(header->fType);
965 cout << " Block type: " << type << endl;
967 result = CheckHeaderField(header->fRecordWidth, buffer, bufferSize, continueParse);
968 if (result != EXIT_SUCCESS) return result;
969 cout << " Record width: " << header->fRecordWidth << endl;
971 result = CheckHeaderField(header->fNrecords, buffer, bufferSize, continueParse);
972 if (result != EXIT_SUCCESS) return result;
973 cout << "Number of entries: " << header->fNrecords << endl;
980 const char* buffer, unsigned long bufferSize,
981 bool continueParse, AliHLTMUONDataBlockType type
984 assert( buffer != NULL );
985 int result = EXIT_SUCCESS;
987 if (bufferSize < sizeof(AliHLTMUONDataBlockHeader))
989 cerr << "ERROR: The size of the file is too small to contain a"
990 " valid data block." << endl;
991 result = PARSE_ERROR;
992 if (not continueParse) return result;
994 const AliHLTMUONDataBlockHeader* header =
995 reinterpret_cast<const AliHLTMUONDataBlockHeader*>(buffer);
997 int subResult = DumpCommonHeader(buffer, bufferSize, header, continueParse);
998 if (subResult != EXIT_SUCCESS) return subResult;
1001 // Check if the block type in the header corresponds to the type given
1002 // by the '-type' command line parameter. If they do not then print an
1003 // error or big fat warning message and force interpretation of the data
1004 // block with the type given by '-type'.
1005 AliHLTMUONDataBlockType headerType = AliHLTMUONDataBlockType(header->fType);
1007 if (type == kUnknownDataBlock)
1009 // -type not used in the command line so just use what is given
1010 // by the data block header.
1013 else if (type != headerType)
1015 cerr << "WARNING: The data block header indicates a type"
1016 " different from what was specified on the command line."
1017 " The data could be corrupt."
1019 cerr << "WARNING: The type value in the file is "
1020 << showbase << hex << header->fType
1021 << " (" << headerType << "), but on the command line it is "
1022 << showbase << hex << int(type) << dec
1023 << " (" << type << ")."
1025 cerr << "WARNING: Will force the interpretation of the data block"
1026 " with a type of " << type << "." << endl;
1029 // Now we know what type the data block is supposed to be so we can
1030 // dump it to screen with the appropriate dump routine.
1033 case kTriggerRecordsDataBlock:
1034 subResult = DumpTriggerRecordsBlock(buffer, bufferSize, continueParse);
1035 if (subResult != EXIT_SUCCESS) result = subResult;
1037 case kTrigRecsDebugDataBlock:
1038 subResult = DumpTrigRecsDebugBlock(buffer, bufferSize, continueParse);
1039 if (subResult != EXIT_SUCCESS) result = subResult;
1041 case kTriggerChannelsDataBlock:
1042 subResult = DumpTriggerChannelsBlock(buffer, bufferSize, continueParse);
1043 if (subResult != EXIT_SUCCESS) result = subResult;
1045 case kRecHitsDataBlock:
1046 subResult = DumpRecHitsBlock(buffer, bufferSize, continueParse);
1047 if (subResult != EXIT_SUCCESS) result = subResult;
1049 case kClustersDataBlock:
1050 subResult = DumpClustersBlock(buffer, bufferSize, continueParse);
1051 if (subResult != EXIT_SUCCESS) result = subResult;
1053 case kChannelsDataBlock:
1054 return DumpChannelsBlock(buffer, bufferSize, continueParse);
1055 if (subResult != EXIT_SUCCESS) result = subResult;
1057 case kMansoTracksDataBlock:
1058 subResult = DumpMansoTracksBlock(buffer, bufferSize, continueParse);
1059 if (subResult != EXIT_SUCCESS) result = subResult;
1061 case kMansoCandidatesDataBlock:
1062 subResult = DumpMansoCandidatesBlock(buffer, bufferSize, continueParse);
1063 if (subResult != EXIT_SUCCESS) result = subResult;
1065 case kSinglesDecisionDataBlock:
1066 subResult = DumpSinglesDecisionBlock(buffer, bufferSize, continueParse);
1067 if (subResult != EXIT_SUCCESS) result = subResult;
1069 case kPairsDecisionDataBlock:
1070 return DumpPairsDecisionBlock(buffer, bufferSize, continueParse);
1071 if (subResult != EXIT_SUCCESS) result = subResult;
1074 cout << "ERROR: Unknown data block type. Found a type number of "
1075 << showbase << hex << int(type) << dec
1076 << " (" << int(type) << ")." << endl;
1077 result = PARSE_ERROR;
1085 * The caller is responsible for freeing memory allocated for buffer with a call
1086 * to delete [] buffer.
1088 int ReadFile(const char* filename, char*& buffer, unsigned long& bufferSize)
1090 assert( filename != NULL );
1092 // Open the file and find its size.
1094 file.open(filename, ios::in);
1097 cerr << "ERROR: Could not open the file: " << filename << endl;
1098 return SYSTEM_ERROR;
1100 file.seekg(0, ios::end);
1103 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1104 return SYSTEM_ERROR;
1106 bufferSize = file.tellg();
1109 cerr << "ERROR: Could not get file size for the file: " <<
1111 return SYSTEM_ERROR;
1113 file.seekg(0, ios::beg);
1116 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1117 return SYSTEM_ERROR;
1120 // Allocate the memory for the file.
1123 buffer = new char[bufferSize];
1125 catch (const std::bad_alloc&)
1127 cerr << "ERROR: Out of memory. Tried to allocate " << bufferSize
1128 << " bytes." << endl;
1129 return SYSTEM_ERROR;
1132 file.read(buffer, bufferSize);
1138 cerr << "ERROR: Could not read from file: " << filename << endl;
1139 return SYSTEM_ERROR;
1148 cerr << "ERROR: Could not close the file: " << filename << endl;
1149 return SYSTEM_ERROR;
1152 return EXIT_SUCCESS;
1156 * Prints the command line usage of this program to standard error.
1158 void PrintUsage(bool asError = true)
1160 std::ostream& os = asError ? cerr : cout;
1161 os << "Usage: dHLTdumpraw [-help|-h] [-continue] [-type <typename>] <filename>" << endl;
1162 os << "Where <filename> is the name of a file containing a raw data block." << endl;
1163 os << "Options:" << endl;
1164 os << " -help | -h" << endl;
1165 os << " Displays this message." << endl;
1166 os << " -continue" << endl;
1167 os << " If specified, the program will try to continue parsing the data block" << endl;
1168 os << " as much as possible rather than stopping at the first error." << endl;
1169 os << " -type <typename>" << endl;
1170 os << " Forces the contents of the subsequent files specified on the command" << endl;
1171 os << " line to be interpreted as a specific type of data block." << endl;
1172 os << " Where <typename> can be one of:" << endl;
1173 os << " trigrecs - trigger records data." << endl;
1174 os << " trigrecsdebug - debugging information about trigger records." << endl;
1175 os << " trigchannels - channel debugging in." << endl;
1176 os << " rechits - reconstructed hits data." << endl;
1177 os << " channels - channel debugging information from hit reconstruction." << endl;
1178 os << " clusters - cluster debugging information from hit reconstruction." << endl;
1179 os << " mansotracks - partial tracks from Manso algorithm." << endl;
1180 os << " mansocandidates - track candidates considered in the Manso algorithm." << endl;
1181 os << " singlesdecision - trigger decisions for single tracks." << endl;
1182 os << " pairsdecision - trigger decisions for track pairs." << endl;
1183 os << " autodetect - the type of the data block will be automatically" << endl;
1184 os << " detected." << endl;
1188 * Parse the string passed as the type of the block and return the corresponding
1189 * AliHLTMUONDataBlockType value.
1191 AliHLTMUONDataBlockType ParseCommandLineType(const char* type)
1193 if (strcmp(type, "trigrecs") == 0)
1195 return kTriggerRecordsDataBlock;
1197 else if (strcmp(type, "trigrecsdebug") == 0)
1199 return kTrigRecsDebugDataBlock;
1201 else if (strcmp(type, "trigchannels") == 0)
1203 return kTriggerChannelsDataBlock;
1205 else if (strcmp(type, "rechits") == 0)
1207 return kRecHitsDataBlock;
1209 else if (strcmp(type,"channels") == 0)
1211 return kChannelsDataBlock;
1213 else if (strcmp(type,"clusters") == 0)
1215 return kClustersDataBlock;
1217 else if (strcmp(type, "mansotracks") == 0)
1219 return kMansoTracksDataBlock;
1221 else if (strcmp(type, "mansocandidates") == 0)
1223 return kMansoCandidatesDataBlock;
1225 else if (strcmp(type, "singlesdecision") == 0)
1227 return kSinglesDecisionDataBlock;
1229 else if (strcmp(type, "pairsdecision") == 0)
1231 return kPairsDecisionDataBlock;
1234 cerr << "ERROR: Invalid type name '" << type << "' specified for argument -type."
1237 return kUnknownDataBlock;
1241 * Parses the command line.
1242 * @param argc Number of arguments as given in main().
1243 * @param argv Array of arguments as given in main().
1244 * @param filenames Pointer to buffer storing file name strings.
1245 * @param numOfFiles Receives the number of file name strings that were found
1246 * and added to 'filenames'.
1247 * @param filetypes Array that receives the type of the data block expected, i.e.
1248 * the value of the -type flag for the corresponding file.
1249 * @return A status flag suitable for returning from main(), containing either
1250 * EXIT_SUCCESS or CMDLINE_ERROR.
1252 int ParseCommandLine(
1255 const char** filenames,
1257 bool& continueParse,
1258 AliHLTMUONDataBlockType* filetypes
1262 continueParse = false;
1263 AliHLTMUONDataBlockType currentType = kUnknownDataBlock;
1265 // Parse the command line.
1266 for (int i = 1; i < argc; i++)
1268 if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0)
1271 return EXIT_SUCCESS;
1273 else if (strcmp(argv[i], "-continue") == 0)
1275 continueParse = true;
1277 else if (strcmp(argv[i], "-type") == 0)
1281 cerr << "ERROR: Missing a type specifier" << endl;
1283 return CMDLINE_ERROR;
1285 // Now we need to parse the typename in the command line.
1286 if (strcmp(argv[i], "autodetect") == 0)
1288 currentType = kUnknownDataBlock;
1292 currentType = ParseCommandLineType(argv[i]);
1293 if (currentType == kUnknownDataBlock) return CMDLINE_ERROR;
1298 assert( numOfFiles < argc );
1299 filenames[numOfFiles] = argv[i];
1300 filetypes[numOfFiles] = currentType;
1305 // Now check that we have at least one filename and all the flags we need.
1306 if (numOfFiles == 0)
1308 cerr << "ERROR: Missing a file name. You must specify at least one file to process."
1311 return CMDLINE_ERROR;
1314 return EXIT_SUCCESS;
1318 int main(int argc, const char** argv)
1320 // Test endianess of this machine during runtime and print warning if it is not
1327 endianTest.dword = 0x1;
1328 if (endianTest.byte[0] != 0x1)
1330 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1331 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1332 cerr << "!! !!" << endl;
1333 cerr << "!! This is not a little endian machine, but dHLT raw data is normally !!" << endl;
1334 cerr << "!! generated in little endian format. Unless you are looking at localy !!" << endl;
1335 cerr << "!! created simulated data, then this program will not show you correct !!" << endl;
1336 cerr << "!! output. !!" << endl;
1337 cerr << "!! !!" << endl;
1338 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1339 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1345 bool continueParse = false;
1346 int returnCode = EXIT_SUCCESS;
1347 char* buffer = NULL;
1351 // There will be at least 'argc' number of filenames.
1352 typedef const char* AnsiString;
1353 const char** filename = new AnsiString[argc];
1354 AliHLTMUONDataBlockType* filetype = new AliHLTMUONDataBlockType[argc];
1356 returnCode = ParseCommandLine(argc, argv, filename, numOfFiles, continueParse, filetype);
1358 if (returnCode == EXIT_SUCCESS)
1360 for (int i = 0; i < numOfFiles; i++)
1362 unsigned long bufferSize = 0;
1363 returnCode = ReadFile(filename[i], buffer, bufferSize);
1364 if (returnCode != EXIT_SUCCESS) break;
1367 cout << "########## Start of dump for file: " << filename[i] << " ##########" << endl;
1369 int result = ParseBuffer(buffer, bufferSize, continueParse, filetype[i]);
1370 if (buffer != NULL) delete [] buffer;
1371 if (result != EXIT_SUCCESS)
1373 returnCode = result;
1374 if (not continueParse) break;
1378 cout << "########## End of dump for file: " << filename[i] << " ##########" << endl;
1388 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
1389 returnCode = FATAL_ERROR;
1390 if (buffer != NULL) delete [] buffer;