]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/MUON/utils/dHLTrootify.cxx
Making important updates to the internal data structures:
[u/mrichter/AliRoot.git] / HLT / MUON / utils / dHLTrootify.cxx
CommitLineData
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>
42using std::cout;
43using std::cerr;
44using 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 */
70int 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 */
183int 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 */
237void 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 */
287int 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
395int 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