]>
Commit | Line | Data |
---|---|---|
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> | |
45 | using std::cout; | |
46 | using std::cerr; | |
47 | using std::endl; | |
48 | using std::showbase; | |
49 | using std::noshowbase; | |
50 | using std::hex; | |
51 | using std::dec; | |
52 | ||
53 | #include <iomanip> | |
54 | using std::setw; | |
55 | using std::left; | |
56 | using 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 | ||
65 | void 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 | ||
83 | template <typename FieldType> | |
84 | int 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 | ||
108 | template <typename FieldType> | |
109 | int 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 | ||
133 | template <typename BlockType> | |
134 | int 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 | ||
168 | template <typename BlockType> | |
169 | AliHLTUInt32_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 | ||
191 | int 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 | ||
202 | int 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 | ||
213 | int 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 | ||
224 | int 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 | ||
250 | int 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 | ||
277 | int 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 | ||
288 | int 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 | ||
299 | int 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 | ||
368 | int 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 | ||
395 | int 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 | ||
425 | int 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 | ||
448 | int 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 | ||
475 | int 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 | ||
497 | int 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 | ||
527 | int 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 | ||
560 | int 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 | ||
610 | int 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 | ||
655 | int 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 | ||
688 | int 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 | ||
714 | int 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 | */ | |
823 | int 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 | */ | |
893 | void 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 | */ | |
922 | AliHLTMUONDataBlockType 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 | */ | |
981 | int 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 | ||
1036 | int 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 | } |