ATLAS Offline Software
Loading...
Searching...
No Matches
d3pdReadersFromFile.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6// STL include(s):
7#include <iostream>
8#include <vector>
9#include <string>
10#include <map>
11#include <set>
12
13// Boost include(s):
14#include <boost/program_options.hpp>
15
16// ROOT include(s):
17#include <TFile.h>
18#include <TList.h>
19#include <TKey.h>
20#include <TDirectory.h>
21#include <TString.h>
22#include <TObjString.h>
23#include <TError.h>
24
25// Gaudi/Athena include(s):
26#include "GaudiKernel/StatusCode.h"
27#include "GaudiKernel/Bootstrap.h"
28#include "GaudiKernel/IMessageSvc.h"
29#include "GaudiKernel/ISvcLocator.h"
32
33// D3PD include(s):
35
36// Local include(s):
37#include "../Variable.h"
38#include "../CodeGenerator_v2.h"
40
42static const char* const PROGRAM_DESC =
43 "This application can be used to create all the D3PDReader classes\n"
44 "from a D3PD file that stores the metadata of the D3PDObjects that\n"
45 "were used to create it";
46
48static const char* const PROGRAM_GREETING =
49 "*******************************************************************\n"
50 "* *\n"
51 "* D3PDReader standalone code generator *\n"
52 "* *\n"
53 "*******************************************************************";
54
56
66template< typename T >
67std::ostream& operator<<( std::ostream& out, const std::vector< T >& vec ) {
68 out << "[";
69 typename std::vector< T >::const_iterator itr = vec.begin();
70 typename std::vector< T >::const_iterator end = vec.end();
71 for( ; itr != end; ++itr ) {
72 out << *itr;
73 if( ++itr != end ) {
74 out << ", ";
75 }
76 --itr;
77 }
78 out << "]";
79 return out;
80}
81
83StatusCode collectObjects( TDirectory* dir,
84 std::set< D3PD::ObjectMetadata >& objects );
86std::vector< D3PD::ObjectMetadata >
87mergeObjects( const std::set< D3PD::ObjectMetadata >& objects );
88
90namespace po = boost::program_options;
91//coverity[root_function]
92int main ATLAS_NOT_THREAD_SAFE ( int argc, char* argv[] ) {
93 // Let's disable the ROOT warnings:
94 gErrorIgnoreLevel = kError;
95
96 // Force the Gaudi MessageSvc into existence. This gets rid of the
97 // warnings from getMessageSvc().
98 SmartIF<IMessageSvc> msvc{Gaudi::svcLocator()->service("MessageSvc")};
99 if( !msvc ) {
100 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
101 << "Couldn't set up the Gaudi message service";
102 return 255;
103 }
104
105 //
106 // Construct the object describing all the command line parameters of the
107 // application:
108 //
109 po::options_description desc( PROGRAM_DESC );
110 desc.add_options()
111 ( "help,h", "Give some help with the program usage" )
112 ( "d3pd-files,f", po::value< std::vector< std::string > >()->multitoken(),
113 "Input D3PD file(s)" )
114 ( "event-class-name,n", po::value< std::string >()->default_value( "Event" ),
115 "Name for the D3PDReader event class" )
116 ( "output,o", po::value< std::string >()->default_value( "." ),
117 "Output directory for the generated source files" )
118 ( "verbosity,v", po::value< int >()->default_value( 3 ),
119 "Verbosity level of the application. (1:VERBOSE, 2:DEBUG, 3:INFO, ...)" );
120
121 //
122 // Interpret the command line options provided by the user:
123 //
124 po::variables_map vm;
125 try {
126 po::store( po::parse_command_line( argc, argv, desc ), vm );
127 po::notify( vm );
128 } catch( const std::exception& ex ) {
129 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
130 << "There was a problem with interpreting the command line options.";
131 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
132 << "Message: " << ex.what();
133 return 255;
134 }
135
136 //
137 // If the user asked for some help, let's print it:
138 //
139 if( vm.count( "help" ) ) {
140 std::cout << desc << std::endl;
141 return 0;
142 }
143
144 //
145 // Set the verbosity level of the application:
146 //
147 msvc->setOutputLevel( vm[ "verbosity" ].as< int >() );
148
149 //
150 // Greet the user, and print all the parameters that the application
151 // received:
152 //
153 std::cout << PROGRAM_GREETING << std::endl;
154
155 // Extract the file name(s) from the command line arguments:
156 if( ! vm.count( "d3pd-files" ) ) {
157 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
158 << "You have to specify at least one D3PD file!";
159 return 255;
160 }
161 const std::vector< std::string > file_names =
162 vm[ "d3pd-files" ].as< std::vector< std::string > >();
163 std::cout << " D3PD file(s): " << file_names << std::endl;
164
165 // Get the event class name:
166 const std::string event_name = vm[ "event-class-name" ].as< std::string >();
167 std::cout << " Event class name: " << event_name << std::endl;
168
169 // Get the output directory:
170 const std::string output = vm[ "output" ].as< std::string >();
171 std::cout << " Output directory: " << output << std::endl;
172
173 //
174 // A list of all the objects collected from all the files:
175 //
176 std::set< D3PD::ObjectMetadata > objects;
177
178 //
179 // Loop over the specified files:
180 //
181 std::vector< std::string >::const_iterator file_itr = file_names.begin();
182 std::vector< std::string >::const_iterator file_end = file_names.end();
183 for( ; file_itr != file_end; ++file_itr ) {
184
185 // Try to open the D3PD file:
186 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "d3pdReadersFromFile" )
187 << "Reading file: " << *file_itr;
188 TFile* ifile = TFile::Open( file_itr->c_str(), "READ" );
189 if( ( ! ifile ) || ifile->IsZombie() ) {
190 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
191 << "Failed to open D3PD file: " << *file_itr;
192 return 255;
193 }
194
195 // Search for the metadata directories:
196 std::vector< std::string > metaDirectories;
197 const TList* keys = ifile->GetListOfKeys();
198 for( Int_t i = 0; i < keys->GetSize(); ++i ) {
199 const TKey* key = dynamic_cast< TKey* >( keys->At( i ) );
200 if (!key) continue;
201 std::string key_name = key->GetName();
202 if( ( key_name.find( "Meta" ) != key_name.npos ) &&
203 ( key->GetClassName() == std::string( "TDirectoryFile" ) ) ) {
204 metaDirectories.push_back( std::move(key_name) );
205 }
206 }
207
208 // Collect the objects from each of these directories:
209 std::vector< std::string >::const_iterator dir_itr = metaDirectories.begin();
210 std::vector< std::string >::const_iterator dir_end = metaDirectories.end();
211 for( ; dir_itr != dir_end; ++dir_itr ) {
212 // Try to access the directory:
213 TDirectory* dir = ifile->GetDirectory( dir_itr->c_str() );
214 if( ! dir ) {
215 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
216 << "Failed to access directory: " << *dir_itr;
217 return 255;
218 }
219 // Collect the metadata from this directory:
220 if( collectObjects( dir, objects ).isFailure() ) {
221 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
222 << "Failed to collect variable definitions from metadata directory: "
223 << *dir_itr;
224 return 255;
225 }
226 }
227
228 // Close the input file:
229 ifile->Close();
230 delete ifile;
231 }
232
233 //
234 // Merge the objects of the same type:
235 //
236 std::vector< D3PD::ObjectMetadata > merged_objects = mergeObjects( objects );
237 if( ! merged_objects.size() ) {
238 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
239 << "Didn't find any metadata about the D3PD variables in the "
240 << "specified file(s)!";
241 return 255;
242 }
243
244 //
245 // Generate the D3PDObjectBase class's source:
246 //
247 if( D3PD::Version2::writeD3PDObjectBase( output ).isFailure() ) {
248 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
249 << "Couldn't create the D3PDObjectBase class source";
250 return 255;
251 }
252
253 //
254 // Generate the VarHandle class's source:
255 //
256 if( D3PD::Version2::writeVarHandle( output ).isFailure() ) {
257 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
258 << "Couldn't create the VarHandle class source";
259 return 255;
260 }
261
262 //
263 // Generate the VarProxy class's source if needed:
264 //
265 if( D3PD::Version2::writeVarProxy( output ).isFailure() ) {
266 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
267 << "Couldn't create the VarProxy class source";
268 return 255;
269 }
270
271 //
272 // Generate the UserD3PDObject class's source:
273 //
274 if( D3PD::Version2::writeUserD3PDObject( output ).isFailure() ) {
275 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
276 << "Couldn't create the UserD3PDObject class source";
277 return 255;
278 }
279
280 //
281 // Generate the D3PDReadStats class's source:
282 //
283 if( D3PD::Version2::writeD3PDReadStats( output ).isFailure() ) {
284 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
285 << "Couldn't create the D3PDReadStats class source";
286 return 255;
287 }
288
289 //
290 // Generate the D3PDPerfStats class's source:
291 //
292 if( D3PD::Version2::writeD3PDPerfStats( output ).isFailure() ) {
293 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
294 << "Couldn't create the D3PDPerfStats class source";
295 return 255;
296 }
297
298 //
299 // Generate the Utils source:
300 //
301 if( D3PD::Version2::writeUtils( output ).isFailure() ) {
302 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
303 << "Couldn't create the Utils source";
304 return 255;
305 }
306
307 //
308 // Generate the sources for each object:
309 //
310 std::vector< D3PD::ObjectMetadata >::const_iterator obj_itr = merged_objects.begin();
311 std::vector< D3PD::ObjectMetadata >::const_iterator obj_end = merged_objects.end();
312 for( ; obj_itr != obj_end; ++obj_itr ) {
313
314 //
315 // Generate the header of the D3PDReader class:
316 //
317 if( D3PD::Version2::writeHeader( obj_itr->name(), output,
318 *obj_itr ).isFailure() ) {
319 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
320 << "Couldn't generate the D3PDReader class header";
321 return 255;
322 }
323
324 //
325 // Generate the source of the D3PDReader class:
326 //
327 if( D3PD::Version2::writeSource( obj_itr->name(), output,
328 *obj_itr ).isFailure() ) {
329 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
330 << "Couldn't generate the D3PDReader class source";
331 return 255;
332 }
333 }
334
335 //
336 // Generate the "event class":
337 //
338 if( D3PD::Version2::writeEventHeader( event_name, output,
339 objects ).isFailure() ) {
340 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
341 << "Couldn't generate the D3PDReader event class header";
342 return 255;
343 }
344 if( D3PD::Version2::writeEventSource( event_name, output,
345 objects ).isFailure() ) {
346 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
347 << "Couldn't generate the D3PDReader event class source";
348 return 255;
349 }
350
351 return 0;
352}
353
363StatusCode collectObjects( TDirectory* dir,
364 std::set< D3PD::ObjectMetadata >& objects ) {
365
366 // Find all the D3PDObject definitions in the directory:
367 const TList* keys = dir->GetListOfKeys();
368 for( Int_t i = 0; i < keys->GetSize(); ++i ) {
369
370 // Look for D3PDObject definitions:
371 const TKey* key = dynamic_cast< TKey* >( keys->At( i ) );
372 if (!key) continue;
373 if( key->GetClassName() != std::string( "TObjString" ) ) continue;
374
375 // Check whether it looks like object metadata:
376 if( ! D3PD::RootObjectMetadata::isObjectMetadata( key->GetName() ) ) {
377 continue;
378 }
379
380 // The name of the D3PDObject:
381 const std::string objName = D3PD::ObjectMetadata::objectName( key->GetName() );
382
383 REPORT_MESSAGE_WITH_CONTEXT( MSG::DEBUG, "d3pdReadersFromFile" )
384 << "Reading object '" << objName << "'";
385
386 // Access the variable description:
387 TObjString* ostring =
388 dynamic_cast< TObjString* >( dir->Get( TString( key->GetName() ) + ";" +
389 TString::Format( "%hi", key->GetCycle() ) ) );
390 if( ! ostring ) {
391 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
392 << "Couldn't access object: " << key->GetName() << ";"
393 << key->GetCycle();
394 return StatusCode::FAILURE;
395 }
396
397 // Decode the metadata:
399 metadata.setName( objName );
400 if( metadata.read( ostring->GetString().Data() ).isFailure() ) {
401 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
402 << "Couldn't collect variables from object: " << key->GetName();
403 return StatusCode::FAILURE;
404 }
405
406 // Fix the variable names if they need fixing:
407 if( metadata.checkPrefixes().isFailure() ) {
408 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "d3pdReadersFromFile" )
409 << "Couldn't fix prefixes in metadata object with name: "
410 << metadata.name();
411 return StatusCode::FAILURE;
412 }
413
414 // Check if such an object has already been added:
415 std::pair< std::set< D3PD::ObjectMetadata >::iterator, bool > ret =
416 objects.insert( metadata );
417 // If this object already existed, merge the two:
418 if( ! ret.second ) {
419 REPORT_MESSAGE_WITH_CONTEXT( MSG::DEBUG, "d3pdReadersFromFile" )
420 << "Merging objects with name '" << objName << "'";
421 D3PD::ObjectMetadata merged( *( ret.first ) );
422 merged.merge( metadata );
423 objects.erase( ret.first );
424 objects.insert( merged );
425 } else {
426 REPORT_MESSAGE_WITH_CONTEXT( MSG::DEBUG, "d3pdReadersFromFile" )
427 << "Added object with name '" << objName << "'";
428 }
429
430 }
431
432 return StatusCode::SUCCESS;
433}
434
443std::vector< D3PD::ObjectMetadata >
444mergeObjects( const std::set< D3PD::ObjectMetadata >& objects ) {
445
446 // Internal map for executing the merging:
447 std::map< std::string, D3PD::ObjectMetadata > tmp_result;
448
449 // Merge the objects using the temporary map:
450 std::set< D3PD::ObjectMetadata >::const_iterator set_itr = objects.begin();
451 std::set< D3PD::ObjectMetadata >::const_iterator set_end = objects.end();
452 for( ; set_itr != set_end; ++set_itr ) {
453 tmp_result[ set_itr->name() ].setName( set_itr->name() );
454 tmp_result[ set_itr->name() ].setPrefix( set_itr->prefix() );
455 tmp_result[ set_itr->name() ].setContainer( set_itr->container() );
456 tmp_result[ set_itr->name() ].merge( *set_itr );
457 }
458
459 // Copy the objects from the temporary map into the result vector:
460 std::vector< D3PD::ObjectMetadata > result;
461 std::map< std::string, D3PD::ObjectMetadata >::const_iterator map_itr =
462 tmp_result.begin();
463 std::map< std::string, D3PD::ObjectMetadata >::const_iterator map_end =
464 tmp_result.end();
465 for( ; map_itr != map_end; ++map_itr ) {
466 result.push_back( map_itr->second );
467 }
468
469 return result;
470}
std::vector< size_t > vec
Helpers for checking error return status codes and reporting errors.
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
int main(int, char **)
Main class for all the CppUnit test classes.
Define macros for attributes used to control the static checker.
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
D3PD variable metadata handling class.
ObjectMetadata & merge(const ObjectMetadata &obj)
Function merging the contents of two objects.
static std::string objectName(const std::string &metaName)
Get the D3PDObject's name from the name of the metadata object.
Extension of the ObjectMetadata class for reading D3PD files.
static bool isObjectMetadata(const std::string &name)
Function guessing if an object with a given name is object metadata.
static const char *const PROGRAM_GREETING
A greeting text that's printed when the application starts up.
static const char *const PROGRAM_DESC
The program description that's printed with the available parameters.
std::ostream & operator<<(std::ostream &out, const std::vector< T > &vec)
Formatted printing for vector objects.
std::vector< D3PD::ObjectMetadata > mergeObjects(const std::set< D3PD::ObjectMetadata > &objects)
Function mergint the objects of the same type.
StatusCode collectObjects(TDirectory *dir, std::set< D3PD::ObjectMetadata > &objects)
Function collecting the objects from a specific directory in a file.
StatusCode writeUtils(const std::string &dir)
This function can be used to create source files containing some utility functions.
StatusCode writeHeader(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to create the header of the class describing a set of D3PD variables.
StatusCode writeEventSource(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the source of the main event class describing a D3PD tree.
StatusCode writeD3PDReadStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDReadStats class's source files.
StatusCode writeSource(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to generate the source file of a D3PDReader class.
StatusCode writeVarHandle(const std::string &dir)
This function can be used to create the D3PDReader::VarHandle class's source files.
StatusCode writeVarProxy(const std::string &dir)
This function can be used to create the D3PDReader::VarProxy class's source files.
StatusCode writeEventHeader(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the header of the main event class describing a D3PD tree.
StatusCode writeD3PDObjectBase(const std::string &dir)
This function can be used to create the D3PDReader::D3PDObjectBase class's source files.
StatusCode writeUserD3PDObject(const std::string &dir)
This function can be used to create the D3PDReader::UserD3PDObject class's source files.
StatusCode writeD3PDPerfStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDPerfStats class's source files.