]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/utils/dHLTrootify.cxx
Improving documentation and macros.
[u/mrichter/AliRoot.git] / HLT / MUON / utils / dHLTrootify.cxx
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 namespace
54 {
55         // CDB path and run number to use.
56         const char* gCDBPath = "local://$ALICE_ROOT/OCDB";
57         Int_t gRunNumber = 0;
58 }
59
60 /**
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
74  *          objects.
75  */
76 int RootifyFiles(
77                 const char** filenames,
78                 AliHLTMUONDataBlockType* filetypes,
79                 int numOfFiles,
80                 const char* outputFile,
81                 bool maxLogging = false,
82                 bool checkData = false
83         )
84 {
85         AliHLTSystem sys;
86         
87         if (maxLogging)
88         {
89                 AliLog::SetGlobalLogLevel(AliLog::kMaxType);
90                 sys.SetGlobalLoggingLevel(kHLTLogAll);
91         }
92         
93         sys.LoadComponentLibraries("libAliHLTUtil.so");
94         sys.LoadComponentLibraries("libAliHLTMUON.so");
95         
96         TString sources = "";
97         typedef AliHLTConfiguration* PAliHLTConfiguration;
98         PAliHLTConfiguration* filePubs = NULL;
99         
100         try
101         {
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.
106                 int i;
107                 for (i = 0; i < numOfFiles; i++)
108                 {
109                         filePubs[i] = NULL;
110                 }
111                 
112                 // Now start allocating the file publishers.
113                 for (i = 0; i < numOfFiles; i++)
114                 {
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()
124                                 );
125                 }
126         }
127         catch (const std::bad_alloc&)
128         {
129                 cerr << "ERROR: There is not enough memory to allocate another configuration object." << endl;
130                 
131                 // Make sure to clean up what was actaully allocated.
132                 if (filePubs != NULL)
133                 {
134                         for (int i = 0; i < numOfFiles; i++)
135                         {
136                                 if (filePubs[i] != NULL)
137                                         delete filePubs[i];
138                         }
139                         delete [] filePubs;
140                 }
141                 
142                 return SYSTEM_ERROR;
143         }
144         
145         // Setup the component for data integrity checking.
146         if (checkData)
147         {
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(),
154                                 sources, dcparams
155                         );
156                 sources = "checker";
157         }
158         
159         // Setup the component which converts the raw internal dHLT data to ROOT objects.
160         AliHLTConfiguration convert("convert", AliHLTMUONConstants::RootifierComponentId(), sources, "");
161         
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());
167         
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;
172         
173         // Clean up all the dynamically allocate objects.
174         for (int i = 0; i < numOfFiles; i++)
175         {
176                 delete filePubs[i];
177         }
178         delete [] filePubs;
179
180         return EXIT_SUCCESS;
181 }
182
183 /**
184  * This method decodes the type of the file.
185  */
186 int DecodeFileType(const char* filename, AliHLTMUONDataBlockType& type)
187 {
188         assert( filename != NULL );
189         
190         // Open the file and find its size.
191         fstream file;
192         file.open(filename, ios::in);
193         if (not file)
194         {
195                 cerr << "ERROR: Could not open the file: " << filename << endl;
196                 return SYSTEM_ERROR;
197         }
198         
199         AliHLTMUONDataBlockHeader header;
200         file.read(reinterpret_cast<char*>(&header), sizeof(header));
201         if (not file)
202         {
203                 cerr << "ERROR: Could not read from file: " << filename << endl;
204                 return SYSTEM_ERROR;
205         }
206         
207         file.close();
208         if (not file)
209         {
210                 cerr << "ERROR: Could not close the file: " << filename << endl;
211                 return SYSTEM_ERROR;
212         }
213         
214         type = AliHLTMUONDataBlockType(header.fType);
215         
216         // Check that the type is something valid. Otherwise set it to a
217         // value of kUnknownDataBlock.
218         switch (type)
219         {
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:
229                 break;
230         default: type = kUnknownDataBlock;
231                 break;
232         }
233         
234         return EXIT_SUCCESS;
235 }
236
237 /**
238  * Prints the command line usage of this program to standard out or error.
239  */
240 void PrintUsage(bool asError = true)
241 {
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;
278 }
279
280 /**
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.
294  */
295 int ParseCommandLine(
296                 int argc,
297                 const char** argv,
298                 const char** filenames,
299                 AliHLTMUONDataBlockType* filetypes,
300                 int& numOfFiles,
301                 const char*& outputFile,
302                 bool& maxLogging,
303                 bool& checkData
304         )
305 {
306         numOfFiles = 0;
307         outputFile = NULL;
308         maxLogging = false;
309         checkData = false;
310         bool pathSet = false;
311         bool runSet = false;
312         AliHLTMUONDataBlockType currentType = kUnknownDataBlock;
313
314         // Parse the command line.
315         for (int i = 1; i < argc; i++)
316         {
317                 if (strcmp(argv[i], "-help") == 0 or strcmp(argv[i], "-h") == 0)
318                 {
319                         PrintUsage(false);
320                         return EXIT_SUCCESS;
321                 }
322                 else if (strcmp(argv[i], "-outfile") == 0 or strcmp(argv[i], "-o") == 0)
323                 {
324                         if (outputFile != NULL)
325                         {
326                                 cerr << "WARNING: Already used -outfile|-o with " << outputFile
327                                         << " before. Will override it with the last value specified with -outfile|-o."
328                                         << endl;
329                         }
330                         if (++i >= argc)
331                         {
332                                 cerr << "ERROR: Missing an output filename." << endl << endl;
333                                 PrintUsage();
334                                 return CMDLINE_ERROR;
335                         }
336                         outputFile = argv[i];
337                 }
338                 else if (strcmp(argv[i], "-type") == 0 or strcmp(argv[i], "-t") == 0)
339                 {
340                         if (++i >= argc)
341                         {
342                                 cerr << "ERROR: Missing a type specifier." << endl << endl;
343                                 PrintUsage();
344                                 return CMDLINE_ERROR;
345                         }
346                         // Now we need to parse the typename in the command line.
347                         if (strcmp(argv[i], "autodetect") == 0)
348                         {
349                                 currentType = kUnknownDataBlock;
350                         }
351                         else
352                         {
353                                 currentType = AliHLTMUONUtils::ParseCommandLineTypeString(argv[i]);
354                                 if (currentType == kUnknownDataBlock)
355                                 {
356                                         cerr << "ERROR: Invalid type name '" << argv[i]
357                                                 << "' specified for argument " << argv[i-1]
358                                                 << "." << endl << endl;
359                                         PrintUsage();
360                                         return CMDLINE_ERROR;
361                                 }
362                         }
363                 }
364                 else if (strcmp(argv[i], "-debug") == 0 or strcmp(argv[i], "-d") == 0)
365                 {
366                         maxLogging = true;
367                 }
368                 else if (strcmp(argv[i], "-check") == 0 or strcmp(argv[i], "-c") == 0)
369                 {
370                         checkData = true;
371                 }
372                 else if (strcmp(argv[i], "-cdbpath") == 0 or strcmp(argv[i], "-p") == 0)
373                 {
374                         if (pathSet)
375                         {
376                                 cerr << "WARNING: Already used -cdbpath|-p with '" << gCDBPath
377                                         << "' before. Will override it with the last value specified with -cdbpath|-p."
378                                         << endl;
379                         }
380                         if (++i >= argc)
381                         {
382                                 cerr << "ERROR: Missing the URL for the CDB path." << endl << endl;
383                                 PrintUsage();
384                                 return CMDLINE_ERROR;
385                         }
386                         gCDBPath = argv[i];
387                         pathSet = true;
388                 }
389                 else if (strcmp(argv[i], "-run") == 0 or strcmp(argv[i], "-r") == 0)
390                 {
391                         if (runSet)
392                         {
393                                 cerr << "WARNING: Already used -run|-r with " << gRunNumber
394                                         << " before. Will override it with the last value specified with -run|-r."
395                                         << endl;
396                         }
397                         if (++i >= argc)
398                         {
399                                 cerr << "ERROR: Missing the run number." << endl << endl;
400                                 PrintUsage();
401                                 return CMDLINE_ERROR;
402                         }
403                         
404                         char* cpErr = NULL;
405                         Int_t run = Int_t( strtol(argv[i], &cpErr, 0) );
406                         if (cpErr == NULL or *cpErr != '\0' or run < 0)
407                         {
408                                 cerr << "ERROR: Cannot convert '" << argv[i] << "' to a valid run number."
409                                         " Expected a positive integer value." << endl;
410                                 return CMDLINE_ERROR;
411                         }
412
413                         gRunNumber = run;
414                         runSet = true;
415                 }
416                 else
417                 {
418                         assert( numOfFiles < argc );
419                         filenames[numOfFiles] = argv[i];
420                         
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)
425                         {
426                                 int result = DecodeFileType(filenames[numOfFiles], typeToUse);
427                                 if (result != EXIT_SUCCESS) return result;
428                                 if (typeToUse == kUnknownDataBlock)
429                                 {
430                                         cerr << "ERROR: Could not decode what type of data"
431                                                 " is stored in the file:"
432                                                 << filenames[numOfFiles] << endl;
433                                         return PARSE_ERROR;
434                                 }
435                         }
436                         
437                         filetypes[numOfFiles] = typeToUse;
438                         numOfFiles++;
439                 }
440         }
441         
442         // Now check that we have at least one filename and all the flags we need.
443         if (numOfFiles == 0)
444         {
445                 cerr << "ERROR: Missing a file name. You must specify at least one file to process."
446                         << endl << endl;
447                 PrintUsage();
448                 return CMDLINE_ERROR;
449         }
450         
451         return EXIT_SUCCESS;
452 }
453
454
455 int main(int argc, const char** argv)
456 {
457         // Test endianess of this machine during runtime and print warning if it is not
458         // little endian.
459         union
460         {
461                 int dword;
462                 char byte[4];
463         } endianTest;
464         endianTest.dword = 0x1;
465         if (endianTest.byte[0] != 0x1)
466         {
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;
477                 cerr << endl;
478         }
479
480
481         int numOfFiles = 0;
482         const char* outputFile = NULL;
483         bool maxLogging = false;
484         bool checkData = false;
485         int returnCode = EXIT_SUCCESS;
486
487         try
488         {
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];
493                 
494                 returnCode = ParseCommandLine(
495                                 argc, argv, filename, filetype, numOfFiles,
496                                 outputFile, maxLogging, checkData
497                         );
498                 if (outputFile == NULL)
499                 {
500                         outputFile = "output.root";
501                 }
502                 if (returnCode == EXIT_SUCCESS)
503                 {
504                         returnCode = RootifyFiles(
505                                         filename, filetype, numOfFiles,
506                                         outputFile, maxLogging, checkData
507                                 );
508                 }
509                 
510                 delete [] filename;
511                 delete [] filetype;
512         }
513         catch (...)
514         {
515                 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
516                 returnCode = FATAL_ERROR;
517         }
518         
519         return returnCode;
520 }
521