11#define ROOTHISTCNV_RCWNTUPLECNV_CPP
36 static_assert( std::is_trivially_copyable_v<T>,
"T must be trivally copyable" );
37 std::memcpy( target, src.
buffer(),
sizeof( T ) * src.
length() );
38 return sizeof( T ) * src.
length();
43 static_assert( std::is_trivially_copyable_v<T>,
"T must be trivally copyable" );
44 std::memcpy(
const_cast<void*
>( target.
buffer() ), src,
sizeof( T ) * target.
length() );
45 return sizeof( T ) * target.
length();
48 template <
typename POD>
49 decltype( auto ) downcast_item(
const INTupleItem& i ) {
52 template <
typename POD>
56 template <
typename POD,
typename T>
57 void downcast_item( T&& ) =
delete;
59 template <
typename Item,
typename F>
60 decltype( auto ) visit( Item& i, F&& f ) {
63 return f( downcast_item<int>( i ) );
65 return f( downcast_item<char>( i ) );
67 return f( downcast_item<short>( i ) );
69 return f( downcast_item<long>( i ) );
71 return f( downcast_item<long long>( i ) );
73 return f( downcast_item<unsigned char>( i ) );
75 return f( downcast_item<unsigned short>( i ) );
77 return f( downcast_item<unsigned int>( i ) );
79 return f( downcast_item<unsigned long>( i ) );
81 return f( downcast_item<unsigned long long>( i ) );
83 return f( downcast_item<double>( i ) );
85 return f( downcast_item<float>( i ) );
87 return f( downcast_item<bool>( i ) );
89 throw std::runtime_error(
"RCWNTupleCnv::visit: unknown INTupleItem::type()" );
94 void analyzeItem(
const std::string& typ,
const NTuple::_Data<T>* it, std::string& desc, std::string& block_name,
95 std::string& var_name,
long& lowerRange,
long& upperRange,
long& size )
102 long item_size =
sizeof( T );
103 long dimension = it->
length();
104 long ndim = it->
ndim() - 1;
108 std::string ind_blk, ind_var;
110 if ( ind_blk != block_name ) {
111 std::cerr <<
"ERROR: Index for CWNT variable " << ind_var <<
" is in a different block: " << ind_blk
115 }
else if ( it->
dim( ndim ) > 1 ) {
116 desc += std::to_string( it->
dim( ndim ) );
119 for (
int i = ndim - 1; i >= 0; i-- ) {
121 desc += std::to_string( it->
dim( i ) );
128 if constexpr ( std::is_integral_v<T> ) {
138 size += item_size * dimension;
147 rtree =
new TTree( desc.c_str(), nt->
title().c_str() );
148 log <<
MSG::VERBOSE <<
"created tree id: " << rtree->GetName() <<
" title: " << nt->
title() <<
" desc: " << desc
153 std::string block_name, var_name;
154 long lowerRange, upperRange;
156 long cursize, oldsize = 0;
157 std::vector<std::string> item_fullname;
159 std::vector<long> item_buf_pos, item_buf_len, item_buf_end;
160 std::vector<long> item_range_lower, item_range_upper;
161 std::vector<std::pair<std::string, std::string>> item_name;
163 for (
const auto& i : nt->
items() ) {
166 visit( *i, [&](
const auto& data ) {
167 analyzeItem( this->
rootVarType( data.type() ), &data, item, block_name, var_name, lowerRange, upperRange, size );
170 item_name.emplace_back( block_name, item );
171 cursize = size - oldsize;
173 log <<
MSG::VERBOSE <<
"item: " << item <<
" type " << i->type() <<
" blk: " << block_name <<
" var: " << var_name
174 <<
" rng: " << lowerRange <<
" " << upperRange <<
" sz: " << size <<
" " << cursize
175 <<
" buf_pos: " << size - cursize <<
endmsg;
177 item_fullname.push_back( var_name );
178 item_buf_pos.push_back( size - cursize );
179 item_buf_len.push_back( cursize );
180 item_buf_end.push_back( size );
181 item_range_lower.push_back( lowerRange );
182 item_range_upper.push_back( upperRange );
188 char* buff = nt->
setBuffer(
new char[size] );
190 log <<
MSG::VERBOSE <<
"Created buffer size: " << size <<
" at " << (
void*)buff <<
endmsg;
193 std::fill_n( buff, size, 0 );
195 char* buf_pos = buff;
197 auto end = item_name.cend();
200 unsigned int i_item = 0;
205 for (
auto itr = item_name.cbegin(); itr != end; ++itr, ++i_item ) {
207 buf_pos = buff + item_buf_pos[i_item];
216 auto br =
new TBranch( rtree, item_fullname[i_item].c_str(), buf_pos, itr->second.c_str(), basket_size );
217 if ( itr->first !=
"AUTO_BLK" ) {
218 std::string title = itr->first;
219 title = itr->first +
"::" + br->GetTitle();
220 br->SetTitle( title.c_str() );
223 log <<
MSG::DEBUG <<
"adding TBranch " << br->GetTitle() <<
" at " << (
void*)buf_pos <<
endmsg;
226 if ( item_range_lower[i_item] < item_range_upper[i_item] ) {
230 TLeafI* index =
nullptr;
231 TObject* tobj = br->GetListOfLeaves()->FindObject( item_fullname[i_item].c_str() );
232 if ( tobj->IsA()->InheritsFrom(
"TLeafI" ) ) {
233 index =
dynamic_cast<TLeafI*
>( tobj );
236 index->SetMaximum( item_range_upper[i_item] );
240 log <<
MSG::ERROR <<
"Could dynamic cast to TLeafI: " << item_fullname[i_item] <<
endmsg;
245 rtree->GetListOfBranches()->Add( br );
261 const auto& items = nt->
items();
262 std::accumulate( begin( items ), end( items ), nt->
buffer(), [](
char* dest,
const INTupleItem* i ) {
263 return dest + visit( *i, [dest]( const auto& item ) { return saveItem( dest, item ); } );
275 if ( ievt >= rtree->GetEntries() ) {
277 log <<
MSG::ERROR <<
"no more entries in tree to read. max: " << rtree->GetEntries() <<
" current: " << ievt
282 rtree->GetEvent( ievt );
286 auto& items = ntup->
items();
287 std::accumulate( begin( items ), end( items ),
const_cast<const char*
>( ntup->
buffer() ),
289 return src + visit( *i, [src]( auto& item ) { return loadItem( src, item ); } );
305 std::string title = tree->GetTitle();
308 status =
m_ntupleSvc->create( CLID_ColumnWiseTuple, title, pObj );
310 if ( !ntup ) { log <<
MSG::ERROR <<
"cannot dynamic cast to INTuple" <<
endmsg; }
314 std::string itemName, indexName, item_type, itemTitle, blockName;
316 long size, totsize = 0;
317 std::vector<std::pair<TLeaf*, int>> itemList;
323 TObjArray* lbr = tree->GetListOfBranches();
325 while ( TObject* tobjb = bitr() ) {
327 TBranch* br =
dynamic_cast<TBranch*
>( tobjb );
328 itemTitle = br->GetTitle();
330 int ipos = itemTitle.find(
"::" );
332 blockName = itemTitle.substr( 0, ipos );
337 TObjArray* lf = br->GetListOfLeaves();
340 while ( TObject* tobj = litr() ) {
342 bool hasRange =
false;
347 TLeaf* tl =
dynamic_cast<TLeaf*
>( tobj );
352 itemName = tl->GetName();
354 if ( blockName !=
"" ) {
355 log <<
MSG::DEBUG <<
"loading NTuple item " << blockName <<
"/" << itemName;
357 log <<
MSG::DEBUG <<
"loading NTuple item " << itemName;
361 TLeaf* indexLeaf = tl->GetLeafCounter( arraySize );
363 if ( arraySize == 0 ) { log <<
MSG::ERROR <<
"TLeaf counter size = 0. This should not happen!" <<
endmsg; }
368 indexName = indexLeaf->GetName();
369 indexRange = indexLeaf->GetMaximum();
370 itemSize = indexRange * tl->GetLenType() * arraySize;
372 log <<
"[" << indexName;
375 if ( arraySize != 1 ) { log <<
"][" << arraySize; }
379 itemSize = tl->GetLenType() * arraySize;
383 if ( arraySize == 1 ) {
387 log <<
"[" << arraySize <<
"]";
396 hasRange = tl->IsRange();
398 itemList.emplace_back( tl, itemSize );
401 if ( tobj->IsA()->InheritsFrom(
"TLeafI" ) ) {
403 TLeafI* tli =
dynamic_cast<TLeafI*
>( tobj );
405 if ( tli->IsUnsigned() ) {
406 unsigned long min = 0, max = 0;
408 min = tli->GetMinimum();
409 max = tli->GetMaximum();
412 item =
createNTupleItem( itemName, blockName, indexName, indexRange, arraySize, min, max, ntup, hasRange );
414 long min = 0, max = 0;
416 min = tli->GetMinimum();
417 max = tli->GetMaximum();
420 item =
createNTupleItem( itemName, blockName, indexName, indexRange, arraySize, min, max, ntup, hasRange );
427 }
else if ( tobj->IsA()->InheritsFrom(
"TLeafF" ) ) {
428 float min = 0., max = 0.;
430 TLeafF* tlf =
dynamic_cast<TLeafF*
>( tobj );
433 min = float( tlf->GetMinimum() );
434 max = float( tlf->GetMaximum() );
440 item =
createNTupleItem( itemName, blockName, indexName, indexRange, arraySize, min, max, ntup, hasRange );
443 }
else if ( tobj->IsA()->InheritsFrom(
"TLeafD" ) ) {
444 double min = 0., max = 0.;
446 TLeafD* tld =
dynamic_cast<TLeafD*
>( tobj );
449 min = tld->GetMinimum();
450 max = tld->GetMaximum();
456 item =
createNTupleItem( itemName, blockName, indexName, indexRange, arraySize, min, max, ntup, hasRange );
465 log <<
MSG::ERROR <<
"Unable to create ntuple item \"" << itemName <<
"\"" <<
endmsg;
471 log <<
MSG::DEBUG <<
"Total buffer size of NTuple: " << totsize <<
" Bytes." <<
endmsg;
473 char* buf = ntup->
setBuffer(
new char[totsize] );
477 for (
const auto& iitr : itemList ) {
478 TLeaf* leaf = iitr.first;
479 int isize = iitr.second;
481 log <<
MSG::VERBOSE <<
"setting TBranch " << leaf->GetBranch()->GetName() <<
" buffer at " << (
void*)bufpos
484 leaf->GetBranch()->SetAddress( (
void*)bufpos );
502 if ( totsize != ts ) { log <<
MSG::ERROR <<
"buffer size mismatch: " << ts <<
" " << totsize <<
endmsg; }
const char *PyHelper getProperty(IInterface *p, char *name)
#define DECLARE_CONVERTER(x)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
SmartIF< IMessageSvc > & msgSvc() const
Retrieve pointer to message service.
Implementation of property with value of concrete type.
NTuple interface class definition.
virtual const char * buffer() const =0
Access data buffer (CONST)
virtual char * setBuffer(char *buff)=0
Attach data buffer.
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.
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 long type() const =0
Type information of the item.
virtual long length() const =0
Access the buffer length.
virtual const std::string & name() const =0
Access _Item name.
virtual bool hasIndex() const =0
Is the tuple have an index item?
The IProperty is the basic interface for all components which have properties that can be set or get.
Definition of the MsgStream class used to transmit messages.
Abstract class describing basic data in an Ntuple.
virtual const ItemRange & range() const =0
Access the range if specified.
static TYP min()
Minimal number of data.
TYP lower() const
Lower boundary of range.
TYP upper() const
Upper boundary of range.
static TYP max()
Maximal number of data.
Abstract base class which allows the user to interact with the actual N tuple implementation.
Converter of Column-wise NTuple into ROOT format.
StatusCode load(TTree *tree, INTuple *&refpObject) override
Create the transient representation of an object.
StatusCode book(const std::string &desc, INTuple *pObject, TTree *&tree) override
Book the N tuple.
StatusCode readData(TTree *rtree, INTuple *pObject, long ievt) override
Read N tuple data.
StatusCode writeData(TTree *rtree, INTuple *pObject) override
Write N tuple data.
std::string getDirectory()
virtual std::string rootVarType(int)
Return ROOT type info:
SmartIF< INTupleSvc > m_ntupleSvc
Reference to N tuple service.
This class is used for returning status codes from appropriate routines.
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
constexpr static const auto SUCCESS
constexpr static const auto FAILURE
bool parseName(const std::string &full, std::string &blk, std::string &var)
INTupleItem * createNTupleItem(const std::string &itemName, const std::string &blockName, const std::string &indexName, int indexRange, int arraySize, TYP min, TYP max, INTuple *ntup, bool hasRange)
Add an item of a given type to the N tuple.