The Gaudi Framework  master (37c0b60a)
extractEvt.C
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 //====================================================================
12 //
13 // Author : M.Frank CERN/LHCb
14 //
15 //====================================================================
16 // ROOT include files
17 #include <TBranch.h>
18 #include <TClass.h>
19 #include <TFile.h>
20 #include <TInterpreter.h>
21 #include <TROOT.h>
22 #include <TSystem.h>
23 #include <TTree.h>
24 #include <TUUID.h>
25 
26 // Standad C/C++ include files
27 #include <memory>
28 #include <stdexcept>
29 #include <string>
30 #include <vector>
31 
32 /*
33  * Gaudi namespace declaration
34  */
35 namespace Gaudi {
36 
44  struct RootRef {
46  int dbase, container, link, clid, svc, entry;
48  RootRef() { this->reset(); }
50  RootRef( const RootRef& c )
51  : dbase( c.dbase ), container( c.container ), link( c.link ), clid( c.clid ), svc( c.svc ), entry( c.entry ) {}
53  RootRef& operator=( const RootRef& c ) {
54  dbase = c.dbase;
55  container = c.container;
56  link = c.link;
57  clid = c.clid;
58  svc = c.svc;
59  entry = c.entry;
60  return *this;
61  }
63  void reset() {
64  dbase = -1;
65  container = -1;
66  link = -1;
67  entry = -1;
68  svc = 1;
69  clid = 1;
70  }
71  };
72 
81  struct RootObjectRefs {
86 
88  RootObjectRefs() = default;
90  RootObjectRefs( const RootObjectRefs& r ) : links( r.links ), refs( r.refs ) {}
92  ~RootObjectRefs() = default;
95  links = r.links;
96  refs = r.refs;
97  return *this;
98  }
99  };
100 
108  struct RootNTupleDescriptor {
116  unsigned long clid = 1;
118  RootNTupleDescriptor() = default;
120  virtual ~RootNTupleDescriptor() = default;
121  };
122 
123  typedef int ExtractStatus;
125 
127  protected:
129  TTree* m_evt_in = nullptr;
130  TTree* m_ref_in = nullptr;
131 
132  TFile* m_out = nullptr;
133  TTree* m_evt_out = nullptr;
134  TTree* m_ref_out = nullptr;
135 
136  int m_localDB_id = 0;
138 
139  public:
141  RootEventExtractor() = default;
142 
144  RootEventExtractor( const char* input, const char* output, const char* output_option );
145 
147  virtual ~RootEventExtractor();
148 
150  ExtractStatus openInput( const char* name );
151 
154 
156  ExtractStatus openOutput( const char* name, const char* option );
157 
160 
163 
165  ExtractStatus select( int evt_num );
166 
169  };
170 
172  int extractEvt( const char* input, const char* output, long num_evt );
173 } // namespace Gaudi
174 
175 using namespace Gaudi;
176 using namespace std;
177 
179 RootEventExtractor::RootEventExtractor( const char* input, const char* output, const char* output_option ) {
180  if ( EXTRACT_SUCCESS != openInput( input ) ) {
181  throw std::runtime_error( "Failed to open input file:" + std::string( input ) );
182  }
183  if ( EXTRACT_SUCCESS != openOutput( output, output_option ) ) {
184  throw std::runtime_error( "Failed to open output file:" + std::string( output ) );
185  }
186 }
187 
190  closeInput();
191  closeOutput();
192 }
193 
196  m_eventList.clear();
197  ::printf( "+++ Event list cleared.\n" );
198  return EXTRACT_SUCCESS;
199 }
200 
203  m_eventList.push_back( evt_num );
204  return EXTRACT_SUCCESS;
205 }
206 
209  if ( m_in ) closeInput();
210  m_in.reset( TFile::Open( name ) );
211  if ( m_in && !m_in->IsZombie() ) {
212  m_evt_in = (TTree*)m_in->Get( "Event" );
213  m_ref_in = (TTree*)m_in->Get( "Refs" );
214  return EXTRACT_SUCCESS;
215  }
216  return EXTRACT_ERROR;
217 }
218 
220 ExtractStatus RootEventExtractor::openOutput( const char* name, const char* option ) {
221  if ( m_out ) closeOutput();
222  m_out = TFile::Open( name, option );
223  m_evt_out = m_ref_out = nullptr;
224  return EXTRACT_SUCCESS;
225 }
226 
229  if ( m_in ) {
230  ::printf( "+++ Closing input file:%s\n", m_in->GetName() );
231  m_in->Close();
232  }
233  m_in.reset();
234  m_evt_in = nullptr;
235  m_ref_in = nullptr;
236  return EXTRACT_SUCCESS;
237 }
238 
241  if ( m_out ) {
242  ::printf( "+++ Closing output file:%s\n", m_out->GetName() );
243  if ( m_evt_out ) m_evt_out->Write();
244  if ( m_ref_out ) m_ref_out->Write();
245  m_out->Close();
246  delete m_out;
247  }
248  m_out = nullptr;
249  m_evt_out = nullptr;
250  m_ref_out = nullptr;
251  return EXTRACT_SUCCESS;
252 }
253 
256  char text[1024];
257  bool new_output = false;
258  TBranch *br_in, *br_out;
259  if ( !m_in || m_in->IsZombie() ) {
260  throw std::runtime_error( "Input file missing - cannot extract events." );
261  } else if ( !m_out || m_out->IsZombie() ) {
262  throw std::runtime_error( "Output file missing - cannot extract events." );
263  } else {
264  m_evt_out = (TTree*)m_out->Get( "Event" );
265  if ( !m_evt_out ) { m_evt_out = m_evt_in->CloneTree( 0 ); }
266  m_ref_out = (TTree*)m_out->Get( "Refs" );
267  if ( !m_ref_out ) {
268  m_ref_out = m_ref_in->CloneTree( 0 );
269  new_output = true;
270  }
271  }
272  m_localDB_id = -1;
273  if ( new_output ) {
274  ::printf( "+++ Copy refs table to new output file:%s\n", m_out->GetName() );
275  br_in = m_ref_in->GetBranch( "Databases" );
276  br_in->SetAddress( text );
277  br_out = m_ref_out->GetBranch( "Databases" );
278  br_out->SetAddress( text );
279  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
280  br_in->GetEntry( i );
281  br_out->Fill();
282  if ( m_localDB_id < 0 && strcmp( text, "<localDB>" ) == 0 ) { m_localDB_id = i; }
283  }
284 
285  br_in = m_ref_in->GetBranch( "Containers" );
286  br_in->SetAddress( text );
287  br_out = m_ref_out->GetBranch( "Containers" );
288  br_out->SetAddress( text );
289  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
290  br_in->GetEntry( i );
291  br_out->Fill();
292  }
293 
294  br_in = m_ref_in->GetBranch( "Links" );
295  br_in->SetAddress( text );
296  br_out = m_ref_out->GetBranch( "Links" );
297  br_out->SetAddress( text );
298  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
299  br_in->GetEntry( i );
300  br_out->Fill();
301  }
302 
303  br_in = m_ref_in->GetBranch( "Params" );
304  br_in->SetAddress( text );
305  br_out = m_ref_out->GetBranch( "Params" );
306  br_out->SetAddress( text );
307  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
308  br_in->GetEntry( i );
309  if ( strncmp( text, "PFN=", 4 ) == 0 ) { // Update PFN entry
310  ::snprintf( text, sizeof( text ), "PFN=%s", br_out->GetFile()->GetName() );
311  ::printf( "+++ PFN of the created output file is:%s\n", text );
312  } else if ( strncmp( text, "FID=", 4 ) == 0 ) { // Create new FID for new file
313  static const char* fmt = "FID=%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX";
314  union uuid_data {
315  unsigned char buf[16];
316  unsigned short sbuf[8];
317  unsigned int ibuf[4];
318  } d;
319  TUUID uuid;
320  uuid.GetUUID( d.buf );
321  ::snprintf( text, sizeof( text ), fmt, d.ibuf[0], d.sbuf[2], d.sbuf[3], d.buf[8], d.buf[9], d.buf[10],
322  d.buf[11], d.buf[12], d.buf[13], d.buf[14], d.buf[15] );
323  ::printf( "+++ FID of the created output file is:%s\n", text );
324  }
325  br_out->Fill();
326  }
327  m_ref_out->Write();
328  }
329 
330  TIter next( m_evt_in->GetListOfBranches() );
331  while ( ( br_in = (TBranch*)next() ) ) {
332  TString name = br_in->GetName();
333  TClass* br_class = gROOT->GetClass( br_in->GetClassName(), kTRUE );
334  br_out = m_evt_out->GetBranch( name );
335  if ( !br_out ) {
336  ::printf( "+++ ERROR: Input and output event trees are incompatible. Selection not possible.\n" );
337  return EXTRACT_ERROR;
338  }
339  int out_num_entries = br_out->GetEntries();
340  for ( const auto& i : m_eventList ) {
341  int num_evt = i;
342  const char* br_type = "DataObject";
343  void* pObject = br_class->New();
344  br_in->SetAddress( &pObject );
345  br_out->SetAddress( &pObject );
346  int num_rd = br_in->GetEntry( num_evt );
347  if ( num_rd < 0 ) { // Definitive error
348  ::printf( "+++ ERROR: Failed to read data from branch:%s\n", name.Data() );
349  return EXTRACT_ERROR;
350  }
351  if ( name.EndsWith( "_R." ) ) {
352  RootObjectRefs* refs = (RootObjectRefs*)pObject;
353  for ( auto& ir : refs->refs ) {
354  RootRef& r = ir;
355  if ( r.dbase == m_localDB_id ) r.entry = out_num_entries;
356  }
357  br_type = "*Index*";
358  }
359  int num_wr = br_out->Fill();
360  if ( num_wr < 0 ) {
361  ::printf( "+++ ERROR: Failed to write data to extraction branch:%s "
362  "read:%d wrote:%d bytes [Length-mismatch]\n",
363  name.Data(), num_rd, num_wr );
364  return EXTRACT_ERROR;
365  }
366  ::printf( "+++ Copied %8d bytes to %-10s branch %s(%d)\n", num_rd, br_type, name.Data(), out_num_entries );
367  ++out_num_entries;
368  }
369  m_evt_out->SetEntries( br_out->GetEntries() + 1 );
370  }
371  m_evt_out->Write();
372  return cancel();
373 }
374 
376 int Gaudi::extractEvt( const char* input, const char* output, long num_evt ) {
377  RootEventExtractor e( input, output, "RECREATE" );
378  if ( e.select( num_evt ) == EXTRACT_SUCCESS ) {
379  if ( e.extract() == EXTRACT_SUCCESS ) { return EXTRACT_SUCCESS; }
380  }
381  return EXTRACT_ERROR;
382 }
383 
384 int extract_event( const char* input, const char* output, long num_evt ) {
385  return extractEvt( input, output, num_evt );
386 }
387 
388 #if 0
389 int main(int, char**) {
390  gROOT->SetBatch(kTRUE);
391  gSystem->Load("libCintex.so");
392  gInterpreter->ProcessLine("ROOT::Cintex::Enable()");
393  return extractEvtFunc("castor:/castor/cern.ch/grid/lhcb/LHCb/Collision12/FULL.DST/00020565/0000/00020565_00005381_1.full.dst","bla.root",2);
394 }
395 #endif
Gaudi::RootEventExtractor::extract
ExtractStatus extract()
Extract all previously selected events from the input file and write it to the output.
Definition: extractEvt.C:255
Gaudi::EXTRACT_SUCCESS
@ EXTRACT_SUCCESS
Definition: extractEvt.C:124
Gaudi::RootEventExtractor::closeInput
ExtractStatus closeInput()
Close input file.
Definition: extractEvt.C:228
Gaudi::EXTRACT_ERROR
@ EXTRACT_ERROR
Definition: extractEvt.C:124
std::strcmp
T strcmp(T... args)
Gaudi::RootEventExtractor::m_evt_out
TTree * m_evt_out
Definition: extractEvt.C:133
Gaudi::RootNTupleDescriptor::optional
std::string optional
Optional description.
Definition: RootRefs.h:91
std::string
STL class.
Gaudi::RootNTupleDescriptor::clid
unsigned long clid
Class ID of the described object.
Definition: RootRefs.h:95
Gaudi::RootRef::clid
int clid
Definition: RootRefs.h:42
Gaudi::ExtractStatus
int ExtractStatus
Definition: extractEvt.C:123
Gaudi::RootEventExtractor::m_ref_out
TTree * m_ref_out
Definition: extractEvt.C:134
Gaudi::ExtractStatusEnum
ExtractStatusEnum
Definition: extractEvt.C:124
Gaudi::RootEventExtractor
Definition: extractEvt.C:126
Gaudi::RootNTupleDescriptor
Definition: RootRefs.h:87
Gaudi::RootRef::reset
void reset()
Reset data content.
Definition: RootRefs.h:50
Gaudi::RootEventExtractor::openInput
ExtractStatus openInput(const char *name)
Open input file.
Definition: extractEvt.C:208
std::vector< int >
Gaudi::RootEventExtractor::m_localDB_id
int m_localDB_id
Definition: extractEvt.C:136
Gaudi::RootRef::dbase
int dbase
Data members to define object location in the persistent world.
Definition: RootRefs.h:42
Gaudi::RootEventExtractor::m_evt_in
TTree * m_evt_in
Definition: extractEvt.C:129
gaudirun.c
c
Definition: gaudirun.py:525
Gaudi::RootObjectRefs::RootObjectRefs
RootObjectRefs(const RootObjectRefs &r)
Copy constructor.
Definition: extractEvt.C:90
Gaudi::RootEventExtractor::m_ref_in
TTree * m_ref_in
Definition: extractEvt.C:130
gaudirun.output
output
Definition: gaudirun.py:521
extract_event
int extract_event(const char *input, const char *output, long num_evt)
Definition: extractEvt.C:384
Gaudi::RootObjectRefs
Definition: RootRefs.h:68
Gaudi::RootNTupleDescriptor::~RootNTupleDescriptor
virtual ~RootNTupleDescriptor()=default
Standard destructor.
Gaudi::RootEventExtractor::cancel
ExtractStatus cancel()
Clear the list of event numbers to be extracted from the file.
Definition: extractEvt.C:195
Gaudi::RootObjectRefs::~RootObjectRefs
~RootObjectRefs()=default
Default destructor.
Gaudi::RootRef::link
int link
Definition: RootRefs.h:42
Gaudi::RootEventExtractor::openOutput
ExtractStatus openOutput(const char *name, const char *option)
Open output file.
Definition: extractEvt.C:220
Gaudi::RootRef::svc
int svc
Definition: RootRefs.h:42
Gaudi::RootEventExtractor::m_eventList
std::vector< int > m_eventList
Definition: extractEvt.C:137
Gaudi::RootEventExtractor::m_in
std::unique_ptr< TFile > m_in
Definition: extractEvt.C:128
Gaudi::RootObjectRefs::links
std::vector< int > links
The links of the link manager.
Definition: RootRefs.h:70
Gaudi::RootNTupleDescriptor::description
std::string description
Description string.
Definition: RootRefs.h:89
Gaudi::RootRef::container
int container
Definition: RootRefs.h:42
Gaudi::RootRef
Definition: RootRefs.h:40
Gaudi::RootEventExtractor::~RootEventExtractor
virtual ~RootEventExtractor()
Default destructor.
Definition: extractEvt.C:189
Gaudi::RootRef::operator=
RootRef & operator=(const RootRef &c)
Assignment operator.
Definition: extractEvt.C:53
std::runtime_error
STL class.
Gaudi::RootObjectRefs::operator=
RootObjectRefs & operator=(const RootObjectRefs &r)
Assignment operator.
Definition: extractEvt.C:94
Gaudi::RootNTupleDescriptor::RootNTupleDescriptor
RootNTupleDescriptor()=default
Standard constructor.
Gaudi
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition: __init__.py:1
Gaudi::RootRef::entry
int entry
Definition: RootRefs.h:42
std::strncmp
T strncmp(T... args)
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
Gaudi::RootEventExtractor::RootEventExtractor
RootEventExtractor()=default
Default constructor.
std
STL namespace.
Gaudi::RootObjectRefs::RootObjectRefs
RootObjectRefs()=default
Default constructor.
fmt
Gaudi::RootEventExtractor::select
ExtractStatus select(int evt_num)
Add a given entry number to the list of events to be selected to the output file.
Definition: extractEvt.C:202
Gaudi::RootRef::RootRef
RootRef()
Standard constructor.
Definition: extractEvt.C:48
Gaudi::RootEventExtractor::closeOutput
ExtractStatus closeOutput()
Close output file.
Definition: extractEvt.C:240
Gaudi::RootObjectRefs::refs
std::vector< RootRef > refs
The references corresponding to the next layer of items in the data store.
Definition: RootRefs.h:72
Gaudi::extractEvt
int extractEvt(const char *input, const char *output, long num_evt)
Function to extract single event and write it to an output file.
Definition: extractEvt.C:376
Gaudi::RootEventExtractor::m_out
TFile * m_out
Definition: extractEvt.C:132
Gaudi::RootNTupleDescriptor::container
std::string container
Identifier of description.
Definition: RootRefs.h:93
std::unique_ptr< TFile >
main
int main(int argc, char *argv[])
Definition: main.cpp:14
Gaudi::RootRef::RootRef
RootRef(const RootRef &c)
Copy constructor.
Definition: extractEvt.C:50
std::next
T next(T... args)