]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/utils/dHLTrootify.cxx
Making important updates to the internal data structures:
[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
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)
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.
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,
75                 bool maxLogging = false,
76                 bool checkData = false
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 '";
120                         params += AliHLTMUONUtils::DataBlockTypeToString(filetypes[i]);
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         
146         // Setup the component for data integrity checking.
147         if (checkData)
148         {
149                 AliHLTConfiguration checker(
150                                 "checker", AliHLTMUONConstants::DataCheckerComponentId(),
151                                 sources, "-warn_on_unexpected_block -ignorespec"
152                         );
153                 sources = "checker";
154         }
155         
156         // Setup the component which converts the raw internal dHLT data to ROOT objects.
157         AliHLTConfiguration convert("convert", AliHLTMUONConstants::RootifierComponentId(), sources, "");
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:
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;
240         os << "Usage: dHLTrootify [-help|-h] [-outfile|-o <output_file>] [-type|-t <typename>]" << endl;
241         os << "         [-debug|-d] [-check|-c] <filename> [<filename> ...]" << endl;
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;
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;
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;
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.
283  * @param checkData  Set to true if data integrity checking was requested.
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,
294                 bool& maxLogging,
295                 bool& checkData
296         )
297 {
298         numOfFiles = 0;
299         outputFile = NULL;
300         maxLogging = false;
301         checkData = false;
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                         {
316                                 cerr << "ERROR: Missing an output filename." << endl << endl;
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                         {
326                                 cerr << "ERROR: Missing a type specifier." << endl << endl;
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                 }
352                 else if (strcmp(argv[i], "-check") == 0 or strcmp(argv[i], "-c") == 0)
353                 {
354                         checkData = true;
355                 }
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;
424         bool checkData = false;
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,
436                                 outputFile, maxLogging, checkData
437                         );
438                 if (outputFile == NULL)
439                 {
440                         outputFile = "output.root";
441                 }
442                 if (returnCode == EXIT_SUCCESS)
443                 {
444                         returnCode = RootifyFiles(
445                                         filename, filetype, numOfFiles,
446                                         outputFile, maxLogging, checkData
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