The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
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 */
35namespace Gaudi {
36
44 struct RootRef {
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 ) {}
52
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 }
62
63 void reset() {
64 dbase = -1;
65 container = -1;
66 link = -1;
67 entry = -1;
68 svc = 1;
69 clid = 1;
70 }
71 };
72
83 std::vector<int> links;
85 std::vector<RootRef> refs;
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
110 std::string description;
112 std::string optional;
114 std::string container;
116 unsigned long clid = 1;
120 virtual ~RootNTupleDescriptor() = default;
121 };
122
123 typedef int ExtractStatus;
125
127 protected:
128 std::unique_ptr<TFile> m_in;
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
137 std::vector<int> m_eventList;
138
139 public:
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
175using namespace Gaudi;
176using namespace std;
177
179RootEventExtractor::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
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
220ExtractStatus 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
376int 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
384int extract_event( const char* input, const char* output, long num_evt ) {
385 return extractEvt( input, output, num_evt );
386}
387
388#if 0
389int 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
int main()
ExtractStatusEnum
Definition extractEvt.C:124
@ EXTRACT_ERROR
Definition extractEvt.C:124
@ EXTRACT_SUCCESS
Definition extractEvt.C:124
int ExtractStatus
Definition extractEvt.C:123
int extract_event(const char *input, const char *output, long num_evt)
Definition extractEvt.C:384
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1
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
STL namespace.
ExtractStatus closeOutput()
Close output file.
Definition extractEvt.C:240
virtual ~RootEventExtractor()
Default destructor.
Definition extractEvt.C:189
ExtractStatus closeInput()
Close input file.
Definition extractEvt.C:228
std::vector< int > m_eventList
Definition extractEvt.C:137
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
ExtractStatus cancel()
Clear the list of event numbers to be extracted from the file.
Definition extractEvt.C:195
std::unique_ptr< TFile > m_in
Definition extractEvt.C:128
ExtractStatus openOutput(const char *name, const char *option)
Open output file.
Definition extractEvt.C:220
ExtractStatus openInput(const char *name)
Open input file.
Definition extractEvt.C:208
RootEventExtractor()=default
Default constructor.
ExtractStatus extract()
Extract all previously selected events from the input file and write it to the output.
Definition extractEvt.C:255
RootNTupleDescriptor()=default
Standard constructor.
unsigned long clid
Class ID of the described object.
Definition RootRefs.h:94
std::string optional
Optional description.
Definition RootRefs.h:90
std::string description
Description string.
Definition RootRefs.h:88
virtual ~RootNTupleDescriptor()=default
Standard destructor.
std::string container
Identifier of description.
Definition RootRefs.h:92
Persistent reference object containing all leafs and links corresponding to a Gaudi DataObject.
Definition extractEvt.C:81
RootObjectRefs & operator=(const RootObjectRefs &r)
Assignment operator.
Definition extractEvt.C:94
~RootObjectRefs()=default
Default destructor.
RootObjectRefs()=default
Default constructor.
RootObjectRefs(const RootObjectRefs &r)
Copy constructor.
Definition extractEvt.C:90
std::vector< int > links
The links of the link manager.
Definition RootRefs.h:69
std::vector< RootRef > refs
The references corresponding to the next layer of items in the data store.
Definition RootRefs.h:71
Persistent reference object.
Definition extractEvt.C:44
int dbase
Data members to define object location in the persistent world.
Definition RootRefs.h:41
void reset()
Reset data content.
Definition RootRefs.h:49
RootRef(const RootRef &c)
Copy constructor.
Definition extractEvt.C:50
RootRef()
Standard constructor.
Definition RootRefs.h:43
RootRef & operator=(const RootRef &c)
Assignment operator.
Definition extractEvt.C:53