]>
Commit | Line | Data |
---|---|---|
f68b4e0e | 1 | /************************************************************************** |
2 | * This file is property of and copyright by the ALICE HLT Project * | |
3 | * All rights reserved. * | |
4 | * * | |
5 | * Primary Authors: * | |
6 | * Artur Szostak <artursz@iafrica.com> * | |
7 | * * | |
8 | * Permission to use, copy, modify and distribute this software and its * | |
9 | * documentation strictly for non-commercial purposes is hereby granted * | |
10 | * without fee, provided that the above copyright notice appears in all * | |
11 | * copies and that both the copyright notice and this permission notice * | |
12 | * appear in the supporting documentation. The authors make no claims * | |
13 | * about the suitability of this software for any purpose. It is * | |
14 | * provided "as is" without express or implied warranty. * | |
15 | **************************************************************************/ | |
16 | ||
17 | /* $Id: $ */ | |
18 | ||
19 | /** | |
20 | * @file dHLTrootify.cxx | |
21 | * @author Artur Szostak <artursz@iafrica.com> | |
22 | * @date 14 May 2008 | |
23 | * @brief Command line utility to convert dHLT's internal raw data blocks into ROOT objects. | |
24 | */ | |
25 | ||
26 | #include "TClassTable.h" | |
27 | #include "TString.h" | |
28 | #include "AliHLTSystem.h" | |
29 | #include "AliHLTConfiguration.h" | |
30 | #include "AliHLTMUONDataBlockReader.h" | |
31 | #include "AliHLTMUONConstants.h" | |
32 | #include "AliHLTMUONUtils.h" | |
33 | #include "AliLog.h" | |
34 | ||
35 | #include <cstring> | |
36 | #include <cstdlib> | |
37 | #include <cassert> | |
38 | #include <new> | |
39 | #include <fstream> | |
40 | ||
41 | #include <iostream> | |
42 | using std::cout; | |
43 | using std::cerr; | |
44 | using std::endl; | |
45 | ||
46 | ||
47 | #define CMDLINE_ERROR 1 | |
48 | #define PARSE_ERROR 2 | |
49 | #define SYSTEM_ERROR 3 | |
50 | #define FATAL_ERROR 4 | |
51 | #define HLTSYSTEM_ERROR 5 | |
52 | ||
53 | ||
f68b4e0e | 54 | /** |
55 | * Uses AliHLTSystem and the AliHLTMUONRootifierComponent to convert the files | |
56 | * into ROOT object format. | |
57 | * @param filenames Array of file name strings. | |
58 | * @param filetypes Array of file types corresponding to each filename. | |
59 | * @param numOfFiles Number of entries in the 'filenames' and 'filetypes' arrays. | |
60 | * @param outputFile The output file name to use. | |
61 | * @param maxLogging If set then all debug messages are printed. (default = false) | |
dba14d7d | 62 | * @param checkData Flag indicating if the internal raw data should be checked for |
63 | * consistency. Errors and warnings will be generated for consistency errors, | |
64 | * but the rootification of the data will continue. | |
f68b4e0e | 65 | * @return Returns HLTSYSTEM_ERROR if there was a problem reported by AliHLTSystem |
66 | * and EXIT_SUCCESS if the ROOT file was created OK. SYSTEM_ERROR is | |
67 | * returned if there was a problem allocating memory for HLT configuration | |
68 | * objects. | |
69 | */ | |
70 | int RootifyFiles( | |
71 | const char** filenames, | |
72 | AliHLTMUONDataBlockType* filetypes, | |
73 | int numOfFiles, | |
74 | const char* outputFile, | |
dba14d7d | 75 | bool maxLogging = false, |
76 | bool checkData = false | |
f68b4e0e | 77 | ) |
78 | { | |
79 | AliHLTSystem sys; | |
80 | ||
81 | if (maxLogging) | |
82 | { | |
83 | AliLog::SetGlobalLogLevel(AliLog::kMaxType); | |
84 | sys.SetGlobalLoggingLevel(kHLTLogAll); | |
85 | } | |
86 | ||
87 | // Check if required libraries are there and load them if not. | |
88 | if (gClassTable->GetID("AliHLTAgentUtil") < 0) | |
89 | { | |
90 | sys.LoadComponentLibraries("libAliHLTUtil.so"); | |
91 | } | |
92 | if (gClassTable->GetID("AliHLTMUONAgent") < 0) | |
93 | { | |
94 | sys.LoadComponentLibraries("libAliHLTMUON.so"); | |
95 | } | |
96 | ||
97 | TString sources = ""; | |
98 | typedef AliHLTConfiguration* PAliHLTConfiguration; | |
99 | PAliHLTConfiguration* filePubs = NULL; | |
100 | ||
101 | try | |
102 | { | |
103 | filePubs = new PAliHLTConfiguration[numOfFiles]; | |
104 | // Must make sure all the pointers are NULL because we | |
105 | // need to clean up afterwords and we might fail half | |
106 | // way through the memory allocation. | |
107 | int i; | |
108 | for (i = 0; i < numOfFiles; i++) | |
109 | { | |
110 | filePubs[i] = NULL; | |
111 | } | |
112 | ||
113 | // Now start allocating the file publishers. | |
114 | for (i = 0; i < numOfFiles; i++) | |
115 | { | |
116 | TString name = "filePublisher_"; | |
117 | name += filenames[i]; | |
118 | sources += name + " "; | |
119 | TString params = "-datatype '"; | |
887a669c | 120 | params += AliHLTMUONUtils::DataBlockTypeToString(filetypes[i]); |
f68b4e0e | 121 | params += "' 'MUON' -dataspec 0x0 -datafile "; |
122 | params += filenames[i]; | |
123 | filePubs[i] = new AliHLTConfiguration( | |
124 | name.Data(), "FilePublisher", NULL, params.Data() | |
125 | ); | |
126 | } | |
127 | } | |
128 | catch (const std::bad_alloc&) | |
129 | { | |
130 | cerr << "ERROR: There is not enough memory to allocate another configuration object." << endl; | |
131 | ||
132 | // Make sure to clean up what was actaully allocated. | |
133 | if (filePubs != NULL) | |
134 | { | |
135 | for (int i = 0; i < numOfFiles; i++) | |
136 | { | |
137 | if (filePubs[i] != NULL) | |
138 | delete filePubs[i]; | |
139 | } | |
140 | delete [] filePubs; | |
141 | } | |
142 | ||
143 | return SYSTEM_ERROR; | |
144 | } | |
145 | ||
dba14d7d | 146 | // Setup the component for data integrity checking. |
147 | if (checkData) | |
148 | { | |
887a669c | 149 | AliHLTConfiguration checker( |
150 | "checker", AliHLTMUONConstants::DataCheckerComponentId(), | |
151 | sources, "-warn_on_unexpected_block -ignorespec" | |
152 | ); | |
dba14d7d | 153 | sources = "checker"; |
154 | } | |
155 | ||
f68b4e0e | 156 | // Setup the component which converts the raw internal dHLT data to ROOT objects. |
887a669c | 157 | AliHLTConfiguration convert("convert", AliHLTMUONConstants::RootifierComponentId(), sources, ""); |
f68b4e0e | 158 | |
159 | // Setup the ROOT file writer. | |
160 | TString params = "-concatenate-events -datafile "; | |
161 | params += outputFile; | |
162 | params += " -specfmt"; | |
163 | AliHLTConfiguration sink("sink", "ROOTFileWriter", "convert", params.Data()); | |
164 | ||
165 | // Build and run the HLT tasks. | |
166 | if (sys.BuildTaskList("sink") != 0) return HLTSYSTEM_ERROR; | |
167 | if (maxLogging) sys.PrintTaskList(); | |
168 | if (sys.Run() != 0) return HLTSYSTEM_ERROR; | |
169 | ||
170 | // Clean up all the dynamically allocate objects. | |
171 | for (int i = 0; i < numOfFiles; i++) | |
172 | { | |
173 | delete filePubs[i]; | |
174 | } | |
175 | delete [] filePubs; | |
176 | ||
177 | return EXIT_SUCCESS; | |
178 | } | |
179 | ||
180 | /** | |
181 | * This method decodes the type of the file. | |
182 | */ | |
183 | int DecodeFileType(const char* filename, AliHLTMUONDataBlockType& type) | |
184 | { | |
185 | assert( filename != NULL ); | |
186 | ||
187 | // Open the file and find its size. | |
188 | fstream file; | |
189 | file.open(filename, ios::in); | |
190 | if (not file) | |
191 | { | |
192 | cerr << "ERROR: Could not open the file: " << filename << endl; | |
193 | return SYSTEM_ERROR; | |
194 | } | |
195 | ||
196 | AliHLTMUONDataBlockHeader header; | |
197 | file.read(reinterpret_cast<char*>(&header), sizeof(header)); | |
198 | if (not file) | |
199 | { | |
200 | cerr << "ERROR: Could not read from file: " << filename << endl; | |
201 | return SYSTEM_ERROR; | |
202 | } | |
203 | ||
204 | file.close(); | |
205 | if (not file) | |
206 | { | |
207 | cerr << "ERROR: Could not close the file: " << filename << endl; | |
208 | return SYSTEM_ERROR; | |
209 | } | |
210 | ||
211 | type = AliHLTMUONDataBlockType(header.fType); | |
212 | ||
213 | // Check that the type is something valid. Otherwise set it to a | |
214 | // value of kUnknownDataBlock. | |
215 | switch (type) | |
216 | { | |
217 | case kTriggerRecordsDataBlock: | |
218 | case kTrigRecsDebugDataBlock: | |
f68b4e0e | 219 | case kRecHitsDataBlock: |
220 | case kClustersDataBlock: | |
221 | case kChannelsDataBlock: | |
222 | case kMansoTracksDataBlock: | |
223 | case kMansoCandidatesDataBlock: | |
224 | case kSinglesDecisionDataBlock: | |
225 | case kPairsDecisionDataBlock: | |
226 | break; | |
227 | default: type = kUnknownDataBlock; | |
228 | break; | |
229 | } | |
230 | ||
231 | return EXIT_SUCCESS; | |
232 | } | |
233 | ||
234 | /** | |
235 | * Prints the command line usage of this program to standard out or error. | |
236 | */ | |
237 | void PrintUsage(bool asError = true) | |
238 | { | |
239 | std::ostream& os = asError ? cerr : cout; | |
dba14d7d | 240 | os << "Usage: dHLTrootify [-help|-h] [-outfile|-o <output_file>] [-type|-t <typename>]" << endl; |
241 | os << " [-debug|-d] [-check|-c] <filename> [<filename> ...]" << endl; | |
f68b4e0e | 242 | os << "Where <filename> is the name of a file containing a raw data block." << endl; |
243 | os << "Options:" << endl; | |
244 | os << " -help | -h" << endl; | |
245 | os << " Displays this message." << endl; | |
246 | os << " -outfile | -o <output_file>" << endl; | |
247 | os << " Specifies the output ROOT file to write to, where <output_file> is the" << endl; | |
248 | os << " name of the output file." << endl; | |
249 | os << " -type | -t <typename>" << endl; | |
250 | os << " Forces the contents of the subsequent files specified on the command" << endl; | |
251 | os << " line to be interpreted as a specific type of data block." << endl; | |
252 | os << " Where <typename> can be one of:" << endl; | |
253 | os << " trigrecs - trigger records data." << endl; | |
254 | os << " trigrecsdebug - debugging information about trigger records." << endl; | |
f68b4e0e | 255 | os << " rechits - reconstructed hits data." << endl; |
256 | os << " channels - channel debugging information from hit reconstruction." << endl; | |
257 | os << " clusters - cluster debugging information from hit reconstruction." << endl; | |
258 | os << " mansotracks - partial tracks from Manso algorithm." << endl; | |
259 | os << " mansocandidates - track candidates considered in the Manso algorithm." << endl; | |
260 | os << " singlesdecision - trigger decisions for single tracks." << endl; | |
261 | os << " pairsdecision - trigger decisions for track pairs." << endl; | |
262 | os << " autodetect - the type of the data block will be automatically" << endl; | |
263 | os << " detected." << endl; | |
264 | os << " -debug | -d" << endl; | |
265 | os << " If specified then the all debug messages are printed by the AliHLTSystem." << endl; | |
dba14d7d | 266 | os << " -check | -c" << endl; |
267 | os << " If specified then data integrity checks are performed on the raw data." << endl; | |
268 | os << " Warnings and errors are printed as problems are found with the data, but" << endl; | |
269 | os << " the data will still be converted into ROOT objects as best as possible." << endl; | |
f68b4e0e | 270 | } |
271 | ||
272 | /** | |
273 | * Parses the command line. | |
274 | * @param argc Number of arguments as given in main(). | |
275 | * @param argv Array of arguments as given in main(). | |
276 | * @param filenames Pointer to buffer storing file name strings. | |
277 | * @param filetypes Array that receives the type of the data block expected, i.e. | |
278 | * the value of the -type flag for the corresponding file. | |
279 | * @param numOfFiles Receives the number of file name strings that were found | |
280 | * and added to 'filenames'. | |
281 | * @param outputFile The output file name to use. Set to NULL if none specified. | |
282 | * @param maxLogging Set to true if maximal logging was requested. | |
dba14d7d | 283 | * @param checkData Set to true if data integrity checking was requested. |
f68b4e0e | 284 | * @return A status flag suitable for returning from main(), containing either |
285 | * EXIT_SUCCESS or CMDLINE_ERROR or SYSTEM_ERROR. | |
286 | */ | |
287 | int ParseCommandLine( | |
288 | int argc, | |
289 | const char** argv, | |
290 | const char** filenames, | |
291 | AliHLTMUONDataBlockType* filetypes, | |
292 | int& numOfFiles, | |
293 | const char*& outputFile, | |
dba14d7d | 294 | bool& maxLogging, |
295 | bool& checkData | |
f68b4e0e | 296 | ) |
297 | { | |
298 | numOfFiles = 0; | |
299 | outputFile = NULL; | |
300 | maxLogging = false; | |
dba14d7d | 301 | checkData = false; |
f68b4e0e | 302 | AliHLTMUONDataBlockType currentType = kUnknownDataBlock; |
303 | ||
304 | // Parse the command line. | |
305 | for (int i = 1; i < argc; i++) | |
306 | { | |
307 | if (strcmp(argv[i], "-help") == 0 or strcmp(argv[i], "-h") == 0) | |
308 | { | |
309 | PrintUsage(false); | |
310 | return EXIT_SUCCESS; | |
311 | } | |
312 | else if (strcmp(argv[i], "-outfile") == 0 or strcmp(argv[i], "-o") == 0) | |
313 | { | |
314 | if (++i >= argc) | |
315 | { | |
887a669c | 316 | cerr << "ERROR: Missing an output filename." << endl << endl; |
f68b4e0e | 317 | PrintUsage(); |
318 | return CMDLINE_ERROR; | |
319 | } | |
320 | outputFile = argv[i]; | |
321 | } | |
322 | else if (strcmp(argv[i], "-type") == 0 or strcmp(argv[i], "-t") == 0) | |
323 | { | |
324 | if (++i >= argc) | |
325 | { | |
887a669c | 326 | cerr << "ERROR: Missing a type specifier." << endl << endl; |
f68b4e0e | 327 | PrintUsage(); |
328 | return CMDLINE_ERROR; | |
329 | } | |
330 | // Now we need to parse the typename in the command line. | |
331 | if (strcmp(argv[i], "autodetect") == 0) | |
332 | { | |
333 | currentType = kUnknownDataBlock; | |
334 | } | |
335 | else | |
336 | { | |
337 | currentType = AliHLTMUONUtils::ParseCommandLineTypeString(argv[i]); | |
338 | if (currentType == kUnknownDataBlock) | |
339 | { | |
340 | cerr << "ERROR: Invalid type name '" << argv[i] | |
341 | << "' specified for argument " << argv[i-1] | |
342 | << "." << endl << endl; | |
343 | PrintUsage(); | |
344 | return CMDLINE_ERROR; | |
345 | } | |
346 | } | |
347 | } | |
348 | else if (strcmp(argv[i], "-debug") == 0 or strcmp(argv[i], "-d") == 0) | |
349 | { | |
350 | maxLogging = true; | |
351 | } | |
dba14d7d | 352 | else if (strcmp(argv[i], "-check") == 0 or strcmp(argv[i], "-c") == 0) |
353 | { | |
354 | checkData = true; | |
355 | } | |
f68b4e0e | 356 | else |
357 | { | |
358 | assert( numOfFiles < argc ); | |
359 | filenames[numOfFiles] = argv[i]; | |
360 | ||
361 | AliHLTMUONDataBlockType typeToUse = currentType; | |
362 | // Work out what the file type is from the file's header | |
363 | // if the type is not yet known. | |
364 | if (typeToUse == kUnknownDataBlock) | |
365 | { | |
366 | int result = DecodeFileType(filenames[numOfFiles], typeToUse); | |
367 | if (result != EXIT_SUCCESS) return result; | |
368 | if (typeToUse == kUnknownDataBlock) | |
369 | { | |
370 | cerr << "ERROR: Could not decode what type of data" | |
371 | " is stored in the file:" | |
372 | << filenames[numOfFiles] << endl; | |
373 | return PARSE_ERROR; | |
374 | } | |
375 | } | |
376 | ||
377 | filetypes[numOfFiles] = typeToUse; | |
378 | numOfFiles++; | |
379 | } | |
380 | } | |
381 | ||
382 | // Now check that we have at least one filename and all the flags we need. | |
383 | if (numOfFiles == 0) | |
384 | { | |
385 | cerr << "ERROR: Missing a file name. You must specify at least one file to process." | |
386 | << endl << endl; | |
387 | PrintUsage(); | |
388 | return CMDLINE_ERROR; | |
389 | } | |
390 | ||
391 | return EXIT_SUCCESS; | |
392 | } | |
393 | ||
394 | ||
395 | int main(int argc, const char** argv) | |
396 | { | |
397 | // Test endianess of this machine during runtime and print warning if it is not | |
398 | // little endian. | |
399 | union | |
400 | { | |
401 | int dword; | |
402 | char byte[4]; | |
403 | } endianTest; | |
404 | endianTest.dword = 0x1; | |
405 | if (endianTest.byte[0] != 0x1) | |
406 | { | |
407 | cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl; | |
408 | cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl; | |
409 | cerr << "!! !!" << endl; | |
410 | cerr << "!! This is not a little endian machine, but dHLT raw data is normally !!" << endl; | |
411 | cerr << "!! generated in little endian format. Unless you are looking at localy !!" << endl; | |
412 | cerr << "!! created simulated data, then this program will not show you correct !!" << endl; | |
413 | cerr << "!! output. !!" << endl; | |
414 | cerr << "!! !!" << endl; | |
415 | cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl; | |
416 | cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl; | |
417 | cerr << endl; | |
418 | } | |
419 | ||
420 | ||
421 | int numOfFiles = 0; | |
422 | const char* outputFile = NULL; | |
423 | bool maxLogging = false; | |
dba14d7d | 424 | bool checkData = false; |
f68b4e0e | 425 | int returnCode = EXIT_SUCCESS; |
426 | ||
427 | try | |
428 | { | |
429 | // There will be a maximum of 'argc' number of filenames possible. | |
430 | typedef const char* AnsiString; | |
431 | const char** filename = new AnsiString[argc]; | |
432 | AliHLTMUONDataBlockType* filetype = new AliHLTMUONDataBlockType[argc]; | |
433 | ||
434 | returnCode = ParseCommandLine( | |
435 | argc, argv, filename, filetype, numOfFiles, | |
dba14d7d | 436 | outputFile, maxLogging, checkData |
f68b4e0e | 437 | ); |
438 | if (outputFile == NULL) | |
439 | { | |
440 | outputFile = "output.root"; | |
441 | } | |
442 | if (returnCode == EXIT_SUCCESS) | |
443 | { | |
444 | returnCode = RootifyFiles( | |
445 | filename, filetype, numOfFiles, | |
dba14d7d | 446 | outputFile, maxLogging, checkData |
f68b4e0e | 447 | ); |
448 | } | |
449 | ||
450 | delete [] filename; | |
451 | delete [] filetype; | |
452 | } | |
453 | catch (...) | |
454 | { | |
455 | cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl; | |
456 | returnCode = FATAL_ERROR; | |
457 | } | |
458 | ||
459 | return returnCode; | |
460 | } | |
461 |