]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/MUON/utils/dHLTdumpraw.cxx
Adding a utility program to perform a logical dump of internal dHLT data block struct...
[u/mrichter/AliRoot.git] / HLT / MUON / utils / dHLTdumpraw.cxx
CommitLineData
3dad52b0 1/**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18/**
19 * @file dHLTdumpraw.cxx
20 * @author Artur Szostak <artursz@iafrica.com>,
21 * Seforo Mohlalisi <seforomohlalisi@yahoo.co.uk>
22 * @date
23 * @brief Command line utility to dump dHLT's internal raw data blocks.
24 */
25
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.
29#define NDEBUG
30#include "AliHLTMUONDataBlockReader.h"
31#undef NDEBUG
32#include "AliHLTMUONUtils.h"
33
34#include <endian.h>
35#ifndef LITTLE_ENDIAN
36#error Handling of internal data for non little endian machines not yet implemented.
37#endif
38
39#include <stdlib.h>
40#include <cassert>
41#include <new>
42#include <fstream>
43
44#include <iostream>
45using std::cout;
46using std::cerr;
47using std::endl;
48using std::showbase;
49using std::noshowbase;
50using std::hex;
51using std::dec;
52
53#include <iomanip>
54using std::setw;
55using std::left;
56using std::internal;
57
58
59#define CMDLINE_ERROR 1
60#define PARSE_ERROR 2
61#define SYSTEM_ERROR 3
62#define FATAL_ERROR 4
63
64
65void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
66{
67 if (padCount == 0) return;
68
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++)
73 {
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"
78 << character << endl;
79 }
80}
81
82
83template <typename FieldType>
84int CheckHeaderField(
85 FieldType& field, const char* buffer, unsigned long bufferSize,
86 bool continueParse
87 )
88{
89 const char* fieldptr = reinterpret_cast<const char*>(&field);
90 const char* endptr = buffer + bufferSize;
91 AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
92
93 if (bufferRemaining < sizeof(field))
94 {
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;
97 if (continueParse)
98 {
99 AliHLTUInt32_t offset = fieldptr - buffer;
100 PrintRubbishData(offset, fieldptr, bufferRemaining);
101 }
102 return PARSE_ERROR;
103 }
104 return EXIT_SUCCESS;
105}
106
107
108template <typename FieldType>
109int CheckField(
110 FieldType& field, const char* buffer, unsigned long bufferSize,
111 bool continueParse
112 )
113{
114 const char* fieldptr = reinterpret_cast<const char*>(&field);
115 const char* endptr = buffer + bufferSize;
116 AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
117
118 if (bufferRemaining < sizeof(field))
119 {
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;
122 if (continueParse)
123 {
124 AliHLTUInt32_t offset = fieldptr - buffer;
125 PrintRubbishData(offset, fieldptr, bufferRemaining);
126 }
127 return PARSE_ERROR;
128 }
129 return EXIT_SUCCESS;
130}
131
132
133template <typename BlockType>
134int CheckCommonHeader(
135 BlockType& block, const char* buffer, unsigned long bufferSize,
136 bool continueParse
137 )
138{
139 int result = EXIT_SUCCESS;
140
141 // Check the fRecordWidth field in the common header.
142 if (block.CommonBlockHeader().fRecordWidth !=
143 sizeof(typename BlockType::ElementType))
144 {
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;
152 }
153
154 if (not block.BufferSizeOk())
155 {
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;
162 }
163
164 return result;
165}
166
167
168template <typename BlockType>
169AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
170{
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)
176 {
177 nentries = block.Nentries();
178 }
179 else
180 {
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)
185 nentries++;
186 }
187 return nentries;
188}
189
190
191int DumpTriggerRecordsBlock(
192 const char* buffer, unsigned long bufferSize,
193 bool continueParse
194 )
195{
196 AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
197 // TODO
198 return EXIT_SUCCESS;
199}
200
201
202int DumpTrigRecsDebugBlock(
203 const char* buffer, unsigned long bufferSize,
204 bool continueParse
205 )
206{
207 AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
208 // TODO
209 return EXIT_SUCCESS;
210}
211
212
213int DumpTriggerChannelsBlock(
214 const char* buffer, unsigned long bufferSize,
215 bool continueParse
216 )
217{
218 AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
219 // TODO
220 return EXIT_SUCCESS;
221}
222
223
224int DumpRecHitStruct(
225 const char* buffer, unsigned long bufferSize,
226 const AliHLTMUONRecHitStruct* hit,
227 bool continueParse
228 )
229{
230 // Step through the fields trying to print them.
231 // At each step check if we have not overflowed the buffer. If we have
232 // not, then we can print the field, otherwise we print the left over
233 // bytes assumed to be corrupted rubbish.
234 int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
235 if (result != EXIT_SUCCESS) return result;
236 cout << setw(13) << left << hit->fX << setw(0);
237
238 result = CheckField(hit->fY, buffer, bufferSize, continueParse);
239 if (result != EXIT_SUCCESS) return result;
240 cout << setw(13) << left << hit->fY << setw(0);
241
242 result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
243 if (result != EXIT_SUCCESS) return result;
244 cout << hit->fZ << setw(0) << endl;
245
246 return result;
247}
248
249
250int DumpRecHitsBlock(
251 const char* buffer, unsigned long bufferSize,
252 bool continueParse
253 )
254{
255 int result = EXIT_SUCCESS;
256 AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
257
258 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
259 if (result != EXIT_SUCCESS and not continueParse) return result;
260
261 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
262
263 // Print the data block record entries.
264 cout << " X (cm) | Y (cm) | Z (cm)" << endl;
265 cout << "---------------------------------------" << endl;
266 const AliHLTMUONRecHitStruct* entry = block.GetArray();
267 for(AliHLTUInt32_t i = 0; i < nentries; i++)
268 {
269 int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
270 if (subResult != EXIT_SUCCESS) return subResult;
271 }
272
273 return result;
274}
275
276
277int DumpClustersBlock(
278 const char* buffer, unsigned long bufferSize,
279 bool continueParse
280 )
281{
282 AliHLTMUONClustersBlockReader block(buffer, bufferSize);
283 // TODO
284 return EXIT_SUCCESS;
285}
286
287
288int DumpChannelsBlock(
289 const char* buffer, unsigned long bufferSize,
290 bool continueParse
291 )
292{
293 AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
294 // TODO
295 return EXIT_SUCCESS;
296}
297
298
299int DumpMansoTrackStruct(
300 const char* buffer, unsigned long bufferSize,
301 const AliHLTMUONMansoTrackStruct* track,
302 bool continueParse
303 )
304{
305 // Step through the fields trying to print them.
306 // At each step check if we have not overflowed the buffer. If we have
307 // not, then we can print the field, otherwise we print the left over
308 // bytes assumed to be corrupted rubbish.
309 int result = CheckField(track->fId, buffer, bufferSize, continueParse);
310 if (result != EXIT_SUCCESS) return result;
311 cout << "Track ID: " << track->fId << "\t";
312
313 result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
314 if (result != EXIT_SUCCESS) return result;
315 cout << "Trigger Record ID: " << track->fTrigRec << endl;
316
317 result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
318 if (result != EXIT_SUCCESS) return result;
319 cout << "Flags: " << showbase << hex << track->fFlags << dec;
320
321 // Print the individual trigger bits.
322 AliHLTMUONParticleSign sign;
323 bool hitset[4];
324 AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
325 cout << " [Sign: " << sign << ", Hits set on chambers: ";
326 bool first = true;
327 for (AliHLTUInt32_t i = 0; i < 4; i++)
328 {
329 if (hitset[i])
330 {
331 cout << (first ? "" : ", ") << i+7;
332 first = false;
333 }
334 }
335 cout << (first ? "none]" : "]") << endl;
336
337 result = CheckField(track->fPx, buffer, bufferSize, continueParse);
338 if (result != EXIT_SUCCESS) return result;
339 cout << "Momentum: (px = " << track->fPx << ", ";
340
341 result = CheckField(track->fPy, buffer, bufferSize, continueParse);
342 if (result != EXIT_SUCCESS) return result;
343 cout << "py = " << track->fPy << ", ";
344
345 result = CheckField(track->fPz, buffer, bufferSize, continueParse);
346 if (result != EXIT_SUCCESS) return result;
347 cout << "pz = " << track->fPz << ") GeV/c\t";
348
349 result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
350 if (result != EXIT_SUCCESS) return result;
351 cout << "Chi squared fit: " << track->fChi2 << endl;
352
353 cout << "Track hits:" << endl;
354 cout << "Chamber | X (cm) | Y (cm) | Z (cm)" << endl;
355 cout << "------------------------------------------------" << endl;
356 const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
357 for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
358 {
359 cout << setw(10) << ch + 7;
360 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
361 if (result != EXIT_SUCCESS) return result;
362 }
363
364 return result;
365}
366
367
368int DumpMansoTracksBlock(
369 const char* buffer, unsigned long bufferSize,
370 bool continueParse
371 )
372{
373 int result = EXIT_SUCCESS;
374 AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
375
376 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
377 if (result != EXIT_SUCCESS and not continueParse) return result;
378
379 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
380
381 // Print the data block record entries.
382 const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
383 for(AliHLTUInt32_t i = 0; i < nentries; i++)
384 {
385 cout << "============================== Manso track number " << i+1
386 << " of " << nentries << " ==============================" << endl;
387 int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
388 if (subResult != EXIT_SUCCESS) return subResult;
389 }
390
391 return result;
392}
393
394
395int DumpMansoRoIStruct(
396 const char* buffer, unsigned long bufferSize,
397 const AliHLTMUONMansoRoIStruct* roi,
398 bool continueParse
399 )
400{
401 // Step through the fields trying to print them.
402 // At each step check if we have not overflowed the buffer. If we have
403 // not, then we can print the field, otherwise we print the left over
404 // bytes assumed to be corrupted rubbish.
405 int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
406 if (result != EXIT_SUCCESS) return result;
407 cout << setw(13) << left << roi->fX << setw(0);
408
409 result = CheckField(roi->fY, buffer, bufferSize, continueParse);
410 if (result != EXIT_SUCCESS) return result;
411 cout << setw(13) << left << roi->fY << setw(0);
412
413 result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
414 if (result != EXIT_SUCCESS) return result;
415 cout << setw(13) << left << roi->fZ << setw(0);
416
417 result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
418 if (result != EXIT_SUCCESS) return result;
419 cout << roi->fRadius << setw(0) << endl;
420
421 return result;
422}
423
424
425int DumpMansoCandidateStruct(
426 const char* buffer, unsigned long bufferSize,
427 const AliHLTMUONMansoCandidateStruct* candidate,
428 bool continueParse
429 )
430{
431 int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
432 if (result != EXIT_SUCCESS) return result;
433
434 cout << "Regions of interest:" << endl;
435 cout << "Chamber | X (cm) | Y (cm) | Z (cm) | Radius (cm)" << endl;
436 cout << "-------------------------------------------------------------" << endl;
437 const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
438 for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
439 {
440 cout << setw(10) << ch + 7;
441 result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
442 if (result != EXIT_SUCCESS) return result;
443 }
444 return result;
445}
446
447
448int DumpMansoCandidatesBlock(
449 const char* buffer, unsigned long bufferSize,
450 bool continueParse
451 )
452{
453 int result = EXIT_SUCCESS;
454 AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
455
456 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
457 if (result != EXIT_SUCCESS and not continueParse) return result;
458
459 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
460
461 // Print the data block record entries.
462 const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
463 for(AliHLTUInt32_t i = 0; i < nentries; i++)
464 {
465 cout << "=========================== Manso track candidate number " << i+1
466 << " of " << nentries << " ===========================" << endl;
467 int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
468 if (subResult != EXIT_SUCCESS) return subResult;
469 }
470
471 return result;
472}
473
474
475int DumpSinglesDecisionBlockHeader(
476 const char* buffer, unsigned long bufferSize,
477 const AliHLTMUONSinglesDecisionBlockStruct* header,
478 bool continueParse
479 )
480{
481 // Step through the header fields trying to print them.
482 // At each step check if we have not overflowed the buffer, if we have
483 // not then we can print the field, otherwise we print the left over
484 // bytes assumed to be corrupted rubbish.
485 int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
486 if (result != EXIT_SUCCESS) return result;
487 cout << " Number of low pt triggers: " << header->fNlowPt << endl;
488
489 result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
490 if (result != EXIT_SUCCESS) return result;
491 cout << "Number of high pt triggers: " << header->fNhighPt << endl;
492
493 return result;
494}
495
496
497int DumpTrackDecisionStruct(
498 const char* buffer, unsigned long bufferSize,
499 const AliHLTMUONTrackDecisionStruct* decision,
500 bool continueParse
501 )
502{
503 // Step through the fields trying to print them.
504 // At each step check if we have not overflowed the buffer. If we have
505 // not, then we can print the field, otherwise we print the left over
506 // bytes assumed to be corrupted rubbish.
507 int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
508 if (result != EXIT_SUCCESS) return result;
509 cout << setw(13) << left << decision->fTrackId << setw(0);
510
511 result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
512 if (result != EXIT_SUCCESS) return result;
513 cout << setw(12) << left << showbase << hex << decision->fTriggerBits
514 << setw(0) << dec;
515
516 // Print the individual trigger bits.
517 bool highPt, lowPt;
518 AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
519 cout << setw(7) << left << (highPt ? "yes" : "no");
520 cout << setw(8) << left << (lowPt ? "yes" : "no");
521 cout << setw(0) << endl;
522
523 return result;
524}
525
526
527int DumpSinglesDecisionBlock(
528 const char* buffer, unsigned long bufferSize,
529 bool continueParse
530 )
531{
532 int result = EXIT_SUCCESS;
533 AliHLTMUONSinglesDecisionBlockReader block(buffer, bufferSize);
534
535 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
536 if (result != EXIT_SUCCESS and not continueParse) return result;
537
538 // Dump the rest of the block header.
539 const AliHLTMUONSinglesDecisionBlockStruct* header = &block.BlockHeader();
540 int subResult = DumpSinglesDecisionBlockHeader(buffer, bufferSize, header, continueParse);
541 if (subResult != EXIT_SUCCESS) return subResult;
542
543 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
544
545 // Print the data block record entries.
546 cout << " | Trigger Bits" << endl;
547 cout << "Track ID | Raw HighPt LowPt" << endl;
548 cout << "--------------------------------------" << endl;
549 const AliHLTMUONTrackDecisionStruct* entry = block.GetArray();
550 for(AliHLTUInt32_t i = 0; i < nentries; i++)
551 {
552 subResult = DumpTrackDecisionStruct(buffer, bufferSize, entry++, continueParse);
553 if (subResult != EXIT_SUCCESS) return subResult;
554 }
555
556 return result;
557}
558
559
560int DumpPairsDecisionBlockHeader(
561 const char* buffer, unsigned long bufferSize,
562 const AliHLTMUONPairsDecisionBlockStruct* header,
563 bool continueParse
564 )
565{
566 // Step through the header fields trying to print them.
567 // At each step check if we have not overflowed the buffer, if we have
568 // not then we can print the field, otherwise we print the left over
569 // bytes assumed to be corrupted rubbish.
570 int result = CheckHeaderField(header->fNunlikeAnyPt, buffer, bufferSize, continueParse);
571 if (result != EXIT_SUCCESS) return result;
572 cout << " Number of unlike all pt triggers: " << header->fNunlikeAnyPt << endl;
573
574 result = CheckHeaderField(header->fNunlikeLowPt, buffer, bufferSize, continueParse);
575 if (result != EXIT_SUCCESS) return result;
576 cout << " Number of unlike low pt triggers: " << header->fNunlikeLowPt << endl;
577
578 result = CheckHeaderField(header->fNunlikeHighPt, buffer, bufferSize, continueParse);
579 if (result != EXIT_SUCCESS) return result;
580 cout << " Number of unlike high pt triggers: " << header->fNunlikeHighPt << endl;
581
582 result = CheckHeaderField(header->fNlikeAnyPt, buffer, bufferSize, continueParse);
583 if (result != EXIT_SUCCESS) return result;
584 cout << " Number of like any pt triggers: " << header->fNlikeAnyPt << endl;
585
586 result = CheckHeaderField(header->fNlikeLowPt, buffer, bufferSize, continueParse);
587 if (result != EXIT_SUCCESS) return result;
588 cout << " Number of like low pt triggers: " << header->fNlikeLowPt << endl;
589
590 result = CheckHeaderField(header->fNlikeHighPt, buffer, bufferSize, continueParse);
591 if (result != EXIT_SUCCESS) return result;
592 cout << " Number of like high pt triggers: " << header->fNlikeHighPt << endl;
593
594 result = CheckHeaderField(header->fNmassAny, buffer, bufferSize, continueParse);
595 if (result != EXIT_SUCCESS) return result;
596 cout << " Number of all invariant mass triggers: " << header->fNmassAny << endl;
597
598 result = CheckHeaderField(header->fNmassLow, buffer, bufferSize, continueParse);
599 if (result != EXIT_SUCCESS) return result;
600 cout << " Number of low invariant mass triggers: " << header->fNmassLow << endl;
601
602 result = CheckHeaderField(header->fNmassHigh, buffer, bufferSize, continueParse);
603 if (result != EXIT_SUCCESS) return result;
604 cout << "Number of high invariant mass triggers: " << header->fNmassHigh << endl;
605
606 return result;
607}
608
609
610int DumpPairDecisionStruct(
611 const char* buffer, unsigned long bufferSize,
612 const AliHLTMUONPairDecisionStruct* decision,
613 bool continueParse
614 )
615{
616 // Step through the fields trying to print them.
617 // At each step check if we have not overflowed the buffer. If we have
618 // not, then we can print the field, otherwise we print the left over
619 // bytes assumed to be corrupted rubbish.
620 int result = CheckField(decision->fTrackAId, buffer, bufferSize, continueParse);
621 if (result != EXIT_SUCCESS) return result;
622 cout << setw(13) << left << decision->fTrackAId << setw(0);
623
624 result = CheckField(decision->fTrackBId, buffer, bufferSize, continueParse);
625 if (result != EXIT_SUCCESS) return result;
626 cout << setw(13) << left << decision->fTrackBId << setw(0);
627
628 result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
629 if (result != EXIT_SUCCESS) return result;
630 cout << setw(12) << left << showbase << hex << decision->fTriggerBits
631 << setw(0) << dec;
632
633 // Print the individual trigger bits.
634 bool highMass, lowMass, unlike;
635 AliHLTUInt8_t highPtCount, lowPtCount;
636 AliHLTMUONUtils::UnpackPairDecisionBits(
637 decision->fTriggerBits,
638 highMass, lowMass, unlike, highPtCount, lowPtCount
639 );
640 cout << setw(7) << left << (highMass ? "yes" : "no");
641 cout << setw(7) << left << (lowMass ? "yes" : "no");
642 cout << setw(7) << left << (unlike ? "yes" : "no");
643 cout << setw(6) << left << AliHLTUInt16_t(highPtCount);
644 cout << setw(8) << left << AliHLTUInt16_t(lowPtCount);
645 cout << setw(0);
646
647 result = CheckField(decision->fInvMass, buffer, bufferSize, continueParse);
648 if (result != EXIT_SUCCESS) return result;
649 cout << decision->fInvMass << endl;
650
651 return EXIT_SUCCESS;
652}
653
654
655int DumpPairsDecisionBlock(
656 const char* buffer, unsigned long bufferSize,
657 bool continueParse
658 )
659{
660 int result = EXIT_SUCCESS;
661 AliHLTMUONPairsDecisionBlockReader block(buffer, bufferSize);
662
663 result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
664 if (result != EXIT_SUCCESS and not continueParse) return result;
665
666 // Dump the rest of the block header.
667 const AliHLTMUONPairsDecisionBlockStruct* header = &block.BlockHeader();
668 int subResult = DumpPairsDecisionBlockHeader(buffer, bufferSize, header, continueParse);
669 if (subResult != EXIT_SUCCESS) return subResult;
670
671 AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
672
673 // Print the data block record entries.
674 cout << " | | Trigger Bits |" << endl;
675 cout << "Track A ID | Track B ID | Raw HiMass LoMass Unlike HiPt# LoPt# | Invariant mass" << endl;
676 cout << "----------------------------------------------------------------------------------------" << endl;
677 const AliHLTMUONPairDecisionStruct* entry = block.GetArray();
678 for(AliHLTUInt32_t i = 0; i < nentries; i++)
679 {
680 subResult = DumpPairDecisionStruct(buffer, bufferSize, entry++, continueParse);
681 if (subResult != EXIT_SUCCESS) return subResult;
682 }
683
684 return result;
685}
686
687
688int DumpCommonHeader(
689 const char* buffer, unsigned long bufferSize,
690 const AliHLTMUONDataBlockHeader* header, bool continueParse
691 )
692{
693 // Step through the header fields trying to print them.
694 // At each step check if we have not overflowed the buffer, if we have
695 // not then we can print the field, otherwise we print the left over
696 // bytes assumed to be corrupted rubbish.
697 int result = CheckHeaderField(header->fType, buffer, bufferSize, continueParse);
698 if (result != EXIT_SUCCESS) return result;
699 AliHLTMUONDataBlockType type = AliHLTMUONDataBlockType(header->fType);
700 cout << " Block type: " << type << endl;
701
702 result = CheckHeaderField(header->fRecordWidth, buffer, bufferSize, continueParse);
703 if (result != EXIT_SUCCESS) return result;
704 cout << " Record width: " << header->fRecordWidth << endl;
705
706 result = CheckHeaderField(header->fNrecords, buffer, bufferSize, continueParse);
707 if (result != EXIT_SUCCESS) return result;
708 cout << "Number of entries: " << header->fNrecords << endl;
709
710 return result;
711}
712
713
714int ParseBuffer(
715 const char* buffer, unsigned long bufferSize,
716 bool continueParse, AliHLTMUONDataBlockType type
717 )
718{
719 assert( buffer != NULL );
720 int result = EXIT_SUCCESS;
721
722 if (bufferSize < sizeof(AliHLTMUONDataBlockHeader))
723 {
724 cerr << "ERROR: The size of the file is too small to contain a"
725 " valid data block." << endl;
726 result = PARSE_ERROR;
727 if (not continueParse) return result;
728 }
729 const AliHLTMUONDataBlockHeader* header =
730 reinterpret_cast<const AliHLTMUONDataBlockHeader*>(buffer);
731
732 int subResult = DumpCommonHeader(buffer, bufferSize, header, continueParse);
733 if (subResult != EXIT_SUCCESS) return subResult;
734
735
736 // Check if the block type in the header corresponds to the type given
737 // by the '-type' command line parameter. If they do not then print an
738 // error or big fat warning message and force interpretation of the data
739 // block with the type given by '-type'.
740 AliHLTMUONDataBlockType headerType = AliHLTMUONDataBlockType(header->fType);
741
742 if (type == kUnknownDataBlock)
743 {
744 // -type not used in the command line so just use what is given
745 // by the data block header.
746 type = headerType;
747 }
748 else if (type != headerType)
749 {
750 cerr << "WARNING: The data block header indicates a type"
751 " different from what was specified on the command line."
752 " The data could be corrupt."
753 << endl;
754 cerr << "WARNING: The type value in the file is "
755 << showbase << hex << header->fType
756 << " (" << headerType << "), but on the command line it is "
757 << showbase << hex << int(type) << dec
758 << " (" << type << ")."
759 << endl;
760 cerr << "WARNING: Will force the interpretation of the data block"
761 " with a type of " << type << "." << endl;
762 }
763
764 // Now we know what type the data block is supposed to be so we can
765 // dump it to screen with the appropriate dump routine.
766 switch (type)
767 {
768 case kTriggerRecordsDataBlock:
769 subResult = DumpTriggerRecordsBlock(buffer, bufferSize, continueParse);
770 if (subResult != EXIT_SUCCESS) result = subResult;
771 break;
772 case kTrigRecsDebugDataBlock:
773 subResult = DumpTrigRecsDebugBlock(buffer, bufferSize, continueParse);
774 if (subResult != EXIT_SUCCESS) result = subResult;
775 break;
776 case kTriggerChannelsDataBlock:
777 subResult = DumpTriggerChannelsBlock(buffer, bufferSize, continueParse);
778 if (subResult != EXIT_SUCCESS) result = subResult;
779 break;
780 case kRecHitsDataBlock:
781 subResult = DumpRecHitsBlock(buffer, bufferSize, continueParse);
782 if (subResult != EXIT_SUCCESS) result = subResult;
783 break;
784 case kClustersDataBlock:
785 subResult = DumpClustersBlock(buffer, bufferSize, continueParse);
786 if (subResult != EXIT_SUCCESS) result = subResult;
787 break;
788 case kChannelsDataBlock:
789 return DumpChannelsBlock(buffer, bufferSize, continueParse);
790 if (subResult != EXIT_SUCCESS) result = subResult;
791 break;
792 case kMansoTracksDataBlock:
793 subResult = DumpMansoTracksBlock(buffer, bufferSize, continueParse);
794 if (subResult != EXIT_SUCCESS) result = subResult;
795 break;
796 case kMansoCandidatesDataBlock:
797 subResult = DumpMansoCandidatesBlock(buffer, bufferSize, continueParse);
798 if (subResult != EXIT_SUCCESS) result = subResult;
799 break;
800 case kSinglesDecisionDataBlock:
801 subResult = DumpSinglesDecisionBlock(buffer, bufferSize, continueParse);
802 if (subResult != EXIT_SUCCESS) result = subResult;
803 break;
804 case kPairsDecisionDataBlock:
805 return DumpPairsDecisionBlock(buffer, bufferSize, continueParse);
806 if (subResult != EXIT_SUCCESS) result = subResult;
807 break;
808 default :
809 cout << "ERROR: Unknown data block type. Found a type number of "
810 << showbase << hex << int(type) << dec
811 << " (" << int(type) << ")." << endl;
812 result = PARSE_ERROR;
813 }
814
815 return result;
816}
817
818
819/**
820 * The caller is responsible for freeing memory allocated for buffer with a call
821 * to delete [] buffer.
822 */
823int ReadFile(const char* filename, char*& buffer, unsigned long& bufferSize)
824{
825 assert( filename != NULL );
826
827 // Open the file and find its size.
828 fstream file;
829 file.open(filename, ios::in);
830 if (not file)
831 {
832 cerr << "ERROR: Could not open the file: " << filename << endl;
833 return SYSTEM_ERROR;
834 }
835 file.seekg(0, ios::end);
836 if (not file)
837 {
838 cerr << "ERROR: Could not seek in the file: " << filename << endl;
839 return SYSTEM_ERROR;
840 }
841 bufferSize = file.tellg();
842 if (not file)
843 {
844 cerr << "ERROR: Could not get file size for the file: " <<
845 filename << endl;
846 return SYSTEM_ERROR;
847 }
848 file.seekg(0, ios::beg);
849 if (not file)
850 {
851 cerr << "ERROR: Could not seek in the file: " << filename << endl;
852 return SYSTEM_ERROR;
853 }
854
855 // Allocate the memory for the file.
856 try
857 {
858 buffer = new char[bufferSize];
859 }
860 catch (const std::bad_alloc&)
861 {
862 cerr << "ERROR: Out of memory. Tried to allocate " << bufferSize
863 << " bytes." << endl;
864 return SYSTEM_ERROR;
865 }
866
867 file.read(buffer, bufferSize);
868 if (not file)
869 {
870 delete [] buffer;
871 buffer = NULL;
872 bufferSize = 0;
873 cerr << "ERROR: Could not read from file: " << filename << endl;
874 return SYSTEM_ERROR;
875 }
876
877 file.close();
878 if (not file)
879 {
880 delete [] buffer;
881 buffer = NULL;
882 bufferSize = 0;
883 cerr << "ERROR: Could not close the file: " << filename << endl;
884 return SYSTEM_ERROR;
885 }
886
887 return EXIT_SUCCESS;
888}
889
890/**
891 * Prints the command line usage of this program to standard error.
892 */
893void PrintUsage()
894{
895 cerr << "Usage: dHLTdumpraw [-help|-h] [-continue] [-type <typename>] <filename>" << endl;
896 cerr << "Where <filename> is the name of a file containing a raw data block." << endl;
897 cerr << "Options:" << endl;
898 cerr << " -help | -h" << endl;
899 cerr << " Displays this message." << endl;
900 cerr << " -continue" << endl;
901 cerr << " If specified, the program will try to continue parsing the data block" << endl;
902 cerr << " as much as possible rather than stopping at the first error." << endl;
903 cerr << " -type <typename>" << endl;
904 cerr << " Forces the contents of the file to be interpreted as a specific" << endl;
905 cerr << " type of data block. Where <typename> can be one of:" << endl;
906 cerr << " trigrecs - trigger records data." << endl;
907 cerr << " trigrecsdebug - debugging information about trigger records." << endl;
908 cerr << " trigchannels - channel debugging in." << endl;
909 cerr << " rechits - reconstructed hits data." << endl;
910 cerr << " channels - channel debugging information from hit reconstruction." << endl;
911 cerr << " clusters - cluster debugging information from hit reconstruction." << endl;
912 cerr << " mansotracks - partial tracks from Manso algorithm." << endl;
913 cerr << " mansocandidates - track candidates considered in the Manso algorithm." << endl;
914 cerr << " singlesdecision - trigger decisions for single tracks." << endl;
915 cerr << " pairsdecision - trigger decisions for track pairs." << endl;
916}
917
918/**
919 * Parse the string passed as the type of the block and return the corresponding
920 * AliHLTMUONDataBlockType value.
921 */
922AliHLTMUONDataBlockType ParseCommandLineType(const char* type)
923{
924 if (strcmp(type, "trigrecs") == 0)
925 {
926 return kTriggerRecordsDataBlock;
927 }
928 else if (strcmp(type, "trigrecsdebug") == 0)
929 {
930 return kTrigRecsDebugDataBlock;
931 }
932 else if (strcmp(type, "trigchannels") == 0)
933 {
934 return kTriggerChannelsDataBlock;
935 }
936 else if (strcmp(type, "rechits") == 0)
937 {
938 return kRecHitsDataBlock;
939 }
940 else if (strcmp(type,"channels") == 0)
941 {
942 return kChannelsDataBlock;
943 }
944 else if (strcmp(type,"clusters") == 0)
945 {
946 return kClustersDataBlock;
947 }
948 else if (strcmp(type, "mansotracks") == 0)
949 {
950 return kMansoTracksDataBlock;
951 }
952 else if (strcmp(type, "mansocandidates") == 0)
953 {
954 return kMansoCandidatesDataBlock;
955 }
956 else if (strcmp(type, "singlesdecision") == 0)
957 {
958 return kSinglesDecisionDataBlock;
959 }
960 else if (strcmp(type, "pairsdecision") == 0)
961 {
962 return kPairsDecisionDataBlock;
963 }
964
965 cerr << "ERROR: Invalid type name '" << type << "' specified for argument -type."
966 << endl << endl;
967 PrintUsage();
968 return kUnknownDataBlock;
969}
970
971/**
972 * Parses the command line.
973 * @param argc Number of arguments as given in main().
974 * @param argv Array of arguments as given in main().
975 * @param filename Receives the pointer to the file name string.
976 * @param type Receives the type of the data block expected, i.e. the
977 * value of the -type flag.
978 * @return A status flag suitable for returning from main(), containing either
979 * EXIT_SUCCESS or CMDLINE_ERROR.
980 */
981int ParseCommandLine(
982 int argc, const char** argv,
983 const char*& filename, bool& continueParse,
984 AliHLTMUONDataBlockType& type
985 )
986{
987 filename = NULL;
988 continueParse = false;
989
990 // Parse the command line.
991 for (int i = 1; i < argc; i++)
992 {
993 if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0)
994 {
995 PrintUsage();
996 return EXIT_SUCCESS;
997 }
998 else if (strcmp(argv[i], "-continue") == 0)
999 {
1000 continueParse = true;
1001 }
1002 else if (strcmp(argv[i], "-type") == 0)
1003 {
1004 // Now we need to parse the typename in the command line.
1005 type = ParseCommandLineType(argv[++i]);
1006 if (type == kUnknownDataBlock) return CMDLINE_ERROR;
1007 }
1008 else
1009 {
1010 if (filename != NULL)
1011 {
1012 cerr << "ERROR: Only one file can be specified, but got '"
1013 << argv[i] << "', with '" << filename
1014 << "' specified earlier." << endl << endl;
1015 PrintUsage();
1016 return CMDLINE_ERROR;
1017 }
1018 else
1019 filename = argv[i];
1020 }
1021 }
1022
1023 // Now check that we have the filename and all the flags we need.
1024 if (filename == NULL)
1025 {
1026 cerr << "ERROR: Missing a file name. You must specify a file to process."
1027 << endl << endl;
1028 PrintUsage();
1029 return CMDLINE_ERROR;
1030 }
1031
1032 return EXIT_SUCCESS;
1033}
1034
1035
1036int main(int argc, const char** argv)
1037{
1038 const char* filename = NULL;
1039 bool continueParse = false;
1040 int returnCode = EXIT_SUCCESS;
1041 AliHLTMUONDataBlockType type = kUnknownDataBlock;
1042 char* buffer = NULL;
1043
1044 try
1045 {
1046 returnCode = ParseCommandLine(argc, argv, filename, continueParse, type);
1047
1048 if (returnCode == EXIT_SUCCESS)
1049 {
1050 unsigned long bufferSize = 0;
1051 returnCode = ReadFile(filename, buffer, bufferSize);
1052 if (returnCode == EXIT_SUCCESS)
1053 returnCode = ParseBuffer(buffer, bufferSize, continueParse, type);
1054 if (buffer != NULL) delete [] buffer;
1055 }
1056
1057 }
1058 catch (...)
1059 {
1060 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
1061 returnCode = FATAL_ERROR;
1062 if (buffer != NULL) delete [] buffer;
1063 }
1064
1065 return returnCode;
1066}