inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_rroot_streamers 00005 #define inlib_rroot_streamers 00006 00007 #include "named" 00008 #include "date" 00009 #include "directory" 00010 #include "graph" 00011 #include "../sout" 00012 #include "../vmanip" 00013 00014 //#include "../histo/histo_data" 00015 #include "../histo/profile_data" 00016 00017 #include "../histo/h1d" 00018 #include "../histo/h2d" 00019 //#include "../histo/h3d" 00020 #include "../histo/p1d" 00021 //#include "../histo/p2d" 00022 00023 #include <list> 00024 #include <cmath> //::log10, ::fabs. 00025 00026 namespace inlib { 00027 namespace rroot { 00028 00029 typedef inlib::histo::histo_data<double,unsigned int,double> hd_data; 00030 typedef inlib::histo::profile_data<double,unsigned int,double,double> pd_data; 00031 00032 inline bool AttAxis_stream(buffer& a_buffer){ 00033 int fNdivisions = 510; //Number of divisions(10000*n3 + 100*n2 + n1) 00034 short fAxisColor = 1; //color of the line axis 00035 short fLabelColor = 1; //color of labels 00036 short fLabelFont = 62; //font for labels 00037 float fLabelOffset = 0.005F; //offset of labels 00038 float fLabelSize = 0.04F; //size of labels 00039 float fTickLength = 0.03F; //length of tick marks 00040 float fTitleOffset = 1; //offset of axis title 00041 float fTitleSize = 0.04F; //size of axis title 00042 short fTitleColor = 1; //color of axis title 00043 short fTitleFont = 62; //font for axis title 00044 00045 // Version 4 streaming (ROOT/v3-00-6). 00046 short v; 00047 unsigned int s, c; 00048 if(!a_buffer.read_version(v,s,c)) return false; 00049 00050 if(!a_buffer.read(fNdivisions)) return false; 00051 if(!a_buffer.read(fAxisColor)) return false; 00052 if(!a_buffer.read(fLabelColor)) return false; 00053 if(!a_buffer.read(fLabelFont)) return false; 00054 if(!a_buffer.read(fLabelOffset)) return false; 00055 if(!a_buffer.read(fLabelSize)) return false; 00056 if(!a_buffer.read(fTickLength)) return false; 00057 if(!a_buffer.read(fTitleOffset)) return false; 00058 if(!a_buffer.read(fTitleSize)) return false; 00059 if(!a_buffer.read(fTitleColor)) return false; 00060 if(!a_buffer.read(fTitleFont)) return false; 00061 00062 if(!a_buffer.check_byte_count(s, c,"TAttAxis")) return false; 00063 return true; 00064 } 00065 00066 class dummy_fac : public virtual ifac { 00067 public: //ifac 00068 virtual iro* create(const std::string& a_class,const args&) { 00069 if(a_class=="TGraph") { //for TH_read_1D/List. 00070 return new graph(); 00071 } else { 00072 m_out << "inlib::rroot::dummy_fac::create :" 00073 << " dummy. Can't create object of class " << sout(a_class) << "." 00074 << std::endl; 00075 } 00076 return 0; 00077 } 00078 public: 00079 dummy_fac(std::ostream& a_out):m_out(a_out){} 00080 virtual ~dummy_fac(){} 00081 protected: 00082 dummy_fac(const dummy_fac& a_from): ifac(a_from),m_out(a_from.m_out){} 00083 dummy_fac& operator=(const dummy_fac&){return *this;} 00084 protected: 00085 std::ostream& m_out; 00086 }; 00087 00088 inline bool Axis_stream(buffer& a_buffer,inlib::histo::axis<double>& a_fAxis){ 00089 // Version 6 streaming (ROOT/v3-00-6). 00090 short v; 00091 unsigned int s, c; 00092 if(!a_buffer.read_version(v,s,c)) return false; 00093 00094 std::string name; 00095 std::string title; 00096 if(!Named_stream(a_buffer,name,title)) return false; 00097 00098 if(!AttAxis_stream(a_buffer)) return false; 00099 00100 int number; 00101 if(!a_buffer.read(number)) return false; 00102 double min; 00103 if(!a_buffer.read(min)) return false; 00104 double max; 00105 if(!a_buffer.read(max)) return false; 00106 //printf("debug : BatchLab::RioTH::streamTAxis : %d %g %g\n", 00107 // number,min,max); 00108 00109 std::vector<double> edges; 00110 if(!Array_stream<double>(a_buffer,edges)) return false; //fXbins TArrayD 00111 00112 int edgen = edges.size(); 00113 if(edgen<=0) { 00114 a_fAxis.configure(number,min,max); 00115 } else { 00116 std::vector<double> vedges; 00117 for(int index=0;index<edgen;index++) { 00118 vedges.push_back(edges[index]); 00119 } 00120 a_fAxis.configure(vedges); 00121 } 00122 00123 int First; 00124 if(!a_buffer.read(First)) return false; 00125 int Last; 00126 if(!a_buffer.read(Last)) return false; 00127 00128 if(v>=8) { //fBits2. 00129 unsigned short dummy; 00130 if(!a_buffer.read(dummy)) return false; 00131 } 00132 00133 //Bool_t 00134 unsigned char TimeDisplay; 00135 if(!a_buffer.read(TimeDisplay)) return false; 00136 00137 //TString 00138 std::string TimeFormat; 00139 if(!a_buffer.read(TimeFormat)) return false; 00140 00141 if(v>=7) { 00142 dummy_fac fac(a_buffer.out()); 00143 ifac::args args; 00144 iro* obj; 00145 if(!a_buffer.read_object(fac,args,obj)) return false; //THashList* 00146 } 00147 00148 if(!a_buffer.check_byte_count(s,c,"TAxis")) return false; 00149 return true; 00150 } 00151 00152 class List : public std::vector<iro*> { 00153 public: 00154 List(){} 00155 virtual ~List(){_clear();} 00156 protected: 00157 List(const List& a_from):std::vector<iro*>(a_from){} 00158 List& operator=(const List&){return *this;} 00159 public: 00160 bool stream(buffer& a_buffer){ 00161 // Stream all objects in the collection to or from the I/O buffer. 00162 _clear(); 00163 00164 short v; 00165 unsigned int s, c; 00166 if(!a_buffer.read_version(v,s,c)) return false; 00167 {uint32 id,bits; 00168 if(!Object_stream(a_buffer,id,bits)) return false;} 00169 if(!a_buffer.read(m_name)) return false; 00170 00171 int nobjects; 00172 if(!a_buffer.read(nobjects)) return false; 00173 00174 for (int i = 0; i < nobjects; i++) { 00175 dummy_fac fac(a_buffer.out()); 00176 ifac::args args; 00177 iro* obj; 00178 if(!a_buffer.read_object(fac,args,obj)) { 00179 a_buffer.out() << "inlib::rroot::List::stream :" 00180 << " can't read object." 00181 << " index " << i 00182 << " over " << nobjects << " objects." 00183 << std::endl; 00184 _clear(); 00185 return false; 00186 } 00187 unsigned char nch; 00188 if(!a_buffer.read(nch)) { 00189 _clear(); 00190 return false; 00191 } 00192 if(nch) { 00193 char readOption[256]; 00194 if(!a_buffer.read_fast_array(readOption,nch)) { 00195 _clear(); 00196 return false; 00197 } 00198 readOption[nch] = 0; 00199 } else { 00200 } 00201 if(obj) push_back(obj); 00202 } 00203 00204 if(!a_buffer.check_byte_count(s,c,"TList")) { 00205 _clear(); 00206 return false; 00207 } 00208 return true; 00209 } 00210 protected: 00211 void _clear() { 00212 //if(m_owner) { 00213 inlib::clear<iro>(*this); 00214 //} else { 00215 // std::vector<T*>::clear(); 00216 //} 00217 } 00218 protected: 00219 std::string m_name; 00220 }; 00221 00222 inline bool null_epsil(double a_1,double a_2,double a_prec = -5) { 00223 return (::log10(::fabs(a_1-a_2))<a_prec?true:false); 00224 } 00225 00226 inline bool TH_read_1D(buffer& a_buffer,hd_data& a_data, 00227 double& a_fEntries,double& a_fSw){ 00228 a_fEntries = 0; 00229 a_fSw = 0; 00230 00231 unsigned int s, c; 00232 short v; 00233 if(!a_buffer.read_version(v,s,c)) return false; 00234 00235 //printf("debug : BatchLab::Rio::TH::streamTH1 : version %d\n",v); 00236 00237 // Version 3 streaming (ROOT/v3-00-6). 00238 00239 std::string name; 00240 std::string title; 00241 if(!Named_stream(a_buffer,name,title)) return false; 00242 00243 a_data.m_title = title; 00244 00245 if(!AttLine_stream(a_buffer)) return false; 00246 if(!AttFill_stream(a_buffer)) return false; 00247 if(!AttMarker_stream(a_buffer)) return false; 00248 00249 int Ncells; 00250 if(!a_buffer.read(Ncells)) return false; 00251 00252 //fXAxis 00253 if(!Axis_stream(a_buffer,a_data.m_axes[0])) return false; 00254 a_data.m_axes[0].m_offset = 1; 00255 00256 if(a_data.m_dimension==2) { 00257 if(!Axis_stream(a_buffer,a_data.m_axes[1])) return false; //fYAxis 00258 a_data.m_axes[1].m_offset = 00259 a_data.m_axes[0].m_offset * (a_data.m_axes[0].bins()+2); 00260 00261 inlib::histo::axis<double> dummy; 00262 if(!Axis_stream(a_buffer,dummy)) return false; //fZAxis 00263 } else { 00264 inlib::histo::axis<double> dummy; 00265 if(!Axis_stream(a_buffer,dummy)) return false; //fYAxis 00266 if(!Axis_stream(a_buffer,dummy)) return false; //fZAxis 00267 } 00268 00269 short barOffset; 00270 if(!a_buffer.read(barOffset)) return false; 00271 00272 short barWidth; 00273 if(!a_buffer.read(barWidth)) return false; 00274 00275 if(!a_buffer.read(a_fEntries)) return false; 00276 00277 if(!a_buffer.read(a_fSw)) return false; //fTsumw 00278 //printf("debug : BatchLab::Rio::TH::streamTH1 : \"%s\" %g %g\n", 00279 //a_data.m_title.c_str(),fEntries,fSw); 00280 00281 double sw2; 00282 if(!a_buffer.read(sw2)) return false; 00283 00284 double xSxw; 00285 if(!a_buffer.read(xSxw)) return false; 00286 00287 double xSx2w; 00288 if(!a_buffer.read(xSx2w)) return false; 00289 00290 double max; 00291 if(!a_buffer.read(max)) return false; 00292 00293 double min; 00294 if(!a_buffer.read(min)) return false; 00295 00296 double NormFactor; 00297 if(!a_buffer.read(NormFactor)) return false; 00298 00299 {std::vector<double> v; 00300 if(!Array_stream<double>(a_buffer,v)) return false;} //fContour TArrayD 00301 00302 std::vector<double> sumw2; //fSumw2 TArrayD 00303 if(!Array_stream<double>(a_buffer,sumw2)) return false; 00304 00305 {std::string opt; 00306 if(!a_buffer.read(opt)) return false; //TString fOption 00307 //look if it is an "annotation trick" : 00308 //if(opt.size()&&(opt[0]==0)) { 00309 // fAnnotation = opt.substr(1,opt.size()-1); 00310 //} 00311 } 00312 00313 {List dummy; 00314 if(!dummy.stream(a_buffer)) { 00315 a_buffer.out() << "inlib::rroot::TH_read_1D :" 00316 << " List stream failed." 00317 << std::endl; 00318 return false; 00319 }} //Functions 00320 00321 if(v>=4) { 00322 int BufferSize; 00323 if(!a_buffer.read(BufferSize)) return false; 00324 00325 //Double_t[fBufferSize] 00326 {char isArray; 00327 if(!a_buffer.read(isArray)) return false; 00328 if(isArray!=0) { 00329 if(BufferSize) { 00330 double* Buffer = new double[BufferSize]; 00331 if(!a_buffer.read_fast_array<double>(Buffer,BufferSize)) 00332 return false; 00333 delete [] Buffer; 00334 } 00335 }} 00336 } 00337 00338 // Add two for outflows. 00339 if(a_data.m_dimension==1) { 00340 a_data.m_bin_number = a_data.m_axes[0].m_number_of_bins + 2; 00341 } else if(a_data.m_dimension==2) { 00342 a_data.m_bin_number = 00343 (a_data.m_axes[0].m_number_of_bins + 2) * 00344 (a_data.m_axes[1].m_number_of_bins + 2); 00345 } 00346 00347 unsigned int binn = a_data.m_bin_number; 00348 a_data.m_bin_Sw2.resize(binn,0); 00349 if(binn==sumw2.size()) { 00350 for(unsigned int index=0;index<binn;index++){ 00351 a_data.m_bin_Sw2[index] = sumw2[index]; 00352 } 00353 } 00354 00355 if(!a_buffer.check_byte_count(s,c,"TH")) return false; 00356 00357 return true; 00358 } 00359 00360 00361 inline bool TH_read_2D(buffer& a_buffer,hd_data& a_data, 00362 double& a_fEntries,double& a_fSw){ 00363 unsigned int s, c; 00364 short v; 00365 if(!a_buffer.read_version(v,s,c)) return false; 00366 00367 //printf("debug : BatchLab::Rio::TH::streamTH2 : version %d\n",v); 00368 00369 // Version 3 streaming (ROOT/v3-00-6). 00370 00371 if(!TH_read_1D(a_buffer,a_data,a_fEntries,a_fSw)) return false; 00372 00373 double ScaleFactor; 00374 if(!a_buffer.read(ScaleFactor)) return false; 00375 double Tsumwy; 00376 if(!a_buffer.read(Tsumwy)) return false; 00377 double Tsumwy2; 00378 if(!a_buffer.read(Tsumwy2)) return false; 00379 double Tsumwxy; 00380 if(!a_buffer.read(Tsumwxy)) return false; 00381 00382 if(!a_buffer.check_byte_count(s,c,"TH2")) return false; 00383 00384 return true; 00385 } 00386 00387 inline const std::string& TH1F_cls(){ 00388 static const std::string s_v("TH1F"); 00389 return s_v; 00390 } 00391 00392 inline inlib::histo::h1d* TH1F_stream(buffer& a_buffer,bool a_profile = false){ 00393 unsigned int s, c; 00394 short v; 00395 if(!a_buffer.read_version(v,s,c)) return 0; 00396 00397 //printf("debug : BatchLab::Rio::TH1F::stream : version %d\n",v); 00398 00399 // Version 1 streaming (ROOT/v3-00-6). 00400 00401 // Now we have to reconstruct a valid Histogram from a_buffer : 00402 hd_data data; 00403 00404 data.m_dimension = 1; 00405 //data.m_coords.resize(data.m_dimension,0); 00406 //data.m_ints.resize(data.m_dimension,0); 00407 data.m_axes.resize(1); 00408 00409 double fEntries; 00410 double fSw; 00411 if(!TH_read_1D(a_buffer,data,fEntries,fSw)) return 0; 00412 00413 std::vector<float> bins; //fArray TArrayF 00414 if(!Array_stream<float>(a_buffer,bins)) return 0; 00415 00416 unsigned int binn = data.m_bin_number; 00417 //printf("debug : BatchLab::Rio::TH1F::stream : histo bins %d\n",binn); 00418 data.m_bin_Sw.resize(binn,0); 00419 double asw = 0; 00420 {for(unsigned int index=0;index<binn;index++){ 00421 double h = double(bins[index]); 00422 data.m_bin_Sw[index] = h; 00423 asw += h; 00424 }} 00425 if(!a_profile) { 00426 double sw = data.get_Sw(); 00427 if(!null_epsil(sw,fSw)) { 00428 a_buffer.out() << "inlib::rroot::TH1F::stream : " 00429 << " WARNING : inconsistent total weight" 00430 << " for histo with title " << sout(data.m_title) << " :" 00431 << std::endl 00432 << " read fSw is " << fSw 00433 << " whilst sum of in-range bins weight is " << sw 00434 << " (diff is " << (sw-fSw) << ")." 00435 << std::endl; 00436 } 00437 } 00438 00439 // Fill Sxw and Sx2w by using in range bins : 00440 std::vector<double> empty; 00441 empty.resize(1,0); 00442 data.m_bin_Sxw.resize(binn,empty); 00443 data.m_bin_Sx2w.resize(binn,empty); 00444 std::vector<int> is(data.m_dimension); 00445 {for(unsigned int index=0;index<binn;index++){ 00446 if(!data.is_out(index)) { 00447 float height = bins[index]; 00448 data.get_indices(index,is); 00449 for(unsigned int iaxis=0;iaxis<data.m_dimension;iaxis++) { 00450 double x = data.m_axes[iaxis].bin_center(is[iaxis]); 00451 data.m_bin_Sxw[index][iaxis] = x * height; 00452 data.m_bin_Sx2w[index][iaxis] = x * x * height; 00453 } 00454 } 00455 }} 00456 00457 //ROOT does not store the number of entries per bin. 00458 // We have the global number of entries and weight ; with that 00459 // we do our best.... 00460 data.m_bin_entries.resize(binn,0); 00461 if(!a_profile && asw) { 00462 for(unsigned int index=0;index<binn;index++){ 00463 float height = bins[index]; 00464 int number = (int)((fEntries * height) / asw); 00465 if(number<0) { 00466 } else { 00467 data.m_bin_entries[index] = number; 00468 } 00469 } 00470 int allEntries = data.get_all_entries(); 00471 if(allEntries<int(fEntries)) { //FIXME 00472 //Correct some bins randomly (beurk, do you have a better idea ?) : 00473 int diff = int(fEntries)-allEntries; 00474 unsigned int nx = data.m_axes[0].m_number_of_bins; 00475 for(int i=0;i<diff;i++) { 00476 int ri = ::rand(); 00477 // ibin in [1,nx-1] 00478 int ibin = int((nx-1) * ((double)ri/(double)RAND_MAX)) + 1; 00479 int offset = ibin; 00480 data.m_bin_entries[offset]++; 00481 } 00482 } else if(allEntries>int(fEntries)) { //FIXME 00483 a_buffer.out() << "inlib::rroot::TH1F::stream : " 00484 << " WARNING : can't reemulate number of entries per bin " 00485 << " for histo with title " << sout(data.m_title) << " :" 00486 << std::endl 00487 << " read fEntries (a double) is " << fEntries 00488 << " whilst corrected bin entries is " << allEntries 00489 << " (diff is " << (allEntries-int(fEntries)) << ")." 00490 << std::endl; 00491 } else { 00492 } 00493 } 00494 00495 if(!a_buffer.check_byte_count(s,c,"TH1F")) return 0; 00496 00497 inlib::histo::h1d* h = new inlib::histo::h1d("",10,0,1); 00498 h->copy_from_data(data); 00499 h->update_fast_getters(); 00500 // We have now a valid HCL histogram. 00501 return h; //give ownership to caller. 00502 } 00503 00504 inline const std::string& TH1D_cls(){ 00505 static const std::string s_v("TH1D"); 00506 return s_v; 00507 } 00508 00509 inline inlib::histo::h1d* TH1D_stream(buffer& a_buffer,bool a_profile = false){ 00510 unsigned int s, c; 00511 short v; 00512 if(!a_buffer.read_version(v,s,c)) return 0; 00513 00514 //printf("debug : BatchLab::Rio::TH1D::stream : version %d\n",v); 00515 00516 // Version 1 streaming (ROOT/v3-00-6). 00517 00518 // Now we have to reconstruct a valid Histogram from a_buffer : 00519 hd_data data; 00520 00521 data.m_dimension = 1; 00522 //data.m_coords.resize(data.m_dimension,0); 00523 //data.m_ints.resize(data.m_dimension,0); 00524 data.m_axes.resize(1); 00525 00526 double fEntries; 00527 double fSw; 00528 if(!TH_read_1D(a_buffer,data,fEntries,fSw)) return 0; 00529 00530 std::vector<double> bins; //fArray TArrayD 00531 if(!Array_stream<double>(a_buffer,bins)) return 0; 00532 00533 unsigned int binn = data.m_bin_number; 00534 //printf("debug : BatchLab::Rio::TH1D::stream : histo bins %d\n",binn); 00535 data.m_bin_Sw.resize(binn,0); 00536 double asw = 0; 00537 {for(unsigned int index=0;index<binn;index++){ 00538 double h = bins[index]; 00539 data.m_bin_Sw[index] = h; 00540 asw += h; 00541 }} 00542 if(!a_profile) { 00543 double sw = data.get_Sw(); 00544 if(!null_epsil(sw,fSw)) { 00545 a_buffer.out() << "inlib::rroot::TH1D::stream : " 00546 << " WARNING : inconsistent total weight" 00547 << " for histo with title " << sout(data.m_title) << " :" 00548 << std::endl 00549 << " read fSw is " << fSw 00550 << " whilst sum of in-range bins weight is " << sw 00551 << " (diff is " << (sw-fSw) << ")." 00552 << std::endl; 00553 } 00554 } 00555 00556 // Fill Sxw and Sx2w by using in range bins : 00557 std::vector<double> empty; 00558 empty.resize(1,0); 00559 data.m_bin_Sxw.resize(binn,empty); 00560 data.m_bin_Sx2w.resize(binn,empty); 00561 std::vector<int> is(data.m_dimension); 00562 for(unsigned int index=0;index<binn;index++){ 00563 if(!data.is_out(index)) { 00564 double height = bins[index]; 00565 data.get_indices(index,is); 00566 for(unsigned int iaxis=0;iaxis<data.m_dimension;iaxis++) { 00567 double x = data.m_axes[iaxis].bin_center(is[iaxis]); 00568 data.m_bin_Sxw[index][iaxis] = x * height; 00569 data.m_bin_Sx2w[index][iaxis] = x * x * height; 00570 } 00571 } 00572 } 00573 00574 //ROOT does not store the number of entries per bin. 00575 // We have the global number of entries and weight ; with that 00576 // we do our best.... 00577 data.m_bin_entries.resize(binn,0); 00578 if(!a_profile && asw) { 00579 for(unsigned int index=0;index<binn;index++){ 00580 double height = bins[index]; 00581 int number = (int)((fEntries * height) / asw); 00582 if(number<0) { 00583 } else { 00584 data.m_bin_entries[index] = number; 00585 } 00586 } 00587 int allEntries = data.get_all_entries(); 00588 if(allEntries<int(fEntries)) { //FIXME 00589 //Correct some bins randomly (beurk, do you have a better idea ?) : 00590 int diff = int(fEntries)-allEntries; 00591 unsigned int nx = data.m_axes[0].m_number_of_bins; 00592 for(int i=0;i<diff;i++) { 00593 int ri = ::rand(); 00594 int ibin = int((nx-1) * ((double)ri/(double)RAND_MAX)) + 1; 00595 int offset = ibin; 00596 data.m_bin_entries[offset]++; 00597 } 00598 } else if(allEntries>int(fEntries)) { //FIXME 00599 a_buffer.out() << "inlib::rroot::TH1D::stream : " 00600 << " WARNING : can't reemulate number of entries per bin " 00601 << " for histo with title " << sout(data.m_title) << " :" 00602 << std::endl 00603 << " read fEntries (a double) is " << fEntries 00604 << " whilst corrected bin entries is " << allEntries 00605 << " (diff is " << (allEntries-int(fEntries)) << ")." 00606 << std::endl; 00607 } else { 00608 } 00609 } 00610 00611 if(!a_buffer.check_byte_count(s,c,"TH1D")) return 0; 00612 00613 inlib::histo::h1d* h = new inlib::histo::h1d("",10,0,1); 00614 h->copy_from_data(data); 00615 h->update_fast_getters(); 00616 // We have now a valid HCL histogram. 00617 00618 return h; 00619 } 00620 00621 inline const std::string& TH2F_cls(){ 00622 static const std::string s_v("TH2F"); 00623 return s_v; 00624 } 00625 00626 inline inlib::histo::h2d* TH2F_stream(buffer& a_buffer,bool a_profile = false){ 00627 unsigned int s, c; 00628 short v; 00629 if(!a_buffer.read_version(v,s,c)) return 0; 00630 00631 //printf("debug : BatchLab::Rio::TH2F::stream : version %d\n",v); 00632 00633 // Version 3 streaming (ROOT/v3-00-6). 00634 00635 // Now we have to reconstruct a valid Histogram from a_buffer : 00636 hd_data data; 00637 00638 data.m_dimension = 2; 00639 //data.m_coords.resize(data.m_dimension,0); 00640 //data.m_ints.resize(data.m_dimension,0); 00641 data.m_axes.resize(2); 00642 00643 double fEntries; 00644 double fSw; 00645 if(!TH_read_2D(a_buffer,data,fEntries,fSw)) return 0; 00646 00647 std::vector<float> bins; //fArray TArrayF 00648 if(!Array_stream<float>(a_buffer,bins)) return 0; 00649 00650 //printf("debug : BatchLab::Rio::TH2F::stream : histo bins %d\n",n); 00651 unsigned int binn = data.m_bin_number; 00652 data.m_bin_Sw.resize(binn,0); 00653 double asw = 0; 00654 {for(unsigned int index=0;index<binn;index++){ 00655 double h = double(bins[index]); 00656 data.m_bin_Sw[index] = h; 00657 asw += h; 00658 }} 00659 if(!a_profile) { 00660 double sw = data.get_Sw(); 00661 if(!null_epsil(sw,fSw)) { 00662 a_buffer.out() << "exlib::rroot::TH2F::stream : " 00663 << " WARNING : inconsistent total weight" 00664 << " for histo with title " << sout(data.m_title) << " :" 00665 << std::endl 00666 << " read fSw is " << fSw 00667 << " whilst sum of in-range bins weight is " << sw 00668 << " (diff is " << (sw-fSw) << ")." 00669 << std::endl; 00670 } 00671 } 00672 00673 // Fill Sxw and Sx2w by using in range bins : 00674 std::vector<double> empty; 00675 empty.resize(2,0); 00676 data.m_bin_Sxw.resize(binn,empty); 00677 data.m_bin_Sx2w.resize(binn,empty); 00678 std::vector<int> is(data.m_dimension); 00679 for(unsigned int index=0;index<binn;index++){ 00680 if(!data.is_out(index)) { 00681 float height = bins[index]; 00682 data.get_indices(index,is); 00683 for(unsigned int iaxis=0;iaxis<data.m_dimension;iaxis++) { 00684 double x = data.m_axes[iaxis].bin_center(is[iaxis]); 00685 data.m_bin_Sxw[index][iaxis] = x * height; 00686 data.m_bin_Sx2w[index][iaxis] = x * x * height; 00687 } 00688 } 00689 } 00690 00691 //ROOT does not store the number of entries per bin. 00692 // We have the global number of entries and weight ; with that 00693 // we do our best.... 00694 data.m_bin_entries.resize(binn,0); 00695 if(!a_profile && asw) { 00696 for(unsigned int index=0;index<binn;index++){ 00697 float height = bins[index]; 00698 int number = (int)((fEntries * height) / asw); 00699 if(number<0) { 00700 } else { 00701 data.m_bin_entries[index] = number; 00702 } 00703 } 00704 int allEntries = data.get_all_entries(); 00705 if(allEntries<(int)fEntries) { //FIXME 00706 //Correct some bins randomly (beurk, do you have a better idea ?) : 00707 int diff = int(fEntries-allEntries); 00708 unsigned int nx = data.m_axes[0].m_number_of_bins; 00709 unsigned int ny = data.m_axes[1].m_number_of_bins; 00710 for(int i=0;i<diff;i++) { 00711 int ri = ::rand(); 00712 int ibin = int((nx-1) * ((double)ri/(double)RAND_MAX)) + 1; 00713 int rj = ::rand(); 00714 int jbin = int((ny-1) * ((double)rj/(double)RAND_MAX)) + 1; 00715 int offset = ibin + jbin * data.m_axes[1].m_offset; 00716 data.m_bin_entries[offset]++; 00717 } 00718 } else if(allEntries>int(fEntries)) { //FIXME 00719 a_buffer.out() << "inlib::rroot::TH2F::stream : " 00720 << " WARNING : can't reemulate number of entries per bin " 00721 << " for histo with title " << sout(data.m_title) << " :" 00722 << std::endl 00723 << " read fEntries (a double) is " << fEntries 00724 << " whilst corrected bin entries is " << allEntries 00725 << " (diff is " << (allEntries-int(fEntries)) << ")." 00726 << std::endl; 00727 } else { 00728 } 00729 } 00730 00731 if(!a_buffer.check_byte_count(s,c,"TH2F")) return 0; 00732 00733 inlib::histo::h2d* h = new inlib::histo::h2d("",10,0,1,10,0,1); 00734 h->copy_from_data(data); 00735 h->update_fast_getters(); 00736 // We have now a valid HCL histogram. 00737 00738 return h; 00739 } 00740 00741 inline const std::string& TH2D_cls(){ 00742 static const std::string s_v("TH2D"); 00743 return s_v; 00744 } 00745 00746 inline inlib::histo::h2d* TH2D_stream(buffer& a_buffer,bool a_profile = false){ 00747 unsigned int s, c; 00748 short v; 00749 if(!a_buffer.read_version(v,s,c)) return 0; 00750 00751 //printf("debug : BatchLab::Rio::TH2D::stream : version %d\n",v); 00752 00753 // Version 3 streaming (ROOT/v3-00-6). 00754 00755 // Now we have to reconstruct a valid Histogram from a_buffer : 00756 hd_data data; 00757 00758 data.m_dimension = 2; 00759 //data.m_coords.resize(data.m_dimension,0); 00760 //data.m_ints.resize(data.m_dimension,0); 00761 data.m_axes.resize(2); 00762 00763 double fEntries; 00764 double fSw; 00765 if(!TH_read_2D(a_buffer,data,fEntries,fSw)) return 0; 00766 00767 std::vector<double> bins; //fArray TArrayD 00768 if(!Array_stream<double>(a_buffer,bins)) return 0; 00769 00770 //printf("debug : BatchLab::Rio::TH2D::stream : histo bins %d\n",n); 00771 unsigned int binn = data.m_bin_number; 00772 data.m_bin_Sw.resize(binn,0); 00773 double asw = 0; 00774 {for(unsigned int index=0;index<binn;index++){ 00775 double h = bins[index]; 00776 data.m_bin_Sw[index] = h; 00777 asw += h; 00778 }} 00779 if(!a_profile) { 00780 double sw = data.get_Sw(); 00781 if(!null_epsil(sw,fSw)) { 00782 a_buffer.out() << "inlib::rroot::TH2D::stream : " 00783 << " WARNING : inconsistent total weight" 00784 << " for histo with title " << sout(data.m_title) << " :" 00785 << std::endl 00786 << " read fSw is " << fSw 00787 << " whilst sum of in-range bins weight is " << sw 00788 << " (diff is " << (sw-fSw) << ")." 00789 << std::endl; 00790 } 00791 } 00792 00793 // Fill Sxw and Sx2w by using in range bins : 00794 std::vector<double> empty; 00795 empty.resize(2,0); 00796 data.m_bin_Sxw.resize(binn,empty); 00797 data.m_bin_Sx2w.resize(binn,empty); 00798 std::vector<int> is(data.m_dimension); 00799 for(unsigned int index=0;index<binn;index++){ 00800 if(!data.is_out(index)) { 00801 double height = bins[index]; 00802 data.get_indices(index,is); 00803 for(unsigned int iaxis=0;iaxis<data.m_dimension;iaxis++) { 00804 double x = data.m_axes[iaxis].bin_center(is[iaxis]); 00805 data.m_bin_Sxw[index][iaxis] = x * height; 00806 data.m_bin_Sx2w[index][iaxis] = x * x * height; 00807 } 00808 } 00809 } 00810 00811 //ROOT does not store the number of entries per bin. 00812 // We have the global number of entries and weight ; with that 00813 // we do our best.... 00814 data.m_bin_entries.resize(binn,0); 00815 if(!a_profile && asw) { 00816 for(unsigned int index=0;index<binn;index++){ 00817 double height = bins[index]; 00818 int number = (int)((fEntries * height) / asw); 00819 if(number<0) { 00820 } else { 00821 data.m_bin_entries[index] = number; 00822 } 00823 } 00824 int allEntries = data.get_all_entries(); 00825 if(allEntries<(int)fEntries) { //FIXME 00826 //Correct some bins randomly (beurk, do you have a better idea ?) : 00827 int diff = int(fEntries-allEntries); 00828 unsigned int nx = data.m_axes[0].m_number_of_bins; 00829 unsigned int ny = data.m_axes[1].m_number_of_bins; 00830 for(int i=0;i<diff;i++) { 00831 int ri = ::rand(); 00832 int ibin = int((nx-1) * ((double)ri/(double)RAND_MAX)) + 1; 00833 int rj = ::rand(); 00834 int jbin = int((ny-1) * ((double)rj/(double)RAND_MAX)) + 1; 00835 int offset = ibin + jbin * data.m_axes[1].m_offset; 00836 data.m_bin_entries[offset]++; 00837 } 00838 } else if(allEntries>int(fEntries)) { //FIXME 00839 a_buffer.out() << "inlib::rroot::TH2D::stream : " 00840 << " WARNING : can't reemulate number of entries per bin " 00841 << " for histo with title " << sout(data.m_title) << " :" 00842 << std::endl 00843 << " read fEntries (a double) is " << fEntries 00844 << " whilst corrected bin entries is " << allEntries 00845 << " (diff is " << (allEntries-int(fEntries)) << ")." 00846 << std::endl; 00847 } else { 00848 } 00849 } 00850 00851 if(!a_buffer.check_byte_count(s,c,"TH2D")) return 0; 00852 00853 inlib::histo::h2d* h = new inlib::histo::h2d("",10,0,1,10,0,1); 00854 h->copy_from_data(data); 00855 h->update_fast_getters(); 00856 // We have now a valid HCL histogram. 00857 00858 return h; 00859 } 00860 00861 inline const std::string& TProfile_cls(){ 00862 static const std::string s_v("TProfile"); 00863 return s_v; 00864 } 00865 00866 inline inlib::histo::p1d* TProfile_stream(buffer& a_buffer){ 00867 unsigned int s, c; 00868 short v; 00869 if(!a_buffer.read_version(v,s,c)) return 0; 00870 00871 // Version 3 streaming (ROOT/v3-00-6). 00872 00873 //WARNING : the mapping inlib::histo::p1d / TProfile is not obvious. 00874 //HCL::m_bin_Svw <---> TProfile::fArray 00875 //HCL::m_bin_Sv2w <---> TProfile::fSumw2 00876 //HCL::m_bin_Sw <---> TProfile::fBinEntries 00877 00878 00879 inlib::histo::h1d* h = TH1D_stream(a_buffer,true); 00880 if(!h) return 0; 00881 00882 //NOTE : histo.m_bin_Sw <---> TH1D::TArrayD::fArray 00883 00884 //WARNING : should have a valid Rio::TH1D::fHistogram 00885 // being a inlib::histo::h1d. 00886 // But the inlib::histo::p1d does not inherit inlib::histo::h1d. 00887 00888 pd_data data(h->get_histo_data()); 00889 delete h; 00890 00891 std::vector<double> bins; //fBinEntries TArrayD 00892 if(!Array_stream<double>(a_buffer,bins)) return 0; 00893 int errorMode; 00894 if(!a_buffer.read(errorMode)) return 0; 00895 double ymin; 00896 if(!a_buffer.read(ymin)) return 0; 00897 double ymax; 00898 if(!a_buffer.read(ymax)) return 0; 00899 00900 if(v>=4) { 00901 double sumwy; 00902 if(!a_buffer.read(sumwy)) return 0; 00903 double sumwy2; 00904 if(!a_buffer.read(sumwy2)) return 0; 00905 std::vector<double> bins_sumw2; //fBinSumw2 TArrayD 00906 if(!Array_stream<double>(a_buffer,bins_sumw2)) return 0; 00907 } 00908 00909 data.m_is_profile = true; 00910 data.m_cut_v = true; 00911 data.m_min_v = ymin; 00912 data.m_max_v = ymax; 00913 00914 unsigned int binn = data.m_bin_number; 00915 data.m_bin_Svw.resize(binn,0); 00916 data.m_bin_Sv2w.resize(binn,0); 00917 00918 for(unsigned int index=0;index<binn;index++){ 00919 double svw = data.m_bin_Sw[index]; 00920 double sw = bins[index]; 00921 data.m_bin_entries[index] = (int)sw; //FIXME : ok for w = 1 only ! 00922 data.m_bin_Sw[index] = (double)sw; 00923 //FIXME : data.m_bin_Sxw 00924 //FIXME : data.m_bin_Sx2w 00925 data.m_bin_Svw[index] = svw; 00926 data.m_bin_Sv2w[index] = 0; //FIXME 00927 } 00928 00929 if(!a_buffer.check_byte_count(s,c,"TProfile")) return 0; 00930 00931 inlib::histo::p1d* p = new inlib::histo::p1d("",10,0,1); 00932 p->copy_from_data(data); 00933 p->update_fast_getters(); 00934 // We have now a valid inlib::histo::p1d. 00935 return p; 00936 } 00937 00938 class TDirectory : public inlib::rroot::directory { 00939 public: 00940 static const std::string& store_class() { 00941 static const std::string s_v("TDirectory"); 00942 return s_v; 00943 } 00944 public: 00945 TDirectory(ifile& a_file) 00946 :inlib::rroot::directory(a_file) 00947 {} 00948 virtual ~TDirectory(){} 00949 protected: 00950 TDirectory(const TDirectory& a_from) 00951 : inlib::rroot::directory(a_from) 00952 {} 00953 TDirectory& operator=(const TDirectory&){return *this;} 00954 public: 00955 bool stream(buffer& a_buffer){ 00956 initialize(); 00957 short version; 00958 if(!a_buffer.read_version(version)) return false; 00959 unsigned int date; 00960 if(!a_buffer.read(date)) return false; 00961 //m_date_C.setDate(date); 00962 if(!a_buffer.read(date)) return false; 00963 //m_date_M.setDate(date); 00964 if(!a_buffer.read(m_nbytes_keys)) return false; 00965 if(!a_buffer.read(m_nbytes_name)) return false; 00966 if(version>1000) { 00967 if(!a_buffer.read(m_seek_directory)) return false; 00968 if(!a_buffer.read(m_seek_parent)) return false; 00969 if(!a_buffer.read(m_seek_keys)) return false; 00970 } else { 00971 {seek32 i; 00972 if(!a_buffer.read(i)) return false; 00973 m_seek_directory = i;} 00974 00975 {seek32 i; 00976 if(!a_buffer.read(i)) return false; 00977 m_seek_parent = i;} 00978 00979 {seek32 i; 00980 if(!a_buffer.read(i)) return false; 00981 m_seek_keys = i;} 00982 } 00983 //short v = version%1000; 00984 00985 if (m_seek_keys) { 00986 uint32 n; 00987 if(!read_keys(n)) { 00988 a_buffer.out() << "inlib::rroot::TDirectory::stream :" 00989 << " cannot read keys." 00990 << std::endl; 00991 return false; 00992 } 00993 } 00994 00995 return true; 00996 } 00997 protected: 00998 void initialize(){ 00999 // Initialise directory to defaults : 01000 // If directory is created via default ctor (when dir is read from file) 01001 // don't add it here to the directory since its name is not yet known. 01002 // It will be added to the directory in TKey::ReadObj(). 01003 m_date_C = 0;//m_date_C.set(); 01004 m_date_M = 0;//m_date_M.set(); 01005 m_nbytes_keys = 0; 01006 m_seek_directory = 0; 01007 m_seek_parent = 0; 01008 m_seek_keys = 0; 01009 } 01010 }; 01011 01012 01013 inline void dump(std::ostream& a_out, 01014 inlib::rroot::ifile& a_file, 01015 const std::vector<inlib::rroot::key*>& a_keys, 01016 bool a_recursive, 01017 unsigned int a_spaces = 0) { 01018 01019 // dump non directory objects : 01020 {std::vector<inlib::rroot::key*>::const_iterator it; 01021 for(it=a_keys.begin();it!=a_keys.end();++it) { 01022 inlib::rroot::key& k = *(*it); 01023 if(k.object_class()==inlib::rroot::TDirectory::store_class()) continue; 01024 {for(unsigned index=0;index<a_spaces;index++) a_out << " ";} 01025 k.dump(a_out); 01026 }} 01027 01028 // dump directories : 01029 {std::vector<inlib::rroot::key*>::const_iterator it; 01030 for(it=a_keys.begin();it!=a_keys.end();++it) { 01031 inlib::rroot::key& k = *(*it); 01032 if(k.object_class()!=inlib::rroot::TDirectory::store_class()) continue; 01033 01034 std::string label = k.object_name(); 01035 {for(unsigned index=0;index<a_spaces;index++) a_out << " ";} 01036 a_out << "directory : " << label << std::endl; 01037 01038 if(!a_recursive) continue; 01039 01040 uint32 sz; 01041 char* buf = k.get_object_buffer(sz); 01042 //we don't have ownership of buf. 01043 if(!buf) { 01044 a_out << "inlib::rroot::dump :" 01045 << " can't get directory data buffer." 01046 << std::endl; 01047 } else { 01048 inlib::rroot::buffer b(a_out,a_file.byte_swap(), 01049 sz,buf,k.key_length(),false); 01050 inlib::rroot::TDirectory tdir(a_file); 01051 if(!tdir.stream(b)) { 01052 a_out << "inlib::rroot::dump :" 01053 << " can't stream TDirectory." 01054 << std::endl; 01055 } else { 01056 const std::vector<inlib::rroot::key*>& keys = tdir.keys(); 01057 dump(a_out,a_file,keys,a_recursive,a_spaces+1); 01058 } 01059 } 01060 }} 01061 } 01062 01063 }} 01064 01065 #endif