ATLAS Offline Software
Loading...
Searching...
No Matches
d3pdReadersFromFile.cxx File Reference
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <boost/program_options.hpp>
#include <TFile.h>
#include <TList.h>
#include <TKey.h>
#include <TDirectory.h>
#include <TString.h>
#include <TObjString.h>
#include <TError.h>
#include "GaudiKernel/StatusCode.h"
#include "GaudiKernel/Bootstrap.h"
#include "GaudiKernel/IMessageSvc.h"
#include "GaudiKernel/ISvcLocator.h"
#include "AthenaKernel/errorcheck.h"
#include "CxxUtils/checker_macros.h"
#include "D3PDMakerUtils/ObjectMetadata.h"
#include "../Variable.h"
#include "../CodeGenerator_v2.h"
#include "../RootObjectMetadata.h"

Go to the source code of this file.

Functions

template<typename T>
std::ostream & operator<< (std::ostream &out, const std::vector< T > &vec)
 Formatted printing for vector objects.
StatusCode collectObjects (TDirectory *dir, std::set< D3PD::ObjectMetadata > &objects)
 Function collecting the objects from a specific directory in a file.
std::vector< D3PD::ObjectMetadatamergeObjects (const std::set< D3PD::ObjectMetadata > &objects)
 Function mergint the objects of the same type.
int main ATLAS_NOT_THREAD_SAFE (int argc, char *argv[])
 A convenience declaration to save myself some typeing.

Variables

static const char *const PROGRAM_DESC
 The program description that's printed with the available parameters.
static const char *const PROGRAM_GREETING
 A greeting text that's printed when the application starts up.

Function Documentation

◆ ATLAS_NOT_THREAD_SAFE()

int main ATLAS_NOT_THREAD_SAFE ( int argc,
char * argv[] )

A convenience declaration to save myself some typeing.

Definition at line 92 of file d3pdReadersFromFile.cxx.

92 {
93 // Let's disable the ROOT warnings:
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}
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
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::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.
output
Definition merge.py:16

◆ collectObjects()

StatusCode collectObjects ( TDirectory * dir,
std::set< D3PD::ObjectMetadata > & objects )

Function collecting the objects from a specific directory in a file.

This function is used to collect the metadata about D3PDObjects from one particular directory in one D3PD file.

Parameters
dirThe directory where metadata should be searched for
objectsThe global list of object metadata
Returns
StatusCode::SUCCESS if the operation was successful, StatusCode::FAILURE otherwise

Definition at line 363 of file d3pdReadersFromFile.cxx.

364 {
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}
D3PD variable metadata handling class.
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.

◆ mergeObjects()

std::vector< D3PD::ObjectMetadata > mergeObjects ( const std::set< D3PD::ObjectMetadata > & objects)

Function mergint the objects of the same type.

This function is used to merge the objects of the same type on its input.

This practically means that objects that have the same "object name" get merged, irrespective of their prefix.

Parameters
objectsA set of independent D3PDObjects
Returns
A merged list of D3PDObjects

Definition at line 444 of file d3pdReadersFromFile.cxx.

444 {
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}

◆ operator<<()

template<typename T>
std::ostream & operator<< ( std::ostream & out,
const std::vector< T > & vec )

Formatted printing for vector objects.

The code has to print a vector in at least one place. To make it easily readable in the code, I like to use such an output operator. It can be used for any kind of vector as long as the template type can also be printed with the << operator.

Parameters
outAn STL output stream
vecThe vector that should be printed
Returns
The same output stream that the operator received

Definition at line 67 of file d3pdReadersFromFile.cxx.

67 {
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}
std::vector< size_t > vec

Variable Documentation

◆ PROGRAM_DESC

const char* const PROGRAM_DESC
static
Initial value:
=
"This application can be used to create all the D3PDReader classes\n"
"from a D3PD file that stores the metadata of the D3PDObjects that\n"
"were used to create it"

The program description that's printed with the available parameters.

Definition at line 42 of file d3pdReadersFromFile.cxx.

◆ PROGRAM_GREETING

const char* const PROGRAM_GREETING
static
Initial value:
=
"*******************************************************************\n"
"* *\n"
"* D3PDReader standalone code generator *\n"
"* *\n"
"*******************************************************************"

A greeting text that's printed when the application starts up.

Definition at line 48 of file d3pdReadersFromFile.cxx.