The Gaudi Framework  master (76629ece)
Loading...
Searching...
No Matches
CollectionCloneAlg.cpp
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// CollectionCloneAlg.cpp
13// --------------------------------------------------------------------
14//
15// Author : Markus Frank
16//
17// ====================================================================
26#include <GaudiKernel/NTuple.h>
29#include <GaudiKernel/SmartIF.h>
30#include <vector>
31
32namespace {
33
34 template <class T>
35 static long upper( const INTupleItem* item ) {
36#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wnull-dereference"
38 const NTuple::_Data<T>* it = dynamic_cast<const NTuple::_Data<T>*>( item );
39 assert( it != nullptr );
40 return it->range().upper();
41#pragma GCC diagnostic pop
42 }
43
44 template <class TYP>
45 static StatusCode createItem( MsgStream& log, INTuple* tuple, INTupleItem* src, const TYP& null ) {
46 NTuple::_Data<TYP>* source = dynamic_cast<NTuple::_Data<TYP>*>( src );
47 if ( !source ) return StatusCode::FAILURE;
48 TYP low = source->range().lower();
49 TYP high = source->range().upper();
50 long hasIdx = source->hasIndex();
51 long ndim = source->ndim();
52 const std::string& name = source->name();
53 std::string idxName;
54 long dim[4], idxLen = 0;
55 long dim1 = 1, dim2 = 1;
56 INTupleItem* it = nullptr;
57 for ( int i = 0; i < ndim; i++ ) dim[i] = source->dim( i );
59 if ( hasIdx ) {
60 const INTupleItem* index = source->indexItem();
61 idxName = index->name();
62 switch ( index->type() ) {
64 idxLen = upper<unsigned char>( index );
65 break;
67 idxLen = upper<unsigned short>( index );
68 break;
70 idxLen = upper<unsigned int>( index );
71 break;
73 idxLen = upper<unsigned long>( index );
74 break;
76 idxLen = upper<char>( index );
77 break;
79 idxLen = upper<short>( index );
80 break;
82 idxLen = upper<int>( index );
83 break;
85 idxLen = upper<long>( index );
86 break;
87 default:
88 log << MSG::ERROR << "Column " << idxName << " is not a valid index column!" << endmsg;
90 }
91 }
92 switch ( ndim ) {
93 case 0:
94 it = NTuple::_Item<TYP>::create( tuple, name, typeid( TYP ), low, high, null );
95 break;
96 case 1:
97 dim1 = ( hasIdx ) ? idxLen : dim[0];
98 it = NTuple::_Array<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, low, high, null );
99 break;
100 case 2:
101 dim1 = ( hasIdx ) ? idxLen : dim[0];
102 dim2 = ( hasIdx ) ? dim[0] : dim[1];
103 it = NTuple::_Matrix<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, dim2, low, high, null );
104 break;
105 default:
106 return StatusCode::FAILURE;
107 }
108 return tuple->add( it );
109 }
110} // namespace
111
123
124 Gaudi::Property<std::string> m_tupleSvc{ this, "EvtTupleSvc", "EvtTupleSvc", "name of the data provider service" };
125 Gaudi::Property<std::vector<std::string>> m_inputs{ this, "Input", {}, "input specifications" };
126 Gaudi::Property<std::string> m_output{ this, "Output", {}, "output specification" };
127
131 std::string m_rootName;
133 std::string m_outName;
135 std::string m_criteria;
137 std::string m_selectorName;
138
139public:
142
145 MsgStream log( msgSvc(), name() );
146 m_rootName = "";
147 m_outName = "";
148 m_criteria = "";
149 m_selectorName = "";
150 m_dataSvc = service( m_tupleSvc, true );
151 if ( !m_dataSvc ) {
152 log << MSG::ERROR << "Failed to access service \"" << m_tupleSvc << "\"." << endmsg;
153 return StatusCode::FAILURE;
154 }
155 std::string fun;
157 for ( auto attrib : Parser( m_output ) ) {
158 switch ( ::toupper( attrib.tag[0] ) ) {
159 case 'D':
160 m_outName = std::move( attrib.value );
161 break;
162 case 'S':
163 m_criteria = std::move( attrib.value );
164 break;
165 case 'F':
166 fun = std::move( attrib.value );
167 break;
168 default:
169 break;
170 }
171 }
172 if ( m_outName.empty() ) {
173 log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
174 return StatusCode::FAILURE;
175 }
176 if ( !fun.empty() || !m_criteria.empty() ) {
177 if ( !m_criteria.empty() && fun.empty() ) fun = "NTuple::Selector";
178 m_selectorName = fun;
179 }
180 return StatusCode::SUCCESS;
181 }
182
184 StatusCode finalize() override {
185 m_dataSvc.reset();
186 return StatusCode::SUCCESS;
187 }
188
190 StatusCode execute() override {
191 StatusCode status = connect();
192 return status.isSuccess() ? mergeInputTuples() : status;
193 }
194
196 virtual StatusCode book( const NTuple::Tuple* nt ) {
197 MsgStream log( msgSvc(), name() );
199 NTuple::Tuple* tuple = m_dataSvc->book( m_outName, nt->clID(), nt->title() );
200 for ( const auto& i : nt->items() ) {
201 switch ( i->type() ) {
203 status = createItem<unsigned char>( log, tuple, i, 0 );
204 break;
206 status = createItem<unsigned short>( log, tuple, i, 0 );
207 break;
209 status = createItem<unsigned int>( log, tuple, i, 0 );
210 break;
212 status = createItem<unsigned long>( log, tuple, i, 0 );
213 break;
215 status = createItem<char>( log, tuple, i, 0 );
216 break;
218 status = createItem<short>( log, tuple, i, 0 );
219 break;
221 status = createItem<int>( log, tuple, i, 0 );
222 break;
224 status = createItem<long>( log, tuple, i, 0 );
225 break;
227 status = createItem( log, tuple, i, false );
228 break;
230 status = createItem<float>( log, tuple, i, 0 );
231 break;
233 status = createItem<double>( log, tuple, i, 0 );
234 break;
236 status = createItem<IOpaqueAddress*>( log, tuple, i, nullptr );
237 break;
239 status = createItem<void*>( log, tuple, i, nullptr );
240 break;
242 // status = createItem(log, tuple, i, (std::string*)0);
243 // break;
245 // status = createItem(log, tuple, i, (char*)0);
246 // break;
248 default:
249 status = StatusCode::FAILURE;
250 break;
251 }
252 }
253 return status;
254 }
255
256 // Perform some basic checks
257 virtual StatusCode checkInput( const NTuple::Tuple* clone, const NTuple::Tuple* src ) {
258 MsgStream log( msgSvc(), name() );
259 if ( clone && src ) {
260 const INTuple::ItemContainer& clone_items = clone->items();
261 const std::string clone_id = clone->registry()->identifier();
262 const std::string src_id = src->registry()->identifier();
263
264 log << MSG::ERROR;
265 for ( auto i = clone_items.begin(); i != clone_items.end(); ++i ) {
266 const INTupleItem* itm = *i;
267 const std::string& nam = itm->name();
268 const INTupleItem* src_itm = src->find( nam );
269 if ( !src_itm ) {
270 log << "Tuple item " << nam << " not present in " << src_id << endmsg;
271 return StatusCode::FAILURE;
272 }
273 if ( itm->type() != src_itm->type() ) {
274 log << "Tuple item " << nam << " are of different types in " << src_id << ":" << src_itm->typeName()
275 << " <-> " << clone_id << ":" << itm->typeName() << endmsg;
276 return StatusCode::FAILURE;
277 }
278 if ( itm->ndim() != src_itm->ndim() ) {
279 log << "Tuple item " << nam << " have different dimensions in " << src_id << ":" << src_itm->ndim() << " <-> "
280 << clone_id << ":" << itm->ndim() << endmsg;
281 return StatusCode::FAILURE;
282 }
283 for ( int j = 0; j < itm->ndim(); ++j ) {
284 if ( src_itm->dim( j ) != itm->dim( j ) ) {
285 log << "Tuple item " << nam << " have different dimensions in " << src_id << "[" << j
286 << "]:" << src_itm->dim( j ) << " <-> " << clone_id << "[" << j << "]:" << itm->dim( j ) << endmsg;
287 return StatusCode::FAILURE;
288 }
289 }
290 if ( itm->hasIndex() != src_itm->hasIndex() ) {
291 log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->hasIndex()
292 << " <-> " << clone_id << ":" << itm->hasIndex() << endmsg;
293 return StatusCode::FAILURE;
294 }
295 if ( itm->hasIndex() ) {
296 if ( itm->index() != src_itm->index() ) {
297 log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->index()
298 << " <-> " << clone_id << ":" << itm->index() << endmsg;
299 return StatusCode::FAILURE;
300 }
301 }
302 }
303 return StatusCode::SUCCESS;
304 }
305 return StatusCode::FAILURE;
306 }
307
309 StatusCode mergeEntries( const std::string& input ) {
310 MsgStream log( msgSvc(), name() );
311 NTuplePtr out( m_dataSvc.get(), m_outName );
312 if ( 0 != out ) {
313 const INTuple::ItemContainer& clone_items = out->items();
314 std::vector<GenericAddress> addrVector( clone_items.size() );
316 NTuplePtr nt( m_dataSvc.get(), input );
317 size_t k = 0, nentry = 0;
318 if ( 0 != nt ) {
319 const INTuple::ItemContainer& source_items = nt->items();
320 for ( k = 0; k < source_items.size(); ++k ) {
321 if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
322 *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
323 }
324 }
325 while ( status.isSuccess() ) {
326 status = m_dataSvc->readRecord( nt.ptr() );
327 if ( status.isSuccess() ) {
328 INTuple::ItemContainer::const_iterator i;
329 nentry++;
330 for ( k = 0, i = source_items.begin(); i != source_items.end(); ++i, ++k ) {
331 const INTupleItem* src_itm = *i;
332 const INTupleItem* out_itm = out->find( src_itm->name() );
333 size_t size = 0;
334 switch ( ( *i )->type() ) {
336 size = sizeof( unsigned char );
337 break;
339 size = sizeof( unsigned short );
340 break;
342 size = sizeof( unsigned int );
343 break;
345 size = sizeof( unsigned long );
346 break;
348 size = sizeof( char );
349 break;
351 size = sizeof( short );
352 break;
354 size = sizeof( int );
355 break;
357 size = sizeof( long );
358 break;
360 size = sizeof( bool );
361 break;
363 size = sizeof( float );
364 break;
366 size = sizeof( double );
367 break;
369 *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
370 size = 0;
371 break;
373 size = ::strlen( (const char*)src_itm->buffer() ) + 1;
374 break;
376 *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
377 size = 0;
378 } break;
380 IOpaqueAddress* ppA1 = &addrVector[k];
381 IOpaqueAddress** ppA2 = (IOpaqueAddress**)( out_itm->buffer() );
382 *ppA2 = ppA1;
383 size = 0;
384 } break;
386 default:
387 size = 0;
388 break;
389 }
390 if ( size > 0 ) {
391 ::memcpy( const_cast<void*>( out_itm->buffer() ), src_itm->buffer(), size * src_itm->length() );
392 }
393 }
394 status = m_dataSvc->writeRecord( out.ptr() );
395 if ( !status.isSuccess() ) {
396 log << MSG::ERROR << "Failed to write record " << nentry << " from " << input << " to " << m_outName
397 << endmsg;
398 }
399 }
400 }
401 log << MSG::INFO << "End of reading tuple " << input << " after " << nentry << " entries." << endmsg;
402
403 if ( nentry > 0 || m_selectorName != "" ) { return StatusCode::SUCCESS; }
404 return StatusCode::FAILURE;
405 }
406 log << MSG::ERROR << "Failed to access input: " << input << endmsg;
407 }
408 return StatusCode::FAILURE;
409 }
410
414 for ( size_t i = 0; i < m_inputs.size(); ++i ) {
415 NTuplePtr nt( m_dataSvc.get(), m_inputs[i] );
416 if ( !( 0 == nt ) ) {
417 NTuplePtr out( m_dataSvc.get(), m_outName );
418 if ( 0 == out ) {
419 status = book( nt );
420 } else {
421 status = checkInput( out, nt );
422 }
423 if ( !status.isSuccess() ) {
424 return status;
425 } else if ( m_selectorName != "" ) {
426 SmartIF<ISelectStatement> stmt( ObjFactory::create( m_selectorName, serviceLocator() ).release() );
427 if ( stmt ) {
428 if ( !m_criteria.empty() ) stmt->setCriteria( m_criteria );
429 nt->attachSelector( stmt ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
430 } else {
431 MsgStream log( msgSvc(), name() );
432 log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
433 return StatusCode::FAILURE;
434 }
435 }
436 } else {
437 MsgStream log( msgSvc(), name() );
438 log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
439 return StatusCode::FAILURE;
440 }
441 }
442 return StatusCode::SUCCESS;
443 }
444
447 MsgStream log( msgSvc(), name() );
448 for ( const auto& input : m_inputs ) {
449 StatusCode sc = mergeEntries( input );
450 if ( !sc.isSuccess() ) {
451 log << MSG::ERROR << "Failed to merge tuple:" << input << endmsg;
452 return sc;
453 }
454 }
455 return StatusCode::SUCCESS;
456 }
457};
void toupper(std::string &s)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
SmartDataPtr< NTuple::Tuple > NTuplePtr
Definition NTuple.h:1020
#define DECLARE_COMPONENT(type)
Small algorithm, which allows to merge N-tuples in a generic way.
StatusCode connect()
Connect input and output N-tuples.
StatusCode execute() override
Execute procedure.
StatusCode mergeEntries(const std::string &input)
Merge the entries of a single input tuple into the output.
virtual StatusCode book(const NTuple::Tuple *nt)
Book the N-tuple according to the specification.
std::string m_criteria
Selection criteria (if any)
std::string m_selectorName
Selector factory.
std::string m_rootName
Name of the root leaf (obtained at initialize)
Gaudi::Property< std::vector< std::string > > m_inputs
StatusCode initialize() override
Initialize.
Gaudi::Property< std::string > m_output
virtual StatusCode checkInput(const NTuple::Tuple *clone, const NTuple::Tuple *src)
StatusCode mergeInputTuples()
Merge all N-tuple entries.
StatusCode finalize() override
Finalize.
SmartIF< INTupleSvc > m_dataSvc
Reference to data provider service.
Gaudi::Property< std::string > m_tupleSvc
std::string m_outName
Output tuple name.
const SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
IRegistry * registry() const
Get pointer to Registry.
Definition DataObject.h:79
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Algorithm(std::string name, ISvcLocator *svcloc, std::string version=PACKAGE_VERSION)
Constructor.
Definition Algorithm.h:98
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
const std::string & name() const override
The identifying name of the algorithm object.
const std::string & type() const override
The type of the algorithm object.
Definition Algorithm.h:162
SmartIF< IService > service(std::string_view name, const bool createIf=true, const bool quiet=false) const
Return a pointer to the service identified by name (or "type/name")
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
Parse attribute strings allowing iteration over the various attributes.
NTuple interface class definition.
Definition INTuple.h:86
std::vector< INTupleItem * > ItemContainer
Definition INTuple.h:93
virtual const INTupleItem * find(const std::string &name) const =0
Find an item row of the Ntuple (CONST)
virtual ItemContainer & items()=0
Access item container.
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
virtual const std::string & title() const =0
Object title.
NTuple interface class definition.
Definition INTuple.h:32
virtual long ndim() const =0
Dimension.
virtual const void * buffer() const =0
Access data buffer (CONST)
virtual long dim(long i) const =0
Access individual dimensions.
virtual const std::string & index() const =0
Access the index _Item.
virtual std::string typeName() const =0
Proper type name of the object.
virtual long type() const =0
Type information of the item.
virtual long length() const =0
Access the buffer length.
virtual INTupleItem * indexItem()=0
Pointer to index column (if present, 0 else)
virtual const std::string & name() const =0
Access _Item name.
virtual bool hasIndex() const =0
Is the tuple have an index item?
Opaque address interface definition.
virtual const id_type & identifier() const =0
Full identifier (or key)
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
static _Array * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long len, TYP min, TYP max, TYP def)
Create instance.
Abstract class describing basic data in an Ntuple.
Definition NTuple.h:122
virtual const ItemRange & range() const =0
Access the range if specified.
static _Item * create(INTuple *tup, const std::string &name, const std::type_info &info, TYP min, TYP max, TYP def)
Create instance.
static _Matrix * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long ncol, long nrow, TYP min, TYP max, TYP def)
Create instance.
TYP lower() const
Lower boundary of range.
Definition NTuple.h:78
TYP upper() const
Upper boundary of range.
Definition NTuple.h:80
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition NTuple.h:380
TYPE * ptr()
Automatic conversion to data type.
Small smart pointer class with automatic reference counting for IInterface.
Definition SmartIF.h:28
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
size_t index(const Gaudi::ParticleProperty *property, const Gaudi::Interfaces::IParticlePropertySvc *service)
helper utility for mapping of Gaudi::ParticleProperty object into non-negative integral sequential id...
@ ERROR
Definition IMessageSvc.h:22
@ INFO
Definition IMessageSvc.h:22