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