![]() |
|
|
Generated: 24 Nov 2008 |
00001 // $Id: RCWNTupleCnv.cpp,v 1.17 2007/05/29 13:06:17 mato Exp $ 00002 #define ROOTHISTCNV_RCWNTUPLECNV_CPP 00003 00004 #define ALLOW_ALL_TYPES 00005 00006 00007 // Include files 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 // Compiler include files 00015 #include <cstdio> 00016 #include <utility> /* std::pair */ 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 // Instantiation of a static factory class used by clients to create 00028 // instances of this service 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 // Loop over the items 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 // std::vector<long> item_size,item_size2; 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: // 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: // 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: // 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: // unsigned char 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: // unsigned short 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: // unsigned int 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: // unsigned long 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: // 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: // 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 // log << MSG::WARNING << "item: " << item << " blk: " << block_name 00171 // << " var: " << var_name << " rng: " << lowerRange << " " 00172 // << upperRange << " sz: " << size << " " << cursize 00173 // << " buf_pos: " << size-cursize << endreq; 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 // Zero out the buffer to make ROOT happy 00190 memset (buff,0,size); 00191 00192 // Tell the ntuple where it is 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 // Loop over items, creating a new branch for each one; 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 // log << MSG::WARNING << "adding TBranch " << i_item << " " 00207 // << item_fullname[i_item] 00208 // << " format: " << itr->second.c_str() << " at " 00209 // << (void*) buf_pos << " (" << (void*) buff << "+" 00210 // << (void*)item_buf_pos[i_item] << ")" 00211 // << endreq; 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 // for index items with a limited range. Must be a TLeafI! 00234 if ( item_range_lower[i_item] < item_range_upper[i_item] ) { 00235 // log << MSG::VERBOSE << "\"" << item_fullname[i_item] 00236 // << "\" is range limited " << item_range_lower[i_item] << " " 00237 // << item_range_upper[i_item] << endreq; 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 // FIXME -- add for next version of ROOT 00246 // index->SetMinimum( item_range_lower[i_item] ); 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 // Fill the tree; 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: // bool 00279 tar += saveItem(tar, (bool*)(*i)->buffer(), (*i)->length()); 00280 break; 00281 case DataTypeInfo::CHAR: // char 00282 tar += saveItem(tar, (char*)(*i)->buffer(), (*i)->length()); 00283 break; 00284 case DataTypeInfo::SHORT: // short 00285 tar += saveItem(tar, (short*)(*i)->buffer(), (*i)->length()); 00286 break; 00287 case DataTypeInfo::INT: // int 00288 tar += saveItem(tar, (int*)(*i)->buffer(), (*i)->length()); 00289 break; 00290 case DataTypeInfo::LONG: // long 00291 tar += saveItem(tar, (long*)(*i)->buffer(), (*i)->length()); 00292 break; 00293 case DataTypeInfo::UCHAR: // unsigned char 00294 tar += saveItem(tar, (unsigned char*)(*i)->buffer(), (*i)->length()); 00295 break; 00296 case DataTypeInfo::USHORT: // unsigned short 00297 tar += saveItem(tar, (unsigned short*)(*i)->buffer(), (*i)->length()); 00298 break; 00299 case DataTypeInfo::UINT: // unsigned int 00300 tar += saveItem(tar, (unsigned int*)(*i)->buffer(), (*i)->length()); 00301 break; 00302 case DataTypeInfo::ULONG: // unsigned long 00303 tar += saveItem(tar, (unsigned long*)(*i)->buffer(), (*i)->length()); 00304 break; 00305 case DataTypeInfo::FLOAT: // float 00306 tar += saveItem(tar, (float*)(*i)->buffer(), (*i)->length()); 00307 break; 00308 case DataTypeInfo::DOUBLE: // 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 // copy data from ntup->buffer() to ntup->items()->buffer() 00345 00346 for (INTuple::ItemContainer::iterator i = cols.begin(); i != cols.end(); i++ ) { 00347 00348 // log << MSG::WARNING << " " << (*i)->name() << ": " << (void*) src 00349 // << " " << (*i)->length() << " "; 00350 00351 // int *idat; 00352 // float *fdat; 00353 // long *ldat; 00354 00355 00356 switch( (*i)->type() ) { 00357 case DataTypeInfo::BOOL: // bool 00358 src += loadItem(src, (bool*)(*i)->buffer(), (*i)->length()); 00359 break; 00360 case DataTypeInfo::CHAR: // char 00361 src += loadItem(src, (char*)(*i)->buffer(), (*i)->length()); 00362 break; 00363 case DataTypeInfo::SHORT: // short 00364 src += loadItem(src, (short*)(*i)->buffer(), (*i)->length()); 00365 break; 00366 case DataTypeInfo::INT: // short 00367 // idat = (int*) src; 00368 // log << *idat << endreq; 00369 src += loadItem(src, (int*)(*i)->buffer(), (*i)->length()); 00370 break; 00371 case DataTypeInfo::LONG: // short 00372 // ldat = (long*) src; 00373 // log << *ldat << endreq; 00374 src += loadItem(src, (long*)(*i)->buffer(), (*i)->length()); 00375 break; 00376 case DataTypeInfo::UCHAR: // unsigned char 00377 src += loadItem(src, (unsigned char*)(*i)->buffer(), (*i)->length()); 00378 break; 00379 case DataTypeInfo::USHORT: // unsigned short 00380 src += loadItem(src, (unsigned short*)(*i)->buffer(), (*i)->length()); 00381 break; 00382 case DataTypeInfo::UINT: // unsigned short 00383 src += loadItem(src, (unsigned int*)(*i)->buffer(), (*i)->length()); 00384 break; 00385 case DataTypeInfo::ULONG: // unsigned short 00386 src += loadItem(src, (unsigned long*)(*i)->buffer(), (*i)->length()); 00387 break; 00388 case DataTypeInfo::FLOAT: // unsigned short 00389 // fdat = (float*) src; 00390 // log << (*fdat) << endreq; 00391 src += loadItem(src, (float*)(*i)->buffer(), (*i)->length()); 00392 break; 00393 case DataTypeInfo::DOUBLE: // unsigned short 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 // loop over all branches (==leaves) 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 // TLeaf* tl = (TLeaf*)tobj; 00458 TLeaf* tl = dynamic_cast<TLeaf*> (tobj); 00459 itemName = tl->GetName(); 00460 00461 // char* buf_pos = (char*)tl->GetValuePointer(); 00462 // cout << " " << itemName << " " << blockName << " " 00463 // << (void*)buf_pos; 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 //index Arrays and Matrices 00483 00484 hasIndex = true; 00485 indexName = indexLeaf->GetName(); 00486 // indexRange = tl->GetNdata(); 00487 indexRange = indexLeaf->GetMaximum(); 00488 itemSize = indexRange * tl->GetLenType() * arraySize; 00489 00490 log << "[" << indexName; 00491 00492 // Just for Matrices 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 // Simple items 00505 } else { 00506 // Arrays of constant size 00507 log << "[" << arraySize << "]"; 00508 } 00509 } 00510 00511 log << endreq; 00512 00513 // cout << " index: " << indexName << endl; 00514 00515 // size = tl->GetNdata() * tl->GetLenType(); 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 // Integer 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 // Float 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 // Double 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 } // end litr 00593 } // end bitr 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 // //testing 00615 // if (leaf->IsA()->InheritsFrom("TLeafI")) { 00616 // for (int ievt=0; ievt<5; ievt++) { 00617 // leaf->GetBranch()->GetEvent(ievt); 00618 // int *idat = (int*)bufpos; 00619 // log << MSG::WARNING << leaf->GetName() << ": " << ievt << " " 00620 // << *idat << endreq; 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