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