The Gaudi Framework  v32r2 (46d42edc)
extractEvt.C
Go to the documentation of this file.
1 //====================================================================
2 //
3 // Author : M.Frank CERN/LHCb
4 //
5 //====================================================================
6 // ROOT include files
7 #include "TBranch.h"
8 #include "TClass.h"
9 #include "TFile.h"
10 #include "TInterpreter.h"
11 #include "TROOT.h"
12 #include "TSystem.h"
13 #include "TTree.h"
14 #include "TUUID.h"
15 
16 // Standad C/C++ include files
17 #include <memory>
18 #include <stdexcept>
19 #include <string>
20 #include <vector>
21 
22 /*
23  * Gaudi namespace declaration
24  */
25 namespace Gaudi {
26 
34  struct RootRef {
38  RootRef() { this->reset(); }
40  RootRef( const RootRef& c )
41  : dbase( c.dbase ), container( c.container ), link( c.link ), clid( c.clid ), svc( c.svc ), entry( c.entry ) {}
43  RootRef& operator=( const RootRef& c ) {
44  dbase = c.dbase;
45  container = c.container;
46  link = c.link;
47  clid = c.clid;
48  svc = c.svc;
49  entry = c.entry;
50  return *this;
51  }
53  void reset() {
54  dbase = -1;
55  container = -1;
56  link = -1;
57  entry = -1;
58  svc = 1;
59  clid = 1;
60  }
61  };
62 
71  struct RootObjectRefs {
76 
78  RootObjectRefs() = default;
80  RootObjectRefs( const RootObjectRefs& r ) : links( r.links ), refs( r.refs ) {}
82  ~RootObjectRefs() = default;
85  links = r.links;
86  refs = r.refs;
87  return *this;
88  }
89  };
90 
106  unsigned long clid;
108  RootNTupleDescriptor() = default;
110  virtual ~RootNTupleDescriptor() = default;
111  };
112 
113  typedef int ExtractStatus;
115 
117  protected:
119  TTree* m_evt_in = nullptr;
120  TTree* m_ref_in = nullptr;
121 
122  TFile* m_out = nullptr;
123  TTree* m_evt_out = nullptr;
124  TTree* m_ref_out = nullptr;
125 
126  int m_localDB_id = 0;
128 
129  public:
131  RootEventExtractor() = default;
132 
134  RootEventExtractor( const char* input, const char* output, const char* output_option );
135 
137  virtual ~RootEventExtractor();
138 
140  ExtractStatus openInput( const char* name );
141 
144 
146  ExtractStatus openOutput( const char* name, const char* option );
147 
150 
153 
155  ExtractStatus select( int evt_num );
156 
159  };
160 
162  int extractEvt( const char* input, const char* output, long num_evt );
163 } // namespace Gaudi
164 
165 using namespace Gaudi;
166 using namespace std;
167 
169 RootEventExtractor::RootEventExtractor( const char* input, const char* output, const char* output_option ) {
170  if ( EXTRACT_SUCCESS != openInput( input ) ) {
171  throw std::runtime_error( "Failed to open input file:" + std::string( input ) );
172  }
173  if ( EXTRACT_SUCCESS != openOutput( output, output_option ) ) {
174  throw std::runtime_error( "Failed to open output file:" + std::string( output ) );
175  }
176 }
177 
180  closeInput();
181  closeOutput();
182 }
183 
186  m_eventList.clear();
187  ::printf( "+++ Event list cleared.\n" );
188  return EXTRACT_SUCCESS;
189 }
190 
193  m_eventList.push_back( evt_num );
194  return EXTRACT_SUCCESS;
195 }
196 
199  if ( m_in ) closeInput();
200  m_in.reset( TFile::Open( name ) );
201  if ( m_in && !m_in->IsZombie() ) {
202  m_evt_in = (TTree*)m_in->Get( "Event" );
203  m_ref_in = (TTree*)m_in->Get( "Refs" );
204  return EXTRACT_SUCCESS;
205  }
206  return EXTRACT_ERROR;
207 }
208 
210 ExtractStatus RootEventExtractor::openOutput( const char* name, const char* option ) {
211  if ( m_out ) closeOutput();
212  m_out = TFile::Open( name, option );
213  m_evt_out = m_ref_out = nullptr;
214  return EXTRACT_SUCCESS;
215 }
216 
219  if ( m_in ) {
220  ::printf( "+++ Closing input file:%s\n", m_in->GetName() );
221  m_in->Close();
222  }
223  m_in.reset();
224  m_evt_in = nullptr;
225  m_ref_in = nullptr;
226  return EXTRACT_SUCCESS;
227 }
228 
231  if ( m_out ) {
232  ::printf( "+++ Closing output file:%s\n", m_out->GetName() );
233  if ( m_evt_out ) m_evt_out->Write();
234  if ( m_ref_out ) m_ref_out->Write();
235  m_out->Close();
236  delete m_out;
237  }
238  m_out = nullptr;
239  m_evt_out = nullptr;
240  m_ref_out = nullptr;
241  return EXTRACT_SUCCESS;
242 }
243 
246  char text[1024];
247  bool new_output = false;
248  TBranch *br_in, *br_out;
249  if ( !m_in || m_in->IsZombie() ) {
250  throw std::runtime_error( "Input file missing - cannot extract events." );
251  } else if ( !m_out || m_out->IsZombie() ) {
252  throw std::runtime_error( "Output file missing - cannot extract events." );
253  } else {
254  m_evt_out = (TTree*)m_out->Get( "Event" );
255  if ( !m_evt_out ) { m_evt_out = m_evt_in->CloneTree( 0 ); }
256  m_ref_out = (TTree*)m_out->Get( "Refs" );
257  if ( !m_ref_out ) {
258  m_ref_out = m_ref_in->CloneTree( 0 );
259  new_output = true;
260  }
261  }
262  m_localDB_id = -1;
263  if ( new_output ) {
264  ::printf( "+++ Copy refs table to new output file:%s\n", m_out->GetName() );
265  br_in = m_ref_in->GetBranch( "Databases" );
266  br_in->SetAddress( text );
267  br_out = m_ref_out->GetBranch( "Databases" );
268  br_out->SetAddress( text );
269  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
270  br_in->GetEntry( i );
271  br_out->Fill();
272  if ( m_localDB_id < 0 && strcmp( text, "<localDB>" ) == 0 ) { m_localDB_id = i; }
273  }
274 
275  br_in = m_ref_in->GetBranch( "Containers" );
276  br_in->SetAddress( text );
277  br_out = m_ref_out->GetBranch( "Containers" );
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  }
283 
284  br_in = m_ref_in->GetBranch( "Links" );
285  br_in->SetAddress( text );
286  br_out = m_ref_out->GetBranch( "Links" );
287  br_out->SetAddress( text );
288  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
289  br_in->GetEntry( i );
290  br_out->Fill();
291  }
292 
293  br_in = m_ref_in->GetBranch( "Params" );
294  br_in->SetAddress( text );
295  br_out = m_ref_out->GetBranch( "Params" );
296  br_out->SetAddress( text );
297  for ( int i = 0; i < br_in->GetEntries(); ++i ) {
298  br_in->GetEntry( i );
299  if ( strncmp( text, "PFN=", 4 ) == 0 ) { // Update PFN entry
300  ::snprintf( text, sizeof( text ), "PFN=%s", br_out->GetFile()->GetName() );
301  ::printf( "+++ PFN of the created output file is:%s\n", text );
302  } else if ( strncmp( text, "FID=", 4 ) == 0 ) { // Create new FID for new file
303  static const char* fmt = "FID=%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX";
304  union uuid_data {
305  unsigned char buf[16];
306  unsigned short sbuf[8];
307  unsigned int ibuf[4];
308  } d;
309  TUUID uuid;
310  uuid.GetUUID( d.buf );
311  ::snprintf( text, sizeof( text ), fmt, d.ibuf[0], d.sbuf[2], d.sbuf[3], d.buf[8], d.buf[9], d.buf[10],
312  d.buf[11], d.buf[12], d.buf[13], d.buf[14], d.buf[15] );
313  ::printf( "+++ FID of the created output file is:%s\n", text );
314  }
315  br_out->Fill();
316  }
317  m_ref_out->Write();
318  }
319 
320  TIter next( m_evt_in->GetListOfBranches() );
321  while ( ( br_in = (TBranch*)next() ) ) {
322  TString name = br_in->GetName();
323  TClass* br_class = gROOT->GetClass( br_in->GetClassName(), kTRUE );
324  br_out = m_evt_out->GetBranch( name );
325  if ( !br_out ) {
326  ::printf( "+++ ERROR: Input and output event trees are incompatible. Selection not possible.\n" );
327  return EXTRACT_ERROR;
328  }
329  int out_num_entries = br_out->GetEntries();
330  for ( const auto& i : m_eventList ) {
331  int num_evt = i;
332  const char* br_type = "DataObject";
333  void* pObject = br_class->New();
334  br_in->SetAddress( &pObject );
335  br_out->SetAddress( &pObject );
336  int num_rd = br_in->GetEntry( num_evt );
337  if ( num_rd < 0 ) { // Definitive error
338  ::printf( "+++ ERROR: Failed to read data from branch:%s\n", name.Data() );
339  return EXTRACT_ERROR;
340  }
341  if ( name.EndsWith( "_R." ) ) {
342  RootObjectRefs* refs = (RootObjectRefs*)pObject;
343  for ( auto& ir : refs->refs ) {
344  RootRef& r = ir;
345  if ( r.dbase == m_localDB_id ) r.entry = out_num_entries;
346  }
347  br_type = "*Index*";
348  }
349  int num_wr = br_out->Fill();
350  if ( num_wr < 0 ) {
351  ::printf( "+++ ERROR: Failed to write data to extraction branch:%s "
352  "read:%d wrote:%d bytes [Length-mismatch]\n",
353  name.Data(), num_rd, num_wr );
354  return EXTRACT_ERROR;
355  }
356  ::printf( "+++ Copied %8d bytes to %-10s branch %s(%d)\n", num_rd, br_type, name.Data(), out_num_entries );
357  ++out_num_entries;
358  }
359  m_evt_out->SetEntries( br_out->GetEntries() + 1 );
360  }
361  m_evt_out->Write();
362  return cancel();
363 }
364 
366 int Gaudi::extractEvt( const char* input, const char* output, long num_evt ) {
367  RootEventExtractor e( input, output, "RECREATE" );
368  if ( e.select( num_evt ) == EXTRACT_SUCCESS ) {
369  if ( e.extract() == EXTRACT_SUCCESS ) { return EXTRACT_SUCCESS; }
370  }
371  return EXTRACT_ERROR;
372 }
373 
374 int extract_event( const char* input, const char* output, long num_evt ) {
375  return extractEvt( input, output, num_evt );
376 }
377 
378 #if 0
379 int main(int, char**) {
380  gROOT->SetBatch(kTRUE);
381  gSystem->Load("libCintex.so");
382  gInterpreter->ProcessLine("ROOT::Cintex::Enable()");
383  return extractEvtFunc("castor:/castor/cern.ch/grid/lhcb/LHCb/Collision12/FULL.DST/00020565/0000/00020565_00005381_1.full.dst","bla.root",2);
384 }
385 #endif
RootRef(const RootRef &c)
Copy constructor.
Definition: extractEvt.C:40
STL namespace.
ExtractStatus openOutput(const char *name, const char *option)
Open output file.
Definition: extractEvt.C:210
std::vector< int > links
The links of the link manager.
Definition: extractEvt.C:73
Persistent reference object containing all leafs and links corresponding to a Gaudi DataObject.
Definition: extractEvt.C:71
RootObjectRefs(const RootObjectRefs &r)
Copy constructor.
Definition: extractEvt.C:80
STL class.
ExtractStatus closeInput()
Close input file.
Definition: extractEvt.C:218
ExtractStatus closeOutput()
Close output file.
Definition: extractEvt.C:230
int dbase
Data members to define object location in the persistent world.
Definition: extractEvt.C:36
Persistent reference object.
Definition: extractEvt.C:34
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:192
std::string optional
Optional description.
Definition: extractEvt.C:102
RootNTupleDescriptor()=default
Standard constructor.
T next(T... args)
T strcmp(T... args)
~RootObjectRefs()=default
Default destructor.
std::string description
Description string.
Definition: extractEvt.C:100
int ExtractStatus
Definition: extractEvt.C:113
std::vector< int > m_eventList
Definition: extractEvt.C:127
ExtractStatus openInput(const char *name)
Open input file.
Definition: extractEvt.C:198
void reset()
Reset data content.
Definition: extractEvt.C:53
virtual ~RootEventExtractor()
Default destructor.
Definition: extractEvt.C:179
int extract_event(const char *input, const char *output, long num_evt)
Definition: extractEvt.C:374
RootObjectRefs()=default
Default constructor.
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:366
ExtractStatusEnum
Definition: extractEvt.C:114
virtual ~RootNTupleDescriptor()=default
Standard destructor.
RootObjectRefs & operator=(const RootObjectRefs &r)
Assignment operator.
Definition: extractEvt.C:84
ExtractStatus extract()
Extract all previously selected events from the input file and write it to the output.
Definition: extractEvt.C:245
T strncmp(T... args)
std::string container
Identifier of description.
Definition: extractEvt.C:104
unsigned long clid
Class ID of the described object.
Definition: extractEvt.C:106
ExtractStatus cancel()
Clear the list of event numbers to be extracted from the file.
Definition: extractEvt.C:185
RootRef & operator=(const RootRef &c)
Assignment operator.
Definition: extractEvt.C:43
int main(int argc, char *argv[])
Definition: main.cpp:4
std::vector< RootRef > refs
The references corresponding to the next layer of items in the data store.
Definition: extractEvt.C:75
RootRef()
Standard constructor.
Definition: extractEvt.C:38
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
std::unique_ptr< TFile > m_in
Definition: extractEvt.C:118
RootEventExtractor()=default
Default constructor.