| The Gaudi Framework v32r1 (f65d50dc)

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 {
36 int dbase, container, link, clid, svc, entry;
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 {
73 std::vector<int> links;
75 std::vector<RootRef> refs;
76
78 RootObjectRefs() = default;
80 RootObjectRefs( const RootObjectRefs& r ) : links( r.links ), refs( r.refs ) {}
82 ~RootObjectRefs() = default;
84 RootObjectRefs& operator=( const RootObjectRefs& r ) {
85 links = r.links;
86 refs = r.refs;
87 return *this;
88 }
89 };
90
98 struct RootNTupleDescriptor {
100 std::string description;
102 std::string optional;
104 std::string container;
106 unsigned long clid;
108 RootNTupleDescriptor() = default;
110 virtual ~RootNTupleDescriptor() = default;
111 };
112
113 typedef int ExtractStatus;
114 enum ExtractStatusEnum { EXTRACT_ERROR = 0, EXTRACT_SUCCESS = 1 };
115
116 struct RootEventExtractor {
117 protected:
118 std::unique_ptr<TFile> m_in;
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;
127 std::vector<int> m_eventList;
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
143 ExtractStatus closeInput();
144
146 ExtractStatus openOutput( const char* name, const char* option );
147
149 ExtractStatus closeOutput();
150
152 ExtractStatus cancel();
153
155 ExtractStatus select( int evt_num );
156
158 ExtractStatus extract();
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
179 RootEventExtractor::~RootEventExtractor() {
180 closeInput();
181 closeOutput();
182 }
183
185 ExtractStatus RootEventExtractor::cancel() {
186 m_eventList.clear();
187 ::printf( "+++ Event list cleared.\n" );
188 return EXTRACT_SUCCESS;
189 }
190
192 ExtractStatus RootEventExtractor::select( int evt_num ) {
193 m_eventList.push_back( evt_num );
194 return EXTRACT_SUCCESS;
195 }
196
198 ExtractStatus RootEventExtractor::openInput( const char* name ) {
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
218 ExtractStatus RootEventExtractor::closeInput() {
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
230 ExtractStatus RootEventExtractor::closeOutput() {
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
245 ExtractStatus RootEventExtractor::extract() {
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
Gaudi::RootRef::RootRef
RootRef(const RootRef &c)
Copy constructor.
Definition: extractEvt.C:40
gaudirun.c
c
Definition: gaudirun.py:487
gaudiComponentHelp.name
name
Definition: gaudiComponentHelp.py:41
gaudirun.output
output
Definition: gaudirun.py:484
Gaudi::RootEventExtractor
Definition: extractEvt.C:116
std
STL namespace.
Gaudi::RootRef::container
int container
Definition: extractEvt.C:36
Gaudi::RootEventExtractor::openOutput
ExtractStatus openOutput(const char *name, const char *option)
Open output file.
Definition: extractEvt.C:210
Gaudi::RootRef::entry
int entry
Definition: extractEvt.C:36
Gaudi::EXTRACT_SUCCESS
Definition: extractEvt.C:114
Gaudi::RootObjectRefs::links
std::vector< int > links
The links of the link manager.
Definition: extractEvt.C:73
Gaudi::RootObjectRefs
Persistent reference object containing all leafs and links corresponding to a Gaudi DataObject.
Definition: extractEvt.C:71
Gaudi::RootObjectRefs::RootObjectRefs
RootObjectRefs(const RootObjectRefs &r)
Copy constructor.
Definition: extractEvt.C:80
std::string
STL class.
Gaudi::RootEventExtractor::closeInput
ExtractStatus closeInput()
Close input file.
Definition: extractEvt.C:218
Gaudi::RootEventExtractor::m_ref_out
TTree * m_ref_out
Definition: extractEvt.C:124
Gaudi::RootEventExtractor::closeOutput
ExtractStatus closeOutput()
Close output file.
Definition: extractEvt.C:230
Gaudi::RootRef::dbase
int dbase
Data members to define object location in the persistent world.
Definition: extractEvt.C:36
Gaudi::RootRef
Persistent reference object.
Definition: extractEvt.C:34
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:192
Gaudi::RootEventExtractor::m_out
TFile * m_out
Definition: extractEvt.C:122
Gaudi::RootNTupleDescriptor
Description:
Definition: extractEvt.C:98
Gaudi::RootNTupleDescriptor::optional
std::string optional
Optional description.
Definition: extractEvt.C:102
Gaudi::RootNTupleDescriptor::RootNTupleDescriptor
RootNTupleDescriptor()=default
Standard constructor.
Gaudi::RootEventExtractor::m_localDB_id
int m_localDB_id
Definition: extractEvt.C:126
std::next
T next(T... args)
std::strcmp
T strcmp(T... args)
std::runtime_error
STL class.
Gaudi::EXTRACT_ERROR
Definition: extractEvt.C:114
Gaudi::RootObjectRefs::~RootObjectRefs
~RootObjectRefs()=default
Default destructor.
Gaudi::RootNTupleDescriptor::description
std::string description
Description string.
Definition: extractEvt.C:100
Gaudi::ExtractStatus
int ExtractStatus
Definition: extractEvt.C:113
Gaudi::RootEventExtractor::m_eventList
std::vector< int > m_eventList
Definition: extractEvt.C:127
Gaudi::RootEventExtractor::m_evt_out
TTree * m_evt_out
Definition: extractEvt.C:123
Gaudi::RootRef::clid
int clid
Definition: extractEvt.C:36
Gaudi::RootEventExtractor::openInput
ExtractStatus openInput(const char *name)
Open input file.
Definition: extractEvt.C:198
Gaudi::RootRef::reset
void reset()
Reset data content.
Definition: extractEvt.C:53
Gaudi::RootEventExtractor::~RootEventExtractor
virtual ~RootEventExtractor()
Default destructor.
Definition: extractEvt.C:179
extract_event
int extract_event(const char *input, const char *output, long num_evt)
Definition: extractEvt.C:374
Gaudi::RootObjectRefs::RootObjectRefs
RootObjectRefs()=default
Default constructor.
std::vector< int >
std::unique_ptr< TFile >
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:366
Gaudi::RootEventExtractor::m_evt_in
TTree * m_evt_in
Definition: extractEvt.C:119
Gaudi::ExtractStatusEnum
ExtractStatusEnum
Definition: extractEvt.C:114
Gaudi::RootRef::link
int link
Definition: extractEvt.C:36
Gaudi::RootNTupleDescriptor::~RootNTupleDescriptor
virtual ~RootNTupleDescriptor()=default
Standard destructor.
Gaudi::RootObjectRefs::operator=
RootObjectRefs & operator=(const RootObjectRefs &r)
Assignment operator.
Definition: extractEvt.C:84
Gaudi::RootEventExtractor::extract
ExtractStatus extract()
Extract all previously selected events from the input file and write it to the output.
Definition: extractEvt.C:245
std::strncmp
T strncmp(T... args)
Gaudi::RootNTupleDescriptor::container
std::string container
Identifier of description.
Definition: extractEvt.C:104
Gaudi::RootRef::svc
int svc
Definition: extractEvt.C:36
Gaudi::RootNTupleDescriptor::clid
unsigned long clid
Class ID of the described object.
Definition: extractEvt.C:106
Gaudi::RootEventExtractor::cancel
ExtractStatus cancel()
Clear the list of event numbers to be extracted from the file.
Definition: extractEvt.C:185
Gaudi::RootRef::operator=
RootRef & operator=(const RootRef &c)
Assignment operator.
Definition: extractEvt.C:43
main
int main(int argc, char *argv[])
Definition: main.cpp:4
Gaudi::RootEventExtractor::m_ref_in
TTree * m_ref_in
Definition: extractEvt.C:120
Gaudi::RootObjectRefs::refs
std::vector< RootRef > refs
The references corresponding to the next layer of items in the data store.
Definition: extractEvt.C:75
Gaudi::RootRef::RootRef
RootRef()
Standard constructor.
Definition: extractEvt.C:38
Gaudi
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
Gaudi::RootEventExtractor::m_in
std::unique_ptr< TFile > m_in
Definition: extractEvt.C:118
Gaudi::RootEventExtractor::RootEventExtractor
RootEventExtractor()=default
Default constructor.