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