1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
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 **************************************************************************/
20 * @file dHLTrootify.cxx
21 * @author Artur Szostak <artursz@iafrica.com>
23 * @brief Command line utility to convert dHLT's internal raw data blocks into ROOT objects.
26 #include "TClassTable.h"
28 #include "AliHLTSystem.h"
29 #include "AliHLTConfiguration.h"
30 #include "AliHLTMUONDataBlockReader.h"
31 #include "AliHLTMUONConstants.h"
32 #include "AliHLTMUONUtils.h"
47 #define CMDLINE_ERROR 1
49 #define SYSTEM_ERROR 3
51 #define HLTSYSTEM_ERROR 5
55 // CDB path and run number to use.
56 const char* gCDBPath = "local://$ALICE_ROOT/OCDB";
61 * Uses AliHLTSystem and the AliHLTMUONRootifierComponent to convert the files
62 * into ROOT object format.
63 * @param filenames Array of file name strings.
64 * @param filetypes Array of file types corresponding to each filename.
65 * @param numOfFiles Number of entries in the 'filenames' and 'filetypes' arrays.
66 * @param outputFile The output file name to use.
67 * @param maxLogging If set then all debug messages are printed. (default = false)
68 * @param checkData Flag indicating if the internal raw data should be checked for
69 * consistency. Errors and warnings will be generated for consistency errors,
70 * but the rootification of the data will continue.
71 * @return Returns HLTSYSTEM_ERROR if there was a problem reported by AliHLTSystem
72 * and EXIT_SUCCESS if the ROOT file was created OK. SYSTEM_ERROR is
73 * returned if there was a problem allocating memory for HLT configuration
77 const char** filenames,
78 AliHLTMUONDataBlockType* filetypes,
80 const char* outputFile,
81 bool maxLogging = false,
82 bool checkData = false
89 AliLog::SetGlobalLogLevel(AliLog::kMaxType);
90 sys.SetGlobalLoggingLevel(kHLTLogAll);
93 sys.LoadComponentLibraries("libAliHLTUtil.so");
94 sys.LoadComponentLibraries("libAliHLTMUON.so");
97 typedef AliHLTConfiguration* PAliHLTConfiguration;
98 PAliHLTConfiguration* filePubs = NULL;
102 filePubs = new PAliHLTConfiguration[numOfFiles];
103 // Must make sure all the pointers are NULL because we
104 // need to clean up afterwords and we might fail half
105 // way through the memory allocation.
107 for (i = 0; i < numOfFiles; i++)
112 // Now start allocating the file publishers.
113 for (i = 0; i < numOfFiles; i++)
115 TString name = "filePublisher_";
116 name += filenames[i];
117 sources += name + " ";
118 TString params = "-datatype '";
119 params += AliHLTMUONUtils::DataBlockTypeToString(filetypes[i]);
120 params += "' 'MUON' -dataspec 0x0 -datafile ";
121 params += filenames[i];
122 filePubs[i] = new AliHLTConfiguration(
123 name.Data(), "FilePublisher", NULL, params.Data()
127 catch (const std::bad_alloc&)
129 cerr << "ERROR: There is not enough memory to allocate another configuration object." << endl;
131 // Make sure to clean up what was actaully allocated.
132 if (filePubs != NULL)
134 for (int i = 0; i < numOfFiles; i++)
136 if (filePubs[i] != NULL)
145 // Setup the component for data integrity checking.
148 TString dcparams = "-warn_on_unexpected_block -ignorespec -cdbpath ";
149 dcparams += gCDBPath;
150 dcparams += " -run ";
151 dcparams += gRunNumber;
152 AliHLTConfiguration checker(
153 "checker", AliHLTMUONConstants::DataCheckerComponentId(),
159 // Setup the component which converts the raw internal dHLT data to ROOT objects.
160 AliHLTConfiguration convert("convert", AliHLTMUONConstants::RootifierComponentId(), sources, "");
162 // Setup the ROOT file writer.
163 TString params = "-concatenate-events -datafile ";
164 params += outputFile;
165 params += " -specfmt";
166 AliHLTConfiguration sink("sink", "ROOTFileWriter", "convert", params.Data());
168 // Build and run the HLT tasks.
169 if (sys.BuildTaskList("sink") != 0) return HLTSYSTEM_ERROR;
170 if (maxLogging) sys.PrintTaskList();
171 if (sys.Run() != 0) return HLTSYSTEM_ERROR;
173 // Clean up all the dynamically allocate objects.
174 for (int i = 0; i < numOfFiles; i++)
184 * This method decodes the type of the file.
186 int DecodeFileType(const char* filename, AliHLTMUONDataBlockType& type)
188 assert( filename != NULL );
190 // Open the file and find its size.
192 file.open(filename, ios::in);
195 cerr << "ERROR: Could not open the file: " << filename << endl;
199 AliHLTMUONDataBlockHeader header;
200 file.read(reinterpret_cast<char*>(&header), sizeof(header));
203 cerr << "ERROR: Could not read from file: " << filename << endl;
210 cerr << "ERROR: Could not close the file: " << filename << endl;
214 type = AliHLTMUONDataBlockType(header.fType);
216 // Check that the type is something valid. Otherwise set it to a
217 // value of kUnknownDataBlock.
220 case kTriggerRecordsDataBlock:
221 case kTrigRecsDebugDataBlock:
222 case kRecHitsDataBlock:
223 case kClustersDataBlock:
224 case kChannelsDataBlock:
225 case kMansoTracksDataBlock:
226 case kMansoCandidatesDataBlock:
227 case kSinglesDecisionDataBlock:
228 case kPairsDecisionDataBlock:
230 default: type = kUnknownDataBlock;
238 * Prints the command line usage of this program to standard out or error.
240 void PrintUsage(bool asError = true)
242 std::ostream& os = asError ? cerr : cout;
243 os << "Usage: dHLTrootify [-help|-h] [-outfile|-o <output_file>] [-type|-t <typename>]" << endl;
244 os << " [-debug|-d] [-check|-c] [-cdbpath|-p <url>] [-run|-r <number>]" << endl;
245 os << " <filename> [<filename> ...]" << endl;
246 os << "Where <filename> is the name of a file containing a raw data block." << endl;
247 os << "Options:" << endl;
248 os << " -help | -h" << endl;
249 os << " Displays this message." << endl;
250 os << " -outfile | -o <output_file>" << endl;
251 os << " Specifies the output ROOT file to write to, where <output_file> is the" << endl;
252 os << " name of the output file." << endl;
253 os << " -type | -t <typename>" << endl;
254 os << " Forces the contents of the subsequent files specified on the command" << endl;
255 os << " line to be interpreted as a specific type of data block." << endl;
256 os << " Where <typename> can be one of:" << endl;
257 os << " trigrecs - trigger records data." << endl;
258 os << " trigrecsdebug - debugging information about trigger records." << endl;
259 os << " rechits - reconstructed hits data." << endl;
260 os << " channels - channel debugging information from hit reconstruction." << endl;
261 os << " clusters - cluster debugging information from hit reconstruction." << endl;
262 os << " mansotracks - partial tracks from Manso algorithm." << endl;
263 os << " mansocandidates - track candidates considered in the Manso algorithm." << endl;
264 os << " singlesdecision - trigger decisions for single tracks." << endl;
265 os << " pairsdecision - trigger decisions for track pairs." << endl;
266 os << " autodetect - the type of the data block will be automatically" << endl;
267 os << " detected." << endl;
268 os << " -debug | -d" << endl;
269 os << " If specified then the all debug messages are printed by the AliHLTSystem." << endl;
270 os << " -check | -c" << endl;
271 os << " If specified then data integrity checks are performed on the raw data." << endl;
272 os << " Warnings and errors are printed as problems are found with the data, but" << endl;
273 os << " the data will still be converted into ROOT objects as best as possible." << endl;
274 os << " -cdbpath | -p <url>" << endl;
275 os << " The path to the CDB to use when running with the -check | -k option." << endl;
276 os << " -run | -r <number>" << endl;
277 os << " The run number to use when running with the -check | -k option." << endl;
281 * Parses the command line.
282 * @param argc Number of arguments as given in main().
283 * @param argv Array of arguments as given in main().
284 * @param filenames Pointer to buffer storing file name strings.
285 * @param filetypes Array that receives the type of the data block expected, i.e.
286 * the value of the -type flag for the corresponding file.
287 * @param numOfFiles Receives the number of file name strings that were found
288 * and added to 'filenames'.
289 * @param outputFile The output file name to use. Set to NULL if none specified.
290 * @param maxLogging Set to true if maximal logging was requested.
291 * @param checkData Set to true if data integrity checking was requested.
292 * @return A status flag suitable for returning from main(), containing either
293 * EXIT_SUCCESS or CMDLINE_ERROR or SYSTEM_ERROR.
295 int ParseCommandLine(
298 const char** filenames,
299 AliHLTMUONDataBlockType* filetypes,
301 const char*& outputFile,
310 bool pathSet = false;
312 AliHLTMUONDataBlockType currentType = kUnknownDataBlock;
314 // Parse the command line.
315 for (int i = 1; i < argc; i++)
317 if (strcmp(argv[i], "-help") == 0 or strcmp(argv[i], "-h") == 0)
322 else if (strcmp(argv[i], "-outfile") == 0 or strcmp(argv[i], "-o") == 0)
324 if (outputFile != NULL)
326 cerr << "WARNING: Already used -outfile|-o with " << outputFile
327 << " before. Will override it with the last value specified with -outfile|-o."
332 cerr << "ERROR: Missing an output filename." << endl << endl;
334 return CMDLINE_ERROR;
336 outputFile = argv[i];
338 else if (strcmp(argv[i], "-type") == 0 or strcmp(argv[i], "-t") == 0)
342 cerr << "ERROR: Missing a type specifier." << endl << endl;
344 return CMDLINE_ERROR;
346 // Now we need to parse the typename in the command line.
347 if (strcmp(argv[i], "autodetect") == 0)
349 currentType = kUnknownDataBlock;
353 currentType = AliHLTMUONUtils::ParseCommandLineTypeString(argv[i]);
354 if (currentType == kUnknownDataBlock)
356 cerr << "ERROR: Invalid type name '" << argv[i]
357 << "' specified for argument " << argv[i-1]
358 << "." << endl << endl;
360 return CMDLINE_ERROR;
364 else if (strcmp(argv[i], "-debug") == 0 or strcmp(argv[i], "-d") == 0)
368 else if (strcmp(argv[i], "-check") == 0 or strcmp(argv[i], "-c") == 0)
372 else if (strcmp(argv[i], "-cdbpath") == 0 or strcmp(argv[i], "-p") == 0)
376 cerr << "WARNING: Already used -cdbpath|-p with '" << gCDBPath
377 << "' before. Will override it with the last value specified with -cdbpath|-p."
382 cerr << "ERROR: Missing the URL for the CDB path." << endl << endl;
384 return CMDLINE_ERROR;
389 else if (strcmp(argv[i], "-run") == 0 or strcmp(argv[i], "-r") == 0)
393 cerr << "WARNING: Already used -run|-r with " << gRunNumber
394 << " before. Will override it with the last value specified with -run|-r."
399 cerr << "ERROR: Missing the run number." << endl << endl;
401 return CMDLINE_ERROR;
405 Int_t run = Int_t( strtol(argv[i], &cpErr, 0) );
406 if (cpErr == NULL or *cpErr != '\0' or run < 0)
408 cerr << "ERROR: Cannot convert '" << argv[i] << "' to a valid run number."
409 " Expected a positive integer value." << endl;
410 return CMDLINE_ERROR;
418 assert( numOfFiles < argc );
419 filenames[numOfFiles] = argv[i];
421 AliHLTMUONDataBlockType typeToUse = currentType;
422 // Work out what the file type is from the file's header
423 // if the type is not yet known.
424 if (typeToUse == kUnknownDataBlock)
426 int result = DecodeFileType(filenames[numOfFiles], typeToUse);
427 if (result != EXIT_SUCCESS) return result;
428 if (typeToUse == kUnknownDataBlock)
430 cerr << "ERROR: Could not decode what type of data"
431 " is stored in the file:"
432 << filenames[numOfFiles] << endl;
437 filetypes[numOfFiles] = typeToUse;
442 // Now check that we have at least one filename and all the flags we need.
445 cerr << "ERROR: Missing a file name. You must specify at least one file to process."
448 return CMDLINE_ERROR;
455 int main(int argc, const char** argv)
457 // Test endianess of this machine during runtime and print warning if it is not
464 endianTest.dword = 0x1;
465 if (endianTest.byte[0] != 0x1)
467 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
468 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
469 cerr << "!! !!" << endl;
470 cerr << "!! This is not a little endian machine, but dHLT raw data is normally !!" << endl;
471 cerr << "!! generated in little endian format. Unless you are looking at localy !!" << endl;
472 cerr << "!! created simulated data, then this program will not show you correct !!" << endl;
473 cerr << "!! output. !!" << endl;
474 cerr << "!! !!" << endl;
475 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
476 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
482 const char* outputFile = NULL;
483 bool maxLogging = false;
484 bool checkData = false;
485 int returnCode = EXIT_SUCCESS;
489 // There will be a maximum of 'argc' number of filenames possible.
490 typedef const char* AnsiString;
491 const char** filename = new AnsiString[argc];
492 AliHLTMUONDataBlockType* filetype = new AliHLTMUONDataBlockType[argc];
494 returnCode = ParseCommandLine(
495 argc, argv, filename, filetype, numOfFiles,
496 outputFile, maxLogging, checkData
498 if (outputFile == NULL)
500 outputFile = "output.root";
502 if (returnCode == EXIT_SUCCESS)
504 returnCode = RootifyFiles(
505 filename, filetype, numOfFiles,
506 outputFile, maxLogging, checkData
515 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
516 returnCode = FATAL_ERROR;