00001
00002 #define ROOTHISTCNV_RCWNTUPLECNV_CPP
00003
00004 #define ALLOW_ALL_TYPES
00005
00006
00007
00008 #include "GaudiKernel/xtoa.h"
00009 #include "GaudiKernel/CnvFactory.h"
00010 #include "GaudiKernel/INTupleSvc.h"
00011 #include "GaudiKernel/MsgStream.h"
00012 #include "GaudiKernel/NTuple.h"
00013
00014
00015 #include <cstdio>
00016 #include <utility>
00017 #include <list>
00018 #include <vector>
00019
00020 #include "RCWNTupleCnv.h"
00021
00022 #include "TTree.h"
00023 #include "TLeafI.h"
00024 #include "TLeafF.h"
00025 #include "TLeafD.h"
00026
00027 #ifdef __ICC
00028
00029
00030 #pragma warning(disable:1572)
00031 #endif
00032
00033
00034 template <class T> void analyzeItem(std::string typ,
00035 const NTuple::_Data<T>* it,
00036 std::string& desc,
00037 std::string& block_name,
00038 std::string& var_name,
00039 long& lowerRange,
00040 long& upperRange,
00041 long& size)
00042
00043 {
00044
00045 std::string full_name = it->name();
00046 RootHistCnv::parseName(full_name,block_name,var_name);
00047
00048
00049 long item_size = sizeof(T);
00050 long dimension = it->length();
00051 long ndim = it->ndim()-1;
00052 std::ostringstream text;
00053 text << var_name;
00054 if ( it->hasIndex() || it->length() > 1 ) {
00055 text << '[';
00056 }
00057 if ( it->hasIndex() )
00058 {
00059 std::string ind_blk, ind_var;
00060 std::string ind = it->index();
00061 RootHistCnv::parseName(ind,ind_blk,ind_var);
00062 if (ind_blk != block_name) {
00063 std::cerr << "ERROR: Index for CWNT variable " << ind_var
00064 << " is in a different block: " << ind_blk << std::endl;
00065 }
00066 text << ind_var;
00067 }
00068 else if ( it->dim(ndim) > 1 ) {
00069 text << it->dim(ndim);
00070 }
00071
00072 for ( int i = ndim-1; i>=0; i-- ){
00073 text << "][" << it->dim(i);
00074 }
00075 if ( it->hasIndex() || it->length() > 1 ) {
00076 text << ']';
00077 }
00078
00079 if (it->range().lower() != it->range().min() &&
00080 it->range().upper() != it->range().max() ) {
00081 lowerRange = (long) it->range().lower();
00082 upperRange = (long) it->range().upper();
00083 } else {
00084 lowerRange = 0;
00085 upperRange = -1;
00086 }
00087 text << typ;
00088
00089 desc += text.str();
00090 size += item_size * dimension;
00091 }
00092
00093
00094 StatusCode RootHistCnv::RCWNTupleCnv::book(const std::string& desc,
00095 INTuple* nt,
00096 TTree*& rtree)
00097
00098 {
00099 MsgStream log(msgSvc(), "RCWNTupleCnv");
00100 rtree = new TTree(desc.c_str(), nt->title().c_str());
00101 log << MSG::VERBOSE << "created tree id: " << rtree->GetName()
00102 << " title: "<< nt->title() << " desc: " << desc << endmsg;
00103
00104
00105
00106 std::string block_name,var_name;
00107 long lowerRange, upperRange;
00108 long size = 0;
00109 long cursize, oldsize = 0;
00110 std::vector<std::string> item_fullname;
00111
00112 std::vector<long> item_buf_pos, item_buf_len, item_buf_end;
00113 std::vector<long> item_range_lower, item_range_upper;
00114 std::vector<std::pair<std::string,std::string> > item_name;
00115
00116 const INTuple::ItemContainer& cols = nt->items();
00117 for (INTuple::ItemContainer::const_iterator i = cols.begin();
00118 i != cols.end(); ++i ) {
00119 std::string item = "";
00120
00121 switch( (*i)->type() ) {
00122 case DataTypeInfo::INT:
00123 analyzeItem(rootVarType( (*i)->type() ),
00124 dynamic_cast<const NTuple::_Data<int>*>(*i),item,
00125 block_name,var_name,lowerRange,upperRange,size);
00126 break;
00127 case DataTypeInfo::CHAR:
00128 analyzeItem(rootVarType( (*i)->type() ),
00129 dynamic_cast<const NTuple::_Data<char>*>(*i),
00130 item, block_name,var_name,lowerRange,upperRange,size);
00131 break;
00132 case DataTypeInfo::SHORT:
00133 analyzeItem(rootVarType( (*i)->type() ),
00134 dynamic_cast<const NTuple::_Data<short>*>(*i),item,
00135 block_name,var_name,lowerRange,upperRange,size);
00136 break;
00137 case DataTypeInfo::LONG:
00138 analyzeItem(rootVarType( (*i)->type() ),
00139 dynamic_cast<const NTuple::_Data<long>*>(*i),item,
00140 block_name,var_name,lowerRange,upperRange,size);
00141 break;
00142 case DataTypeInfo::LONGLONG:
00143 analyzeItem(rootVarType( (*i)->type() ),
00144 dynamic_cast<const NTuple::_Data<long long>*>(*i),item,
00145 block_name,var_name,lowerRange,upperRange,size);
00146 break;
00147 case DataTypeInfo::UCHAR:
00148 analyzeItem(rootVarType( (*i)->type() ),
00149 dynamic_cast<const NTuple::_Data<unsigned char>*>(*i),
00150 item, block_name,var_name,lowerRange,upperRange,size);
00151 break;
00152 case DataTypeInfo::USHORT:
00153 analyzeItem(rootVarType( (*i)->type() ),
00154 dynamic_cast<const NTuple::_Data<unsigned short>*>(*i),
00155 item, block_name,var_name,lowerRange,upperRange,size);
00156 break;
00157 case DataTypeInfo::UINT:
00158 analyzeItem(rootVarType( (*i)->type() ),
00159 dynamic_cast<const NTuple::_Data<unsigned int>*>(*i),
00160 item, block_name,var_name,lowerRange,upperRange,size);
00161 break;
00162 case DataTypeInfo::ULONG:
00163 analyzeItem(rootVarType( (*i)->type() ),
00164 dynamic_cast<const NTuple::_Data<unsigned long>*>(*i),
00165 item, block_name,var_name,lowerRange,upperRange,size);
00166 break;
00167 case DataTypeInfo::ULONGLONG:
00168 analyzeItem(rootVarType( (*i)->type() ),
00169 dynamic_cast<const NTuple::_Data<unsigned long long>*>(*i),
00170 item, block_name,var_name,lowerRange,upperRange,size);
00171 break;
00172 case DataTypeInfo::DOUBLE:
00173 analyzeItem(rootVarType( (*i)->type() ),
00174 dynamic_cast<const NTuple::_Data<double>*>(*i),item,
00175 block_name,var_name,lowerRange,upperRange,size);
00176 break;
00177 case DataTypeInfo::FLOAT:
00178 analyzeItem(rootVarType( (*i)->type() ),
00179 dynamic_cast<const NTuple::_Data<float>*>(*i),item,
00180 block_name,var_name,lowerRange,upperRange,size);
00181 break;
00182 case DataTypeInfo::BOOL:
00183 analyzeItem(rootVarType( (*i)->type() ),
00184 dynamic_cast<const NTuple::_Data<bool>*>(*i),item,
00185 block_name,var_name,lowerRange,upperRange,size);
00186 break;
00187 default:
00188 break;
00189 }
00190
00191 item_name.push_back(std::pair<std::string,std::string>(block_name,item));
00192 cursize = size - oldsize;
00193
00194 log << MSG::VERBOSE << "item: " << item << " type " << (*i)->type()
00195 << " blk: " << block_name
00196 << " var: " << var_name << " rng: " << lowerRange << " "
00197 << upperRange << " sz: " << size << " " << cursize
00198 << " buf_pos: " << size-cursize << endmsg;
00199
00200 item_fullname.push_back(var_name);
00201 item_buf_pos.push_back(size-cursize);
00202 item_buf_len.push_back(cursize);
00203 item_buf_end.push_back(size);
00204 item_range_lower.push_back(lowerRange);
00205 item_range_upper.push_back(upperRange);
00206
00207 oldsize = size;
00208 }
00209
00210 char* buff = new char[size];
00211 log << MSG::VERBOSE << "Created buffer size: " << size << " at "
00212 << (void*)buff << endmsg;
00213
00214
00215 memset (buff,0,size);
00216
00217
00218 nt->setBuffer(buff);
00219
00220 char *buf_pos = buff;
00221
00222 std::vector<std::pair<std::string,std::string> >::const_iterator itr,end;
00223 end = item_name.end();
00224
00225
00226 unsigned int i_item = 0;
00227 for (itr=item_name.begin(); itr!=end; ++itr, ++i_item) {
00228
00229 buf_pos = buff + item_buf_pos[i_item];
00230
00231
00232
00233
00234
00235
00236
00237
00238 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
00239 TBranch *br = new TBranch(rtree,
00240 #else
00241 TBranch *br = new TBranch(
00242 #endif
00243 item_fullname[i_item].c_str(),
00244 buf_pos,
00245 itr->second.c_str()
00246 );
00247
00248 if (itr->first != "AUTO_BLK") {
00249 std::string tit = itr->first;
00250 tit = itr->first + "::" + br->GetTitle();
00251 br->SetTitle(tit.c_str());
00252 }
00253
00254 log << MSG::DEBUG << "adding TBranch " << br->GetTitle() << " at "
00255 << (void*) buf_pos << endmsg;
00256
00257
00258
00259 if ( item_range_lower[i_item] < item_range_upper[i_item] ) {
00260
00261
00262
00263 TLeafI *index = 0;
00264 TObject *tobj = br->GetListOfLeaves()->FindObject( item_fullname[i_item].c_str() );
00265 if (tobj->IsA()->InheritsFrom("TLeafI")) {
00266 index = dynamic_cast<TLeafI*>(tobj);
00267
00268 if (index != 0) {
00269 index->SetMaximum( item_range_upper[i_item] );
00270
00271
00272 } else {
00273 log << MSG::ERROR << "Could dynamic cast to TLeafI: "
00274 << item_fullname[i_item] << endmsg;
00275 }
00276 }
00277 }
00278
00279 rtree->GetListOfBranches()->Add(br);
00280
00281 }
00282
00283
00284 log << MSG::INFO << "Booked TTree with ID: " << desc
00285 << " \"" << nt->title() << "\" in directory "
00286 << getDirectory() << endmsg;
00287
00288 return StatusCode::SUCCESS;
00289
00290 }
00291
00292
00293
00294
00295 StatusCode RootHistCnv::RCWNTupleCnv::writeData(TTree* rtree, INTuple* nt)
00296
00297 {
00298
00299 const INTuple::ItemContainer& cols = nt->items();
00300 char * tar = nt->buffer();
00301 for (INTuple::ItemContainer::const_iterator i = cols.begin(); i != cols.end(); i++ ) {
00302 switch( (*i)->type() ) {
00303 case DataTypeInfo::BOOL:
00304 tar += saveItem(tar, (bool*)(*i)->buffer(), (*i)->length());
00305 break;
00306 case DataTypeInfo::CHAR:
00307 tar += saveItem(tar, (char*)(*i)->buffer(), (*i)->length());
00308 break;
00309 case DataTypeInfo::SHORT:
00310 tar += saveItem(tar, (short*)(*i)->buffer(), (*i)->length());
00311 break;
00312 case DataTypeInfo::INT:
00313 tar += saveItem(tar, (int*)(*i)->buffer(), (*i)->length());
00314 break;
00315 case DataTypeInfo::LONG:
00316 tar += saveItem(tar, (long*)(*i)->buffer(), (*i)->length());
00317 break;
00318 case DataTypeInfo::LONGLONG:
00319 tar += saveItem(tar, (long long*)(*i)->buffer(), (*i)->length());
00320 break;
00321 case DataTypeInfo::UCHAR:
00322 tar += saveItem(tar, (unsigned char*)(*i)->buffer(), (*i)->length());
00323 break;
00324 case DataTypeInfo::USHORT:
00325 tar += saveItem(tar, (unsigned short*)(*i)->buffer(), (*i)->length());
00326 break;
00327 case DataTypeInfo::UINT:
00328 tar += saveItem(tar, (unsigned int*)(*i)->buffer(), (*i)->length());
00329 break;
00330 case DataTypeInfo::ULONG:
00331 tar += saveItem(tar, (unsigned long*)(*i)->buffer(), (*i)->length());
00332 break;
00333 case DataTypeInfo::ULONGLONG:
00334 tar += saveItem(tar, (unsigned long long*)(*i)->buffer(), (*i)->length());
00335 break;
00336 case DataTypeInfo::FLOAT:
00337 tar += saveItem(tar, (float*)(*i)->buffer(), (*i)->length());
00338 break;
00339 case DataTypeInfo::DOUBLE:
00340 tar += saveItem(tar, (double*)(*i)->buffer(), (*i)->length());
00341 break;
00342 default:
00343 break;
00344 }
00345 }
00346
00347 rtree->Fill();
00348 nt->reset();
00349 return StatusCode::SUCCESS;
00350 }
00351
00352
00353
00354 StatusCode RootHistCnv::RCWNTupleCnv::readData(TTree* rtree,
00355 INTuple* ntup,
00356 long ievt)
00357
00358 {
00359 MsgStream log(msgSvc(), "RCWNTupleCnv::readData");
00360
00361 if (ievt >= rtree->GetEntries()) {
00362 log << MSG::ERROR << "no more entries in tree to read. max: "
00363 << rtree->GetEntries() << " current: " << ievt
00364 << endmsg;
00365 return StatusCode::FAILURE;
00366 }
00367
00368 rtree->GetEvent(ievt);
00369
00370 ievt++;
00371
00372 INTuple::ItemContainer& cols = ntup->items();
00373 char * src = ntup->buffer();
00374
00375
00376
00377 for (INTuple::ItemContainer::iterator i = cols.begin(); i != cols.end(); i++ ) {
00378
00379
00380 switch( (*i)->type() ) {
00381 case DataTypeInfo::BOOL:
00382 src += loadItem(src, (bool*)(*i)->buffer(), (*i)->length());
00383 break;
00384 case DataTypeInfo::CHAR:
00385 src += loadItem(src, (char*)(*i)->buffer(), (*i)->length());
00386 break;
00387 case DataTypeInfo::SHORT:
00388 src += loadItem(src, (short*)(*i)->buffer(), (*i)->length());
00389 break;
00390 case DataTypeInfo::INT:
00391 src += loadItem(src, (int*)(*i)->buffer(), (*i)->length());
00392 break;
00393 case DataTypeInfo::LONG:
00394 src += loadItem(src, (long*)(*i)->buffer(), (*i)->length());
00395 break;
00396 case DataTypeInfo::LONGLONG:
00397 src += loadItem(src, (long long*)(*i)->buffer(), (*i)->length());
00398 break;
00399 case DataTypeInfo::UCHAR:
00400 src += loadItem(src, (unsigned char*)(*i)->buffer(), (*i)->length());
00401 break;
00402 case DataTypeInfo::USHORT:
00403 src += loadItem(src, (unsigned short*)(*i)->buffer(), (*i)->length());
00404 break;
00405 case DataTypeInfo::UINT:
00406 src += loadItem(src, (unsigned int*)(*i)->buffer(), (*i)->length());
00407 break;
00408 case DataTypeInfo::ULONG:
00409 src += loadItem(src, (unsigned long*)(*i)->buffer(), (*i)->length());
00410 break;
00411 case DataTypeInfo::ULONGLONG:
00412 src += loadItem(src, (unsigned long long*)(*i)->buffer(), (*i)->length());
00413 break;
00414 case DataTypeInfo::FLOAT:
00415 src += loadItem(src, (float*)(*i)->buffer(), (*i)->length());
00416 break;
00417 case DataTypeInfo::DOUBLE:
00418 src += loadItem(src, (double*)(*i)->buffer(), (*i)->length());
00419 break;
00420 default:
00421 break;
00422 }
00423
00424 }
00425
00426 return StatusCode::SUCCESS;
00427 }
00428
00429
00430
00431 StatusCode RootHistCnv::RCWNTupleCnv::load(TTree* tree, INTuple*& refpObject )
00432
00433 {
00434 MsgStream log(msgSvc(), "RCWNTupleCnv::load");
00435
00436 StatusCode status;
00437
00438 NTuple::Tuple *pObj = 0;
00439
00440 std::string title = tree->GetTitle();
00441 log << MSG::VERBOSE << "loading CWNT " << title << " at: "
00442 << tree << endmsg;
00443
00444 status = m_ntupleSvc->create(CLID_ColumnWiseTuple, title, pObj);
00445 INTuple* ntup = dynamic_cast<INTuple*>(pObj);
00446
00447 INTupleItem* item=0;
00448
00449 std::string itemName, indexName, item_type, itemTitle, blockName;
00450
00451 long size, totsize=0;
00452 std::list< std::pair<TLeaf*,int> > itemList;
00453
00454
00455
00456
00457
00458 TObjArray* lbr = tree->GetListOfBranches();
00459 TIter bitr ( lbr );
00460 while ( TObject *tobjb = bitr() ) {
00461
00462 TBranch* br = (TBranch*)tobjb;
00463 itemTitle = br->GetTitle();
00464
00465 int ipos = itemTitle.find("::");
00466 if (ipos >= 0) {
00467 blockName = itemTitle.substr(0,ipos);
00468 } else {
00469 blockName = "";
00470 }
00471
00472 TObjArray* lf = br->GetListOfLeaves();
00473
00474 TIter litr ( lf );
00475 while ( TObject *tobj = litr() ) {
00476
00477 bool hasRange=false;
00478 int indexRange = 0;
00479 int itemSize;
00480 item = 0;
00481
00482
00483 TLeaf* tl = dynamic_cast<TLeaf*> (tobj);
00484 itemName = tl->GetName();
00485
00486
00487
00488
00489
00490
00491 if (blockName != "") {
00492 log << MSG::DEBUG << "loading NTuple item " << blockName << "/"
00493 << itemName;
00494 } else {
00495 log << MSG::DEBUG << "loading NTuple item " << itemName;
00496 }
00497
00498 int arraySize;
00499 TLeaf* indexLeaf = tl->GetLeafCounter(arraySize);
00500
00501 if (arraySize == 0) {
00502 log << MSG::ERROR << "TLeaf counter size = 0. This should not happen!"
00503 << endmsg;
00504 }
00505
00506 if (indexLeaf != 0) {
00507
00508
00509 indexName = indexLeaf->GetName();
00510
00511 indexRange = indexLeaf->GetMaximum();
00512 itemSize = indexRange * tl->GetLenType() * arraySize;
00513
00514 log << "[" << indexName;
00515
00516
00517 if (arraySize != 1) {
00518 log << "][" << arraySize;
00519 }
00520 log << "]";
00521
00522 } else {
00523 itemSize = tl->GetLenType() * arraySize;
00524
00525 indexName = "";
00526
00527 if (arraySize == 1) {
00528
00529 } else {
00530
00531 log << "[" << arraySize << "]";
00532 }
00533 }
00534
00535 log << endmsg;
00536
00537
00538
00539
00540 size = itemSize;
00541 totsize += size;
00542
00543 hasRange = tl->IsRange();
00544
00545 itemList.push_back(std::pair<TLeaf*,int>(tl,itemSize));
00546
00547
00548
00549 if (tobj->IsA()->InheritsFrom("TLeafI")) {
00550
00551 TLeafI *tli = dynamic_cast<TLeafI*>(tobj);
00552 if (tli->IsUnsigned()) {
00553 unsigned long min=0, max=0;
00554 if (hasRange) {
00555 min = tli->GetMinimum();
00556 max = tli->GetMaximum();
00557 }
00558
00559 item = createNTupleItem(itemName, blockName, indexName, indexRange,
00560 arraySize,
00561 min, max, ntup);
00562 } else {
00563 long min=0, max=0;
00564 if (hasRange) {
00565 min = tli->GetMinimum();
00566 max = tli->GetMaximum();
00567 }
00568
00569 item = createNTupleItem(itemName, blockName, indexName, indexRange,
00570 arraySize,
00571 min, max, ntup);
00572 }
00573
00574
00575 } else if (tobj->IsA()->InheritsFrom("TLeafF")) {
00576 float min=0., max=0.;
00577
00578 TLeafF *tlf = dynamic_cast<TLeafF*>(tobj);
00579 if (hasRange) {
00580 min = float(tlf->GetMinimum());
00581 max = float(tlf->GetMaximum());
00582 }
00583
00584 item = createNTupleItem(itemName, blockName, indexName, indexRange,
00585 arraySize,
00586 min, max, ntup);
00587
00588
00589 } else if (tobj->IsA()->InheritsFrom("TLeafD")) {
00590 double min=0., max=0.;
00591
00592 TLeafD *tld = dynamic_cast<TLeafD*>(tobj);
00593 if (hasRange) {
00594 min = tld->GetMinimum();
00595 max = tld->GetMaximum();
00596 }
00597
00598 item = createNTupleItem(itemName, blockName, indexName, indexRange,
00599 arraySize,
00600 min, max, ntup);
00601
00602
00603 } else {
00604 log << MSG::ERROR << "Uknown data type" << endmsg;
00605 }
00606
00607
00608 if (item) {
00609 ntup->add(item);
00610 } else {
00611 log << MSG::ERROR
00612 << "Unable to create ntuple item \""
00613 << itemName << "\"" << endmsg;
00614 }
00615
00616 }
00617 }
00618
00619 log << MSG::DEBUG << "Total buffer size of NTuple: " << totsize
00620 << " Bytes." << endmsg;
00621
00622 char* buf = new char[totsize];
00623 char* bufpos = buf;
00624
00625 ntup->setBuffer(buf);
00626
00627 std::list< std::pair<TLeaf*,int> >::const_iterator iitr = itemList.begin();
00628 int ts = 0;
00629 for (; iitr!= itemList.end(); ++iitr) {
00630 TLeaf* leaf = (*iitr).first;
00631 int isize = (*iitr).second;
00632
00633 log << MSG::VERBOSE << "setting TBranch " << leaf->GetBranch()->GetName()
00634 << " buffer at " << (void*) bufpos << endmsg;
00635
00636 leaf->GetBranch()->SetAddress((void*)bufpos);
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 ts += isize;
00650
00651 bufpos += isize;
00652 }
00653
00654 if (totsize != ts ) {
00655 log << MSG::ERROR << "buffer size mismatch: " << ts << " " << totsize
00656 << endmsg;
00657 }
00658
00659 refpObject = ntup;
00660
00661 return StatusCode::SUCCESS;
00662 }
00663
00664
00665
00666 DECLARE_NAMESPACE_CONVERTER_FACTORY(RootHistCnv, RCWNTupleCnv)