Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_aida_ntuple 5 #define tools_aida_ntuple 6 7 // An in memory ntuple able to have "sub ntuple" on a column. 8 // It is used in ioda to read ntuples in XML/AIDA files. 9 10 #ifdef TOOLS_MEM 11 #include "mem" 12 #endif 13 14 #include "vmanip" 15 #include "vfind" 16 #include "typedefs" 17 #include "scast" 18 #include "forit" 19 #include "ntuple_binding" 20 #include "mnmx" 21 22 #include <string> 23 #include <vector> 24 #include <ostream> 25 26 namespace tools { 27 namespace aida { 28 29 class base_col { 30 public: 31 static const std::string& s_class() { 32 static const std::string s_v("tools::aida::base_col"); 33 return s_v; 34 } 35 virtual void* cast(const std::string& a_class) const { 36 if(void* p = cmp_cast<base_col>(this,a_class)) {return p;} 37 return 0; 38 } 39 public: 40 virtual base_col* copy() const = 0; 41 virtual uint64 num_elems() const = 0; 42 virtual bool add() = 0; 43 virtual bool reset() = 0; 44 //binded column reading API : 45 virtual bool fetch_entry() const = 0; 46 virtual void set_user_variable(void*) = 0; 47 protected: 48 base_col(std::ostream& a_out,const std::string& a_name) 49 :m_out(a_out) 50 ,m_name(a_name),m_index(0){ 51 #ifdef TOOLS_MEM 52 mem::increment(s_class().c_str()); 53 #endif 54 } 55 public: 56 virtual ~base_col(){ 57 #ifdef TOOLS_MEM 58 mem::decrement(s_class().c_str()); 59 #endif 60 } 61 protected: 62 base_col(const base_col& a_from) 63 :m_out(a_from.m_out) 64 ,m_name(a_from.m_name) 65 ,m_index(a_from.m_index){ 66 #ifdef TOOLS_MEM 67 mem::increment(s_class().c_str()); 68 #endif 69 } 70 base_col& operator=(const base_col& a_from){ 71 m_name = a_from.m_name; 72 m_index = a_from.m_index; 73 return *this; 74 } 75 public: 76 const std::string& name() const {return m_name;} 77 78 void set_index(uint64 a_index){m_index = a_index;} 79 protected: 80 std::ostream& m_out; 81 std::string m_name; 82 uint64 m_index; 83 }; 84 85 class base_ntu { 86 public: 87 static const std::string& s_class() { 88 static const std::string s_v("tools::aida::base_ntu"); 89 return s_v; 90 } 91 virtual void* cast(const std::string& a_class) const { 92 if(void* p = cmp_cast<base_ntu>(this,a_class)) {return p;} 93 return 0; 94 } 95 protected: 96 base_ntu(std::ostream& a_out,const std::string& a_title) 97 :m_out(a_out),m_title(a_title),m_index(-1){ 98 #ifdef TOOLS_MEM 99 mem::increment(s_class().c_str()); 100 #endif 101 } 102 virtual ~base_ntu() { 103 clear(); 104 #ifdef TOOLS_MEM 105 mem::decrement(s_class().c_str()); 106 #endif 107 } 108 protected: 109 base_ntu(const base_ntu& a_from) 110 :m_out(a_from.m_out) 111 ,m_title(a_from.m_title),m_index(a_from.m_index) 112 { 113 #ifdef TOOLS_MEM 114 mem::increment(s_class().c_str()); 115 #endif 116 tools_vforcit(base_col*,a_from.m_cols,it) { 117 base_col* column = (*it)->copy(); 118 if(!column) { 119 m_out << s_class() << "::cstor :" 120 << " can't copy column." 121 << std::endl; 122 safe_clear<base_col>(m_cols); 123 m_index = -1; 124 return; //throw 125 } 126 m_cols.push_back(column); 127 } 128 } 129 base_ntu& operator=(const base_ntu& a_from){ 130 if(&a_from==this) return *this; 131 132 safe_clear<base_col>(m_cols); 133 m_index = a_from.m_index; 134 135 m_title = a_from.m_title; 136 tools_vforcit(base_col*,a_from.m_cols,it) { 137 base_col* column = (*it)->copy(); 138 if(!column) { 139 m_out << s_class() << "::operator=() :" 140 << " can't copy column." 141 << std::endl; 142 safe_clear<base_col>(m_cols); 143 m_index = -1; 144 return *this; 145 } 146 m_cols.push_back(column); 147 } 148 149 return *this; 150 } 151 public: 152 std::ostream& out() const {return m_out;} 153 const std::vector<base_col*>& columns() const {return m_cols;} 154 size_t number_of_columns() const {return m_cols.size();} 155 156 #ifdef tools_aida_ntuple 157 const std::vector<base_col*>& cols() const {return m_cols;} //deprecated : use columns(). 158 #endif 159 160 void column_names(std::vector<std::string>& a_names) const { 161 a_names.clear(); 162 tools_vforcit(base_col*,m_cols,it) a_names.push_back((*it)->name()); 163 } 164 165 const std::string& title() const {return m_title;} 166 void set_title(const std::string& a_title) {m_title = a_title;} 167 168 uint64 rows() const { 169 if(m_cols.empty()) return 0; 170 return m_cols.front()->num_elems(); 171 } 172 bool number_of_entries(uint64& a_value) const { 173 if(m_cols.empty()) {a_value = 0;return false;} 174 a_value = m_cols.front()->num_elems(); 175 return true; 176 } 177 178 void clear() { //must not be confused with reset(). 179 safe_clear<base_col>(m_cols); 180 m_index = -1; 181 } 182 183 bool reset() { //clear data in columns (but not the column set) 184 bool status = true; 185 tools_vforit(base_col*,m_cols,it) { 186 if(!(*it)->reset()) status = false; 187 } 188 m_index = -1; 189 return status; 190 } 191 192 // reading : 193 void start() {m_index = -1;set_columns_index(0);} 194 bool next() { 195 // a tuple loop is of the form : 196 // tuple.start(); 197 // while(tuple.next()) { 198 // ... 199 // double v; 200 // if(!col->get_entry(v)) {} 201 // ... 202 // } 203 if((m_index+1)>=(int64)rows()) return false; 204 m_index++; 205 set_columns_index(m_index); 206 return true; 207 } 208 int64 row_index() const {return m_index;} 209 210 // filling : 211 bool add_row() { 212 bool status = true; 213 tools_vforit(base_col*,m_cols,it) { 214 if(!(*it)->add()) status = false; 215 } 216 return status; 217 } 218 public: 219 base_col* find_column(const std::string& a_name){ 220 return find_named<base_col>(m_cols,a_name); 221 } 222 223 void add_column(base_col* a_col) { //we take ownership. 224 m_cols.push_back(a_col); 225 } 226 227 protected: 228 void set_columns_index(uint64 a_index) { 229 tools_vforit(base_col*,m_cols,it) { 230 (*it)->set_index(a_index); 231 } 232 } 233 protected: 234 std::ostream& m_out; 235 std::string m_title; 236 int64 m_index; 237 std::vector<base_col*> m_cols; 238 }; 239 240 }} 241 242 #include "tos" 243 #include "sto" 244 #include "columns" 245 #include "stype" 246 247 namespace tools { 248 namespace aida { 249 250 //inline const std::string& s_aida_type(char) { 251 // static const std::string s_v("char"); 252 // return s_v; 253 //} 254 inline const std::string& s_aida_type(short) { 255 static const std::string s_v("short"); 256 return s_v; 257 } 258 inline const std::string& s_aida_type(int) { 259 static const std::string s_v("int"); 260 return s_v; 261 } 262 inline const std::string& s_aida_type(float) { 263 static const std::string s_v("float"); 264 return s_v; 265 } 266 inline const std::string& s_aida_type(double) { 267 static const std::string s_v("double"); 268 return s_v; 269 } 270 271 ///////////////////////////////////////// 272 ///////////////////////////////////////// 273 //inline const std::string& s_aida_type(unsigned char) { 274 // static const std::string s_v("byte"); 275 // return s_v; 276 //} 277 278 inline const std::string& s_aida_type(bool) { 279 static const std::string s_v("boolean"); 280 return s_v; 281 } 282 inline const std::string& s_aida_type(const std::string&) { 283 static const std::string s_v("string"); 284 return s_v; 285 } 286 inline const std::string& s_aida_type(int64) { 287 static const std::string s_v("long"); 288 return s_v; 289 } 290 /* 291 inline const std::string& s_aida_type(const std::vector<double>&) { 292 static const std::string s_v("double[]"); 293 return s_v; 294 } 295 */ 296 inline const std::string& s_aida_type_ituple() { 297 static const std::string s_v("ITuple"); 298 return s_v; 299 } 300 301 ///////////////////////////////////////// 302 /// not AIDA ! ////////////////////////// 303 ///////////////////////////////////////// 304 inline const std::string& s_aida_type(unsigned short) { 305 static const std::string s_v("ushort"); 306 return s_v; 307 } 308 inline const std::string& s_aida_type(unsigned int) { 309 static const std::string s_v("uint"); 310 return s_v; 311 } 312 inline const std::string& s_aida_type(uint64) { 313 static const std::string s_v("ulong"); 314 return s_v; 315 } 316 317 class aida_base_col : public base_col { 318 public: 319 static const std::string& s_class() { 320 static const std::string s_v("tools::aida::aida_base_col"); 321 return s_v; 322 } 323 virtual void* cast(const std::string& a_class) const { 324 if(void* p = cmp_cast<aida_base_col>(this,a_class)) {return p;} 325 return base_col::cast(a_class); 326 } 327 public: 328 virtual const std::string& aida_type() const = 0; 329 virtual bool s_default_value(std::string&) const = 0; 330 virtual bool s_value(std::string&) const = 0; 331 virtual bool s_fill(const std::string&) = 0; 332 public: 333 aida_base_col(std::ostream& a_out,const std::string& a_name) 334 :base_col(a_out,a_name){} 335 public: 336 virtual ~aida_base_col(){} 337 public: 338 aida_base_col(const aida_base_col& a_from) 339 :base_col(a_from) 340 {} 341 aida_base_col& operator=(const aida_base_col& a_from){ 342 base_col::operator=(a_from); 343 return *this; 344 } 345 }; 346 347 inline bool s__fill(const std::string& a_s,std::string& a_v) { 348 a_v = a_s; 349 return true; 350 } 351 inline bool s__fill(const std::string& a_s,char& a_v) { 352 //for exlib/cbk/aida_ntu 353 if(a_s.empty()) return false; 354 a_v = a_s[0]; 355 return true; 356 } 357 inline bool s__fill(const std::string& a_s,unsigned char& a_v) { 358 //for exlib/cbk/aida_ntu 359 if(a_s.empty()) return false; 360 a_v = a_s[0]; 361 return true; 362 } 363 inline bool s__fill(const std::string& a_s,bool& a_v) { 364 return to(a_s,a_v); 365 } 366 inline bool s__fill(const std::string& a_s,short& a_v) { 367 return to<short>(a_s,a_v); 368 } 369 inline bool s__fill(const std::string& a_s,unsigned short& a_v) { 370 return to<unsigned short>(a_s,a_v); 371 } 372 inline bool s__fill(const std::string& a_s,int& a_v) { 373 return to<int>(a_s,a_v); 374 } 375 inline bool s__fill(const std::string& a_s,unsigned int& a_v) { 376 return to<unsigned int>(a_s,a_v); 377 } 378 inline bool s__fill(const std::string& a_s,int64& a_v) { 379 return to<int64>(a_s,a_v); 380 } 381 inline bool s__fill(const std::string& a_s,uint64& a_v) { 382 return to<uint64>(a_s,a_v); 383 } 384 inline bool s__fill(const std::string& a_s,float& a_v) { 385 return to<float>(a_s,a_v); 386 } 387 inline bool s__fill(const std::string& a_s,double& a_v) { 388 return to<double>(a_s,a_v); 389 } 390 391 template <class T> 392 class aida_col : public aida_base_col { 393 public: 394 typedef T entry_t; 395 public: 396 static const std::string& s_class() { 397 static const std::string s_v("tools::aida::aida_col<"+stype(T())+">"); 398 return s_v; 399 } 400 virtual void* cast(const std::string& a_class) const { 401 if(void* p = cmp_cast< aida_col<T> >(this,a_class)) {return p;} 402 return aida_base_col::cast(a_class); 403 } 404 public: 405 virtual base_col* copy() const {return new aida_col(*this);} 406 virtual bool add() {m_data.push_back(m_tmp);m_tmp = m_default;return true;} 407 virtual bool reset() { 408 m_data.clear(); 409 m_index = 0; 410 m_tmp = m_default; 411 return true; 412 } 413 virtual uint64 num_elems() const {return m_data.size();} 414 public: 415 virtual const std::string& aida_type() const {return s_aida_type(T());} 416 virtual bool s_default_value(std::string& a_s) const { 417 a_s = tos(m_default); 418 return true; 419 } 420 virtual bool s_value(std::string& a_s) const { 421 typedef typename std::vector<T>::size_type sz_t; 422 a_s = tos(m_data[sz_t(m_index)]); 423 return true; 424 } 425 426 // for exlib/raxml/tuple : 427 virtual bool s_fill(const std::string& a_s) { 428 //if(!to<T>(a_s,m_tmp)) { 429 if(!s__fill(a_s,m_tmp)) { 430 m_out << s_class() << "::fill :" 431 << " can't convert " << sout(a_s) << "." 432 << std::endl; 433 return false; 434 } 435 return true; 436 } 437 438 virtual void set_user_variable(void* a_user_var) {m_user_var = (T*)a_user_var;} //not owner. 439 public: 440 aida_col(std::ostream& a_out,const std::string& a_name,const T& a_def) 441 :aida_base_col(a_out,a_name) 442 ,m_default(a_def) 443 ,m_tmp(a_def) 444 ,m_user_var(0) //not owner 445 {} 446 public: 447 virtual ~aida_col(){} 448 public: 449 aida_col(const aida_col& a_from) 450 :aida_base_col(a_from) 451 ,m_data(a_from.m_data) 452 ,m_default(a_from.m_default) 453 ,m_tmp(a_from.m_tmp) 454 ,m_user_var(a_from.m_user_var) 455 {} 456 aida_col& operator=(const aida_col& a_from){ 457 aida_base_col::operator=(a_from); 458 if(&a_from==this) return *this; 459 m_data = a_from.m_data; 460 m_default = a_from.m_default; 461 m_tmp = a_from.m_tmp; 462 m_user_var = a_from.m_user_var; 463 return *this; 464 } 465 public: 466 bool fill(const T& a_value) {m_tmp = a_value;return true;} 467 bool get_entry(T& a_v) const { 468 if(m_index>=m_data.size()) { 469 m_out << s_class() << "::get_entry :" 470 << " bad index " << m_index 471 << ". Vec size is " << m_data.size() << "." 472 << "." 473 << std::endl; 474 a_v = T(); 475 return false; 476 } 477 typedef typename std::vector<T>::size_type sz_t; 478 a_v = m_data[sz_t(m_index)]; 479 return true; 480 } 481 virtual bool fetch_entry() const { 482 //NOTE : it is ok to have a NULL m_user_var. 483 if(m_index>=m_data.size()) { 484 m_out << s_class() << "::get_entry :" 485 << " bad index " << m_index 486 << ". Vec size is " << m_data.size() << "." 487 << "." 488 << std::endl; 489 if(m_user_var) *m_user_var = T(); 490 return false; 491 } 492 typedef typename std::vector<T>::size_type sz_t; 493 if(m_user_var) *m_user_var = m_data[sz_t(m_index)]; 494 return true; 495 } 496 protected: 497 std::vector<T> m_data; 498 T m_default; 499 T m_tmp; 500 T* m_user_var; 501 }; 502 503 class ntuple : public base_ntu { 504 public: 505 static cid id_class() {return 2000;} //for ntuple_binding. 506 public: 507 static const std::string& s_class() { 508 static const std::string s_v("tools::aida::ntuple"); 509 return s_v; 510 } 511 virtual void* cast(const std::string& a_class) const { 512 if(void* p = cmp_cast<ntuple>(this,a_class)) {return p;} 513 return base_ntu::cast(a_class); 514 } 515 virtual const std::string& s_cls() const {return s_class();} 516 public: 517 ntuple(std::ostream& a_out,const std::string& a_title) 518 :base_ntu(a_out,a_title) 519 {} 520 virtual ~ntuple() {} 521 public: 522 ntuple(const ntuple& a_from): base_ntu(a_from){} 523 ntuple& operator=(const ntuple& a_from){ 524 base_ntu::operator=(a_from); 525 return *this; 526 } 527 public: 528 template <class T> 529 aida_col<T>* create_col(const std::string& a_name,const T& a_def = T()) { 530 if(find_named<base_col>(m_cols,a_name)) { 531 m_out << s_class() << "::create_col :" 532 << " a column with name " << sout(a_name) << " already exists." 533 << std::endl; 534 return 0; 535 } 536 aida_col<T>* col = new aida_col<T>(m_out,a_name,a_def); 537 if(!col) { 538 m_out << s_class() << "::create_col :" 539 << " can't create aida_col<T> " << sout(a_name) << "." 540 << std::endl; 541 return 0; 542 } 543 m_cols.push_back(col); 544 return col; 545 } 546 547 template <class T> 548 aida_col<T>* find_column(const std::string& a_name){ 549 base_col* col = find_named<base_col>(m_cols,a_name); 550 if(!col) return 0; 551 return safe_cast<base_col, aida_col<T> >(*col); 552 } 553 554 template <class T> 555 bool find_column(const std::string& a_name,aida_col<T>*& a_col,bool a_case_sensitive = true) { //for exlib::evaluator. 556 base_col* col = a_case_sensitive ? find_named<base_col>(m_cols,a_name) : find_named_case_insensitive<base_col>(m_cols,a_name); 557 if(!col) {a_col = 0;return false;} 558 a_col = safe_cast<base_col, aida_col<T> >(*col); 559 return a_col?true:false; 560 } 561 562 aida_base_col* find_aida_base_column(const std::string& a_name,bool a_case_sensitive = true){ //for opaw/panntu. 563 base_col* col = a_case_sensitive ? find_named<base_col>(m_cols,a_name) : find_named_case_insensitive<base_col>(m_cols,a_name); 564 if(!col) return 0; 565 return safe_cast<base_col,aida_base_col>(*col); 566 } 567 568 bool get_row() const { 569 bool status = true; 570 tools_vforcit(base_col*,m_cols,it) { 571 if(!(*it)->fetch_entry()) status = false; 572 } 573 return status; 574 } 575 576 bool set_binding(std::ostream& a_out,const ntuple_binding& a_bd = ntuple_binding()) { 577 tools_vforcit(column_binding,a_bd.columns(),itb) { 578 bool found = false; 579 tools_vforcit(base_col*,m_cols,itc) { 580 if((*itc)->name()==(*itb).name()) { 581 (*itc)->set_user_variable((*itb).user_obj()); 582 found = true; 583 } 584 } 585 if(!found) { 586 a_out << "tools::aida::ntuple :" 587 << " binding name " << sout((*itb).name()) << " does not match any ntuple column." 588 << std::endl; 589 return false; 590 } 591 } 592 return true; 593 } 594 595 template <class T> 596 bool column_min(unsigned int a_col,T& a_value) { 597 a_value = T(); 598 if(m_cols.empty()) return false; 599 if(a_col>=m_cols.size()) return false; 600 base_col* _base_col = m_cols[a_col]; 601 aida_col<T>* _col = safe_cast<base_col, aida_col<T> >(*_base_col); 602 if(!_col) return false; 603 start(); 604 uint64 _rows = rows(); 605 T v; 606 {for(uint64 row=0;row<_rows;row++) { 607 if(!next()) {a_value = T();return false;} 608 if(!_col->get_entry(v)) {} 609 if(!row) { 610 a_value = v; 611 } else { 612 a_value = mn<T>(a_value,v); 613 } 614 }} 615 return true; 616 } 617 618 template <class T> 619 bool column_max(unsigned int a_col,T& a_value) { 620 a_value = T(); 621 if(m_cols.empty()) return false; 622 if(a_col>=m_cols.size()) return false; 623 base_col* _base_col = m_cols[a_col]; 624 aida_col<T>* _col = safe_cast<base_col, aida_col<T> >(*_base_col); 625 if(!_col) return false; 626 start(); 627 uint64 _rows = rows(); 628 T v; 629 {for(uint64 row=0;row<_rows;row++) { 630 if(!next()) {a_value = T();return false;} 631 if(!_col->get_entry(v)) {} 632 if(!row) { 633 a_value = v; 634 } else { 635 a_value = mx<T>(a_value,v); 636 } 637 }} 638 return true; 639 } 640 641 }; 642 643 //////////////////////////////////////////////////////////// 644 /// some special column that can't be done with aida_col<T> //// 645 //////////////////////////////////////////////////////////// 646 647 class aida_col_ntu : public base_col { 648 public: 649 static const std::string& s_class() { 650 static const std::string s_v("tools::aida::aida_col_ntu"); 651 return s_v; 652 } 653 virtual void* cast(const std::string& a_class) const { 654 if(void* p = cmp_cast<aida_col_ntu>(this,a_class)) {return p;} 655 return base_col::cast(a_class); 656 } 657 public: 658 virtual base_col* copy() const {return new aida_col_ntu(*this);} 659 virtual bool add() {m_data.push_back(m_tmp);m_tmp.reset();return true;} 660 virtual bool reset() {m_data.clear();m_index = 0;return true;} 661 virtual uint64 num_elems() const {return m_data.size();} 662 public: 663 base_ntu* get_entry() { 664 if(m_index>=m_data.size()) { 665 m_out << s_class() << "::get_entry :" 666 << " bad index " << m_index 667 << ". Vec size is " << m_data.size() << "." 668 << "." 669 << std::endl; 670 return 0; 671 } 672 typedef std::vector<ntuple>::size_type sz_t; 673 return &(m_data[sz_t(m_index)]); 674 } 675 676 virtual void set_user_variable(void* a_user_var) {m_user_var = (ntuple*)a_user_var;} //not owner. 677 virtual bool fetch_entry() const { 678 if(m_index>=m_data.size()) { 679 m_out << s_class() << "::fetch_entry :" 680 << " bad index " << m_index 681 << ". Vec size is " << m_data.size() << "." 682 << "." 683 << std::endl; 684 if(m_user_var) *m_user_var = ntuple(m_out,""); 685 return false; 686 } 687 typedef std::vector<ntuple>::size_type sz_t; 688 if(m_user_var) *m_user_var = m_data[sz_t(m_index)]; 689 return true; 690 } 691 692 virtual base_ntu* get_to_fill() {return &m_tmp;} 693 public: 694 aida_col_ntu(std::ostream& a_out,const std::string& a_name) 695 :base_col(a_out,a_name) 696 ,m_tmp(a_out,"tmp") 697 ,m_user_var(0) //not owner 698 {} 699 public: 700 virtual ~aida_col_ntu(){} 701 public: 702 aida_col_ntu(const aida_col_ntu& a_from) 703 :base_col(a_from) 704 ,m_data(a_from.m_data) 705 706 ,m_tmp(a_from.m_tmp) 707 ,m_user_var(a_from.m_user_var) 708 {} 709 aida_col_ntu& operator=(const aida_col_ntu& a_from){ 710 base_col::operator=(a_from); 711 if(&a_from==this) return *this; 712 m_data = a_from.m_data; 713 714 m_tmp = a_from.m_tmp; 715 m_user_var = a_from.m_user_var; 716 return *this; 717 } 718 protected: 719 std::vector<ntuple> m_data; 720 ntuple m_tmp; 721 ntuple* m_user_var; 722 }; 723 724 inline bool create_cols_from_vals(ntuple& a_ntu, 725 const std::vector<value>& a_vars, 726 bool a_verbose = false){ 727 tools_vforcit(value,a_vars,it) { 728 if((*it).type()==value::VOID_STAR) { 729 if(a_verbose){ 730 a_ntu.out() << "tools::aida::create_cols_from_vals :" 731 << " ITuple : " << (*it).label() << " : begin " 732 << std::endl; 733 } 734 std::vector<value>* vars = (std::vector<value>*)(*it).get_void_star(); 735 736 aida_col_ntu* col_ntu = new aida_col_ntu(a_ntu.out(),(*it).label()); 737 // create sub columns on the "fillable" of col_ntu : 738 base_ntu* sub_base_ntu = col_ntu->get_to_fill(); 739 if(!sub_base_ntu) { 740 delete col_ntu; 741 return false; 742 } 743 ntuple* sub_aida = safe_cast<base_ntu,ntuple>(*sub_base_ntu); 744 if(!sub_aida) { 745 delete col_ntu; 746 return false; 747 } 748 749 if(!create_cols_from_vals(*sub_aida,*vars,a_verbose)) { 750 delete col_ntu; 751 return false; 752 } 753 754 a_ntu.add_column(col_ntu); 755 756 } else { 757 if(a_verbose){ 758 std::string stype; 759 (*it).s_type(stype); 760 std::string sval; 761 (*it).tos(sval); 762 a_ntu.out() << "tools::aida::create_cols_from_vals :" 763 << " " << stype << " : " 764 << (*it).label() << " : " 765 << sval 766 << std::endl; 767 } 768 769 // char,short,int,float,double 770 // byte,boolean,string,long(for int64) 771 // double[] 772 773 base_col* col = 0; 774 /*if((*it).type()==value::CHAR) { 775 col = a_ntu.create_col<char>((*it).label(),(*it).get_char()); 776 } else*/ if((*it).type()==value::SHORT) { 777 col = a_ntu.create_col<short>((*it).label(),(*it).get_short()); 778 } else if((*it).type()==value::INT) { 779 col = a_ntu.create_col<int>((*it).label(),(*it).get_int()); 780 } else if((*it).type()==value::INT64) { 781 col = a_ntu.create_col<int64>((*it).label(),(*it).get_int64()); 782 } else if((*it).type()==value::FLOAT) { 783 col = a_ntu.create_col<float>((*it).label(),(*it).get_float()); 784 } else if((*it).type()==value::DOUBLE) { 785 col = a_ntu.create_col<double>((*it).label(),(*it).get_double()); 786 787 //} else if((*it).type()==value::UNSIGNED_CHAR) { 788 // col = a_ntu.create_col<unsigned char>((*it).label(),(*it).get_unsigned_char()); 789 } else if((*it).type()==value::UNSIGNED_SHORT) { 790 col = a_ntu.create_col<unsigned short>((*it).label(),(*it).get_unsigned_short()); 791 } else if((*it).type()==value::UNSIGNED_INT) { 792 col = a_ntu.create_col<unsigned int>((*it).label(),(*it).get_unsigned_int()); 793 } else if((*it).type()==value::UNSIGNED_INT64) { 794 col = a_ntu.create_col<uint64>((*it).label(),(*it).get_unsigned_int64()); 795 796 } else if((*it).type()==value::BOOL) { 797 col = a_ntu.create_col<bool>((*it).label(),(*it).get_bool()); 798 } else if((*it).type()==value::STRING) { 799 col = a_ntu.create_col<std::string>((*it).label(),(*it).get_string()); 800 } else if((*it).type()==value::INT64) { 801 col = a_ntu.create_col<int64>((*it).label(),(*it).get_int64()); 802 } 803 804 if(!col) { 805 std::string stype; 806 (*it).s_type(stype); 807 std::string sval; 808 (*it).tos(sval); 809 a_ntu.out() << "tools::aida::create_cols_from_vals :" 810 << " failed for " << stype << " : " 811 << (*it).label() << " : " 812 << sval 813 << std::endl; 814 return false; 815 } 816 } 817 } 818 return true; 819 } 820 821 // for raxml : 822 inline bool create_col(ntuple& a_ntu, 823 const std::string& a_type, 824 const std::string& a_name, 825 const std::string& a_s, //def or booking. 826 bool a_is_ntu){ 827 /* 828 if(a_type==s_aida_type((char)0)) { 829 char v = 0; 830 if(a_s.size()&&!to<char>(a_s,v)) { 831 a_ntu.out() << "tools::aida::create_col :" 832 << " can't convert def " << sout(a_s) 833 << " to a " << a_type 834 << std::endl; 835 return false; 836 } 837 if(!a_ntu.create_col<char>(a_name,v)) { 838 a_ntu.out() << "tools::aida::create_col :" 839 << " can't create column of type " << sout(a_type) 840 << std::endl; 841 return false; 842 } 843 844 } else*/ if(a_type==s_aida_type((short)0)) { 845 short v = 0; 846 if(a_s.size()&&!to<short>(a_s,v)) { 847 a_ntu.out() << "tools::aida::create_col :" 848 << " can't convert def " << sout(a_s) 849 << " to a " << a_type 850 << std::endl; 851 return false; 852 } 853 if(!a_ntu.create_col<short>(a_name,v)) { 854 a_ntu.out() << "tools::aida::create_col :" 855 << " can't create column of type " << sout(a_type) 856 << std::endl; 857 return false; 858 } 859 860 } else if(a_type==s_aida_type((int)0)) { 861 int v = 0; 862 if(a_s.size()&&!to<int>(a_s,v)) { 863 a_ntu.out() << "tools::aida::create_col :" 864 << " can't convert def " << sout(a_s) 865 << " to a " << a_type 866 << std::endl; 867 return false; 868 } 869 if(!a_ntu.create_col<int>(a_name,v)) { 870 a_ntu.out() << "tools::aida::create_col :" 871 << " can't create column of type " << sout(a_type) 872 << std::endl; 873 return false; 874 } 875 876 } else if(a_type==s_aida_type((int64)0)) { 877 int64 v = 0; 878 if(a_s.size()&&!to<int64>(a_s,v)) { 879 a_ntu.out() << "tools::aida::create_col :" 880 << " can't convert def " << sout(a_s) 881 << " to a " << a_type 882 << std::endl; 883 return false; 884 } 885 if(!a_ntu.create_col<int64>(a_name,v)) { 886 a_ntu.out() << "tools::aida::create_col :" 887 << " can't create column of type " << sout(a_type) 888 << std::endl; 889 return false; 890 } 891 892 } else if(a_type==s_aida_type((float)0)) { 893 float v = 0; 894 if(a_s.size()&&!to<float>(a_s,v)) { 895 a_ntu.out() << "tools::aida::create_col :" 896 << " can't convert def " << sout(a_s) 897 << " to a " << a_type 898 << std::endl; 899 return false; 900 } 901 if(!a_ntu.create_col<float>(a_name,v)) { 902 a_ntu.out() << "tools::aida::create_col :" 903 << " can't create column of type " << sout(a_type) 904 << std::endl; 905 return false; 906 } 907 908 909 } else if(a_type==s_aida_type((double)0)) { 910 double v = 0; 911 if(a_s.size()&&!to<double>(a_s,v)) { 912 a_ntu.out() << "tools::aida::create_col :" 913 << " can't convert def " << sout(a_s) 914 << " to a " << a_type 915 << std::endl; 916 return false; 917 } 918 if(!a_ntu.create_col<double>(a_name,v)) { 919 a_ntu.out() << "tools::aida::create_col :" 920 << " can't create column of type " << sout(a_type) 921 << std::endl; 922 return false; 923 } 924 925 /* } else if(a_type==s_aida_type((unsigned char)0)) { //byte 926 unsigned int v = 0; 927 if(a_s.size()&&!to<unsigned int>(a_s,v)) { 928 a_ntu.out() << "tools::aida::create_col :" 929 << " can't convert def " << sout(a_s) 930 << " to a " << a_type 931 << std::endl; 932 return false; 933 } 934 if(v>=256) { 935 a_ntu.out() << "tools::aida::create_col :" 936 << " can't convert def " << sout(a_s) 937 << " to byte." 938 << std::endl; 939 return false; 940 } 941 if(!a_ntu.create_col<unsigned char>(a_name,v)) { 942 a_ntu.out() << "tools::aida::create_col :" 943 << " can't create column of type " << sout(a_type) 944 << std::endl; 945 return false; 946 } 947 */ 948 } else if(a_type==s_aida_type((unsigned short)0)) { 949 unsigned short v = 0; 950 if(a_s.size()&&!to<unsigned short>(a_s,v)) { 951 a_ntu.out() << "tools::aida::create_col :" 952 << " can't convert def " << sout(a_s) 953 << " to a " << a_type 954 << std::endl; 955 return false; 956 } 957 if(!a_ntu.create_col<unsigned short>(a_name,v)) { 958 a_ntu.out() << "tools::aida::create_col :" 959 << " can't create column of type " << sout(a_type) 960 << std::endl; 961 return false; 962 } 963 964 } else if(a_type==s_aida_type((unsigned int)0)) { 965 unsigned int v = 0; 966 if(a_s.size()&&!to<unsigned int>(a_s,v)) { 967 a_ntu.out() << "tools::aida::create_col :" 968 << " can't convert def " << sout(a_s) 969 << " to a " << a_type 970 << std::endl; 971 return false; 972 } 973 if(!a_ntu.create_col<unsigned int>(a_name,v)) { 974 a_ntu.out() << "tools::aida::create_col :" 975 << " can't create column of type " << sout(a_type) 976 << std::endl; 977 return false; 978 } 979 980 } else if(a_type==s_aida_type((uint64)0)) { 981 uint64 v = 0; 982 if(a_s.size()&&!to<uint64>(a_s,v)) { 983 a_ntu.out() << "tools::aida::create_col :" 984 << " can't convert def " << sout(a_s) 985 << " to a " << a_type 986 << std::endl; 987 return false; 988 } 989 if(!a_ntu.create_col<uint64>(a_name,v)) { 990 a_ntu.out() << "tools::aida::create_col :" 991 << " can't create column of type " << sout(a_type) 992 << std::endl; 993 return false; 994 } 995 996 ///////////////////////////////////////// 997 ///////////////////////////////////////// 998 } else if(a_type==s_aida_type((bool)true)) { 999 bool v = false; 1000 if(a_s.size()&&!to(a_s,v)) { 1001 a_ntu.out() << "tools::aida::create_col :" 1002 << " can't convert def " << sout(a_s) 1003 << " to a " << a_type 1004 << std::endl; 1005 return false; 1006 } 1007 if(!a_ntu.create_col<bool>(a_name,v)) { 1008 a_ntu.out() << "tools::aida::create_col :" 1009 << " can't create column of type " << sout(a_type) 1010 << std::endl; 1011 return false; 1012 } 1013 1014 } else if(a_type==s_aida_type(std::string())) { 1015 if(!a_ntu.create_col<std::string>(a_name,a_s)) { 1016 a_ntu.out() << "tools::aida::create_col :" 1017 << " can't create column of type " << sout(a_type) 1018 << std::endl; 1019 return false; 1020 } 1021 1022 } else if(a_type==s_aida_type((int64)0)) { 1023 int64 v = 0; 1024 if(a_s.size()&&!to<int64>(a_s,v)) { 1025 a_ntu.out() << "tools::aida::create_col :" 1026 << " can't convert def " << sout(a_s) 1027 << " to a " << a_type 1028 << std::endl; 1029 return false; 1030 } 1031 if(!a_ntu.create_col<int64>(a_name,v)) { 1032 a_ntu.out() << "tools::aida::create_col :" 1033 << " can't create column of type " << sout(a_type) 1034 << std::endl; 1035 return false; 1036 } 1037 1038 } else if(a_type==s_aida_type_ituple()) { 1039 // we expect a booking string on a_s. 1040 1041 if(!a_is_ntu) { 1042 a_ntu.out() << "tools::aida::create_col :" 1043 << " mismatch a_is_ntu/a_type." 1044 << std::endl; 1045 return false; 1046 } 1047 if(a_s.empty()) { 1048 a_ntu.out() << "tools::aida::create_col :" 1049 << " empty booking string." 1050 << std::endl; 1051 return false; 1052 } 1053 1054 columns::finder f(a_ntu.out(),a_s); 1055 if(!f.find_variables()) { 1056 a_ntu.out() << "tools::aida::create_col :" 1057 << " find_variables() failed for " << sout(a_s) << "." 1058 << std::endl; 1059 return false; 1060 } 1061 1062 aida_col_ntu* col_ntu = new aida_col_ntu(a_ntu.out(),a_name); 1063 //create columns on the fillable. 1064 base_ntu* sub_base_ntu = col_ntu->get_to_fill(); 1065 if(!sub_base_ntu) {delete col_ntu;return false;} 1066 ntuple* sub_aida = safe_cast<base_ntu,ntuple>(*sub_base_ntu); 1067 if(!sub_aida) {delete col_ntu;return false;} 1068 1069 std::vector<value> vars;f.result(vars); 1070 if(!create_cols_from_vals(*sub_aida,vars)) { 1071 columns::delete_columns(vars); 1072 delete col_ntu; 1073 return false; 1074 } 1075 columns::delete_columns(vars); 1076 a_ntu.add_column(col_ntu); 1077 1078 //FIXME : double[] 1079 1080 } else { 1081 a_ntu.out() << "tools::aida::create_col :" 1082 << " col type " << sout(a_type) 1083 << " not yet handled." 1084 << std::endl; 1085 return false; 1086 } 1087 1088 return true; 1089 } 1090 1091 // for waxml : 1092 inline bool create_cols_from_string(ntuple& a_ntu, 1093 const std::string& a_booking, 1094 bool a_verbose = false){ 1095 a_ntu.clear(); 1096 if(a_booking.empty()) { 1097 a_ntu.out() << "tools::aida::create_cols_from_string :" 1098 << " empty booking string." 1099 << std::endl; 1100 return false; 1101 } 1102 1103 columns::finder f(a_ntu.out(),a_booking); 1104 if(!f.find_variables()) { 1105 a_ntu.out() << "tools::aida::create_cols_from_string :" 1106 << " find_variables() failed." 1107 << std::endl; 1108 return false; 1109 } 1110 std::vector<value> vars;f.result(vars); 1111 if(a_verbose) columns::dump_columns(a_ntu.out(),vars); 1112 1113 if(!create_cols_from_vals(a_ntu,vars)) { 1114 columns::delete_columns(vars); 1115 a_ntu.clear(); 1116 return false; 1117 } 1118 columns::delete_columns(vars); 1119 return true; 1120 } 1121 1122 inline aida_col_ntu* find_col_ntu(ntuple& a_ntu,const std::string& a_name){ 1123 base_col* col = find_named<base_col>(a_ntu.columns(),a_name); 1124 if(!col) return 0; 1125 return safe_cast<base_col, aida_col_ntu >(*col); 1126 } 1127 1128 template <class T> 1129 class base_looper { 1130 public: 1131 static const std::string& s_class() { 1132 static const std::string s_v("tools::aida::base_looper<"+stype(T())+">"); 1133 return s_v; 1134 } 1135 protected: 1136 virtual bool action(const T& a_value) = 0; //return false to stop processing. 1137 public: 1138 base_looper(base_ntu& a_ntu,const base_col& a_col) 1139 :m_ntu(a_ntu),m_col(a_col){ 1140 #ifdef TOOLS_MEM 1141 mem::increment(s_class().c_str()); 1142 #endif 1143 } 1144 virtual ~base_looper(){ 1145 #ifdef TOOLS_MEM 1146 mem::decrement(s_class().c_str()); 1147 #endif 1148 } 1149 public: 1150 base_looper(const base_looper& a_from) 1151 :m_ntu(a_from.m_ntu),m_col(a_from.m_col){ 1152 #ifdef TOOLS_MEM 1153 mem::increment(s_class().c_str()); 1154 #endif 1155 } 1156 base_looper& operator=(const base_looper&){return *this;} 1157 public: 1158 bool process() { 1159 std::vector<unsigned int> is; 1160 bool found = false; 1161 if(!find_is(m_ntu,&m_col,is,found)) { 1162 m_ntu.out() << s_class() << "::process :" 1163 << " find_is failed." 1164 << std::endl; 1165 return false; 1166 } 1167 if(!found) { 1168 m_ntu.out() << s_class() << "::process :" 1169 << " find_is : col not found." 1170 << std::endl; 1171 return false; 1172 } 1173 if(is.empty()) { 1174 m_ntu.out() << s_class() << "::process :" 1175 << " is vec empty." 1176 << std::endl; 1177 return false; 1178 } 1179 1180 bool stop = false; 1181 if(!_looper(m_ntu,is,0,stop)) { 1182 m_ntu.out() << s_class() << "::process :" 1183 << " _looper failed." 1184 << std::endl; 1185 return false; 1186 } 1187 return true; 1188 } 1189 protected: 1190 static bool find_is(const base_ntu& a_ntu,const base_col* a_col, 1191 std::vector<unsigned int>& a_is, 1192 bool& a_found){ 1193 // search the indices to reach the sub leaf a_col from the main a_ntu. 1194 // Note : it is assumed that a_is is empty and a_found = false before 1195 // calling with function. 1196 1197 const std::vector<base_col*>& cols = a_ntu.columns(); 1198 1199 // look if a_col is a leaf col of a_ntu : 1200 {unsigned int index = 0; 1201 tools_vforcit(base_col*,cols,it) { 1202 if(*it==a_col) { 1203 a_is.push_back(index); //leaf index is the last one in a_is. 1204 a_found = true; 1205 return true; 1206 } 1207 index++; 1208 }} 1209 1210 // go down sub ntu : 1211 {unsigned int index = 0; 1212 tools_vforcit(base_col*,cols,it) { 1213 aida_col_ntu* col = safe_cast<base_col,aida_col_ntu>(*(*it)); 1214 if(col) { 1215 base_ntu* sub = col->get_to_fill(); //it holds the "sub" cols schema. 1216 if(!sub) {a_is.clear();return false;} 1217 a_is.push_back(index); 1218 if(!find_is(*sub,a_col,a_is,a_found)) {a_is.clear();return false;} 1219 if(a_found) return true; 1220 a_is.pop_back(); 1221 } 1222 index++; 1223 }} 1224 return true; 1225 } 1226 protected: 1227 bool _looper(base_ntu& a_sub, 1228 const std::vector<unsigned int>& a_is, 1229 unsigned int a_depth, 1230 bool& a_stop) { 1231 if(a_depth>=a_is.size()) return false; 1232 1233 unsigned int coli = a_is[a_depth]; 1234 const std::vector<base_col*>& cols = a_sub.columns(); 1235 if(coli>=cols.size()) return false; 1236 1237 if(a_depth==(a_is.size()-1)) { //we reach the leaf. 1238 aida_col<T>* col = safe_cast<base_col, aida_col<T> >(*(cols[coli])); 1239 if(!col) return false; 1240 a_sub.start(); 1241 while(a_sub.next()) { 1242 T v; 1243 if(!col->get_entry(v)) return false; 1244 if(!action(v)) {a_stop = true;break;} 1245 } 1246 } else { 1247 aida_col_ntu* col = safe_cast<base_col,aida_col_ntu>(*(cols[coli])); 1248 if(!col) return false; 1249 a_sub.start(); 1250 while(a_sub.next()) { 1251 base_ntu* ntu = col->get_entry(); //not const. 1252 if(!ntu) return false; 1253 ntu->start(); 1254 while(ntu->next()) { 1255 if(!_looper(*ntu,a_is,a_depth+1,a_stop)) return false; 1256 if(a_stop) break; 1257 } 1258 } 1259 } 1260 return true; 1261 } 1262 protected: 1263 base_ntu& m_ntu; 1264 const base_col& m_col; 1265 }; 1266 1267 }} 1268 1269 #include "mnmx" 1270 1271 namespace tools { 1272 namespace aida { 1273 1274 template <class T> 1275 class stat_looper : public base_looper<T> { 1276 protected: 1277 virtual bool action(const T& a_v) { 1278 if(m_first) { 1279 m_mn = a_v; 1280 m_mx = a_v; 1281 m_S = a_v; 1282 m_S2 = a_v*a_v; 1283 1284 m_first = false; 1285 } else { 1286 m_mn = min_of<T>(m_mn,a_v); 1287 m_mx = max_of<T>(m_mx,a_v); 1288 m_S += a_v; 1289 m_S2 += a_v*a_v; 1290 } 1291 m_counter++; 1292 return true; //continue looping. 1293 } 1294 public: 1295 stat_looper(base_ntu& a_ntu,const base_col& a_col) 1296 :base_looper<T>(a_ntu,a_col) 1297 ,m_first(true) 1298 ,m_mn(T()) 1299 ,m_mx(T()) 1300 ,m_S(T()) 1301 ,m_S2(T()) 1302 ,m_counter(0) 1303 {} 1304 virtual ~stat_looper(){} 1305 public: 1306 stat_looper(const stat_looper& a_from) 1307 :base_looper<T>(a_from) 1308 ,m_first(true) 1309 ,m_mn(T()) 1310 ,m_mx(T()) 1311 ,m_S(T()) 1312 ,m_S2(T()) 1313 ,m_counter(0) 1314 {} 1315 stat_looper& operator=(const stat_looper& a_from){ 1316 base_looper<T>::operator=(a_from); 1317 if(&a_from==this) return *this; 1318 m_first = true; 1319 m_mn = T(); 1320 m_mx = T(); 1321 m_S = T(); 1322 m_S2 = T(); 1323 m_counter = 0; 1324 return *this; 1325 } 1326 public: 1327 bool process() { 1328 m_counter = 0; 1329 if(!base_looper<T>::process()) { 1330 m_mn = T(); 1331 m_mx = T(); 1332 m_S = T(); 1333 m_S2 = T(); 1334 m_counter = 0; 1335 return false; 1336 } 1337 return true; 1338 } 1339 T mn() const {return m_mn;} 1340 T mx() const {return m_mx;} 1341 T S() const {return m_S;} 1342 T S2() const {return m_S2;} 1343 uint64 counter() const {return m_counter;} 1344 protected: 1345 bool m_first; 1346 T m_mn; 1347 T m_mx; 1348 T m_S; 1349 T m_S2; 1350 uint64 m_counter; 1351 }; 1352 1353 template <class T> 1354 inline bool column_infos(base_ntu& a_ntu, 1355 base_col& a_col, 1356 T& a_mn,T& a_mx,T& a_S,T& a_S2, 1357 uint64& a_count){ 1358 stat_looper<T> lpr(a_ntu,a_col); 1359 bool status = lpr.process(); 1360 a_mn = lpr.mn(); 1361 a_mx = lpr.mx(); 1362 a_S = lpr.S(); 1363 a_S2 = lpr.S2(); 1364 a_count = lpr.counter(); 1365 if(!status) return false; 1366 if(!a_count) return false; 1367 return true; 1368 } 1369 1370 inline base_col* find_leaf_column(const base_ntu& a_ntu,const std::string& a_name){ 1371 const std::vector<base_col*>& cols = a_ntu.columns(); 1372 tools_vforcit(base_col*,cols,it) { 1373 aida_col_ntu* col = safe_cast<base_col,aida_col_ntu>(*(*it)); 1374 if(col) { 1375 base_ntu* sub = col->get_to_fill(); //it holds the "sub" cols schema. 1376 if(!sub) return 0; 1377 base_col* fcol = find_leaf_column(*sub,a_name); 1378 if(fcol) return fcol; 1379 } else { 1380 if((*it)->name()==a_name) return *it; 1381 } 1382 } 1383 return 0; 1384 } 1385 1386 template <class T> 1387 inline bool to_vector(base_ntu& a_ntu,std::vector<double>& a_vec,unsigned int a_col = 0) { 1388 a_vec.clear(); 1389 const std::vector<base_col*>& cols = a_ntu.columns(); 1390 if(cols.empty()) return false; 1391 if(a_col>=cols.size()) return false; 1392 base_col* _base_col = cols[a_col]; 1393 aida_col<T>* _col = safe_cast<base_col, aida_col<T> >(*_base_col); 1394 if(!_col) return false; 1395 a_ntu.start(); 1396 uint64 _rows = a_ntu.rows(); 1397 a_vec.resize(_rows); 1398 T v; 1399 {for(uint64 row=0;row<_rows;row++) { 1400 if(!a_ntu.next()) {a_vec.clear();return false;} 1401 if(!_col->get_entry(v)) {} 1402 a_vec[row] = v; 1403 }} 1404 return true; 1405 } 1406 1407 template <class T> 1408 inline bool column_min(ntuple& a_ntu,unsigned int a_col,T& a_value) { 1409 return a_ntu.column_min(a_col,a_value); 1410 } 1411 1412 template <class T> 1413 inline bool column_max(ntuple& a_ntu,unsigned int a_col,T& a_value) { 1414 return a_ntu.column_max(a_col,a_value); 1415 } 1416 1417 }} 1418 1419 #endif