// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_rroot_streamers #define tools_rroot_streamers #include "named" #include "date" #include "directory" #include "graph" #include "clss" #include "info" #include "dummy" #include "list" #include "iros" #include "../sout" #include "../vmanip" //#include "../histo/histo_data" #include "../histo/profile_data" #include "../histo/h1d" #include "../histo/h2d" #include "../histo/h3d" #include "../histo/p1d" #include "../histo/p2d" #include #include //::log10, ::fabs. //#include "../rtausmed" namespace tools { namespace rroot { typedef histo::histo_data hd_data; typedef histo::profile_data pd_data; inline bool AttAxis_stream(buffer& a_buffer){ int fNdivisions = 510; //Number of divisions(10000*n3 + 100*n2 + n1) short fAxisColor = 1; //color of the line axis short fLabelColor = 1; //color of labels short fLabelFont = 62; //font for labels float fLabelOffset = 0.005F; //offset of labels float fLabelSize = 0.04F; //size of labels float fTickLength = 0.03F; //length of tick marks float fTitleOffset = 1; //offset of axis title float fTitleSize = 0.04F; //size of axis title short fTitleColor = 1; //color of axis title short fTitleFont = 62; //font for axis title // Version 4 streaming (ROOT/v3-00-6). short v; unsigned int s, c; if(!a_buffer.read_version(v,s,c)) return false; if(!a_buffer.read(fNdivisions)) return false; if(!a_buffer.read(fAxisColor)) return false; if(!a_buffer.read(fLabelColor)) return false; if(!a_buffer.read(fLabelFont)) return false; if(!a_buffer.read(fLabelOffset)) return false; if(!a_buffer.read(fLabelSize)) return false; if(!a_buffer.read(fTickLength)) return false; if(!a_buffer.read(fTitleOffset)) return false; if(!a_buffer.read(fTitleSize)) return false; if(!a_buffer.read(fTitleColor)) return false; if(!a_buffer.read(fTitleFont)) return false; if(!a_buffer.check_byte_count(s, c,"TAttAxis")) return false; return true; } class dummy_fac : public virtual ifac { public: //ifac virtual iro* create(const std::string& a_class,const args& a_args) { if(rcmp(a_class,"TGraph")) { //for TH_read_1D/List. return new graph(); // for read_sinfos() : } else if(rcmp(a_class,"TStreamerInfo")) { return new StreamerInfo(*this); } else if(rcmp(a_class,"TObjArray")) { std::string* sc = ifac::arg_class(a_args); if(sc) { if((*sc)==streamer_element::s_class()){ return new obj_array(*this,true,true); } else { m_out << "tools::rroot::dummy_fac::create :" << " Can't create TObjArray of " << *sc << "." << std::endl; return 0; } } else { return new iros(*this,true,true); } } else if(rcmp(a_class,"TStreamerBase") ||rcmp(a_class,"TStreamerBasicType") ||rcmp(a_class,"TStreamerBasicPointer") ||rcmp(a_class,"TStreamerObjectAny") ||rcmp(a_class,"TStreamerObject") ||rcmp(a_class,"TStreamerObjectPointer") ||rcmp(a_class,"TStreamerString") ||rcmp(a_class,"TStreamerSTL") ||rcmp(a_class,"TStreamerLoop") ||rcmp(a_class,"TList") ) { return new dummy_streamer_element(); } else { m_out << "tools::rroot::dummy_fac::create :" << " dummy. Can't create object of class " << sout(a_class) << "." << std::endl; } return 0; } virtual void destroy(iro*& a_obj) {delete a_obj;a_obj = 0;} public: dummy_fac(std::ostream& a_out):m_out(a_out){} virtual ~dummy_fac(){} protected: dummy_fac(const dummy_fac& a_from): ifac(a_from),m_out(a_from.m_out){} dummy_fac& operator=(const dummy_fac&){return *this;} protected: std::ostream& m_out; }; inline bool Axis_stream(buffer& a_buffer,histo::axis& a_fAxis){ // Version 6 streaming (ROOT/v3-00-6). short v; unsigned int s, c; if(!a_buffer.read_version(v,s,c)) return false; std::string name; std::string title; if(!Named_stream(a_buffer,name,title)) return false; if(!AttAxis_stream(a_buffer)) return false; int number; if(!a_buffer.read(number)) return false; double min; if(!a_buffer.read(min)) return false; double max; if(!a_buffer.read(max)) return false; //::printf("debug : BatchLab::RioTH::streamTAxis : %d %g %g\n", // number,min,max); std::vector edges; if(!Array_stream(a_buffer,edges)) return false; //fXbins TArrayD size_t edgen = edges.size(); if(!edgen) { a_fAxis.configure(number,min,max); } else { std::vector vedges; for(size_t index=0;index=8) { //fBits2. unsigned short dummy; if(!a_buffer.read(dummy)) return false; } //Bool_t unsigned char TimeDisplay; if(!a_buffer.read(TimeDisplay)) return false; //TString std::string TimeFormat; if(!a_buffer.read(TimeFormat)) return false; if(v>=7) { //THashList* dummy_fac fac(a_buffer.out()); if(!dummy_TXxx_pointer_stream(a_buffer,fac)) return false; } if(!a_buffer.check_byte_count(s,c,"TAxis")) return false; return true; } inline bool null_epsil(double a_1,double a_2,double a_prec = -5) { return (::log10(::fabs(a_1-a_2)) dummy; if(!Axis_stream(a_buffer,dummy)) return false; //fZAxis } else { histo::axis dummy; if(!Axis_stream(a_buffer,dummy)) return false; //fYAxis if(!Axis_stream(a_buffer,dummy)) return false; //fZAxis } short barOffset; if(!a_buffer.read(barOffset)) return false; short barWidth; if(!a_buffer.read(barWidth)) return false; if(!a_buffer.read(a_entries)) return false; if(!a_buffer.read(a_Sw)) return false; //fTsumw //::printf("debug : BatchLab::Rio::TH::streamTH1 : \"%s\" %g %g\n", // a_data.m_title.c_str(),fEntries,fSw); if(!a_buffer.read(a_Sw2)) return false; if(!a_buffer.read(a_Sxw)) return false; if(!a_buffer.read(a_Sx2w)) return false; double max; if(!a_buffer.read(max)) return false; double min; if(!a_buffer.read(min)) return false; double NormFactor; if(!a_buffer.read(NormFactor)) return false; {std::vector v; if(!Array_stream(a_buffer,v)) return false;} //fContour TArrayD std::vector sumw2; //fSumw2 TArrayD if(!Array_stream(a_buffer,sumw2)) return false; {std::string opt; if(!a_buffer.read(opt)) return false; //TString fOption //look if it is an "annotation trick" : //if(opt.size()&&(opt[0]==0)) { // fAnnotation = opt.substr(1,opt.size()-1); //} } {dummy_fac fac(a_buffer.out()); obj_list dummy(fac,true,true); if(!dummy.stream(a_buffer)) { a_buffer.out() << "tools::rroot::TH_read_1D :" << " obj_list stream failed." << std::endl; return false; }} //Functions if(vers>=4) { int BufferSize; if(!a_buffer.read(BufferSize)) return false; //Double_t* Buffer; //[fBufferSize] if(!dummy_array_stream(a_buffer,BufferSize)) return false; } if(vers>=7) { //EBinErrorOpt fBinStatErrOpt; int dummy; if(!a_buffer.read(dummy)) return false; } // Add two for outflows. if(a_data.m_dimension==1) { a_data.m_bin_number = a_data.m_axes[0].m_number_of_bins + 2; } else if(a_data.m_dimension==2) { a_data.m_bin_number = (a_data.m_axes[0].m_number_of_bins + 2) * (a_data.m_axes[1].m_number_of_bins + 2); } else if(a_data.m_dimension==3) { a_data.m_bin_number = (a_data.m_axes[0].m_number_of_bins + 2) * (a_data.m_axes[1].m_number_of_bins + 2) * (a_data.m_axes[2].m_number_of_bins + 2); } unsigned int binn = a_data.m_bin_number; a_data.m_bin_Sw2.resize(binn); if(binn==sumw2.size()) { for(unsigned int index=0;index bins; //fArray TArrayF if(!Array_stream(a_buffer,bins)) return 0; if(!a_buffer.check_byte_count(s,c,"TH1F")) return 0; unsigned int binn = data.m_bin_number; //::printf("debug : BatchLab::Rio::TH1F::stream : histo bins %d\n",binn); data.m_bin_Sw.resize(binn,0); {for(unsigned int index=0;index empty; empty.resize(1,0); data.m_bin_Sxw.resize(binn,empty); data.m_bin_Sx2w.resize(binn,empty);} data.m_all_entries = static_cast(fEntries); data.m_in_range_entries = 0; data.m_in_range_Sw = fSw; data.m_in_range_Sw2 = fSw2; data.m_in_range_Sxw.resize(1,0); data.m_in_range_Sx2w.resize(1,0); data.m_in_range_Sxw[0] = fSxw; data.m_in_range_Sx2w[0] = fSx2w; histo::h1d* h = new histo::h1d("",10,0,1); h->copy_from_data(data); return h; //give ownership to caller. } inline histo::h1d* TH1D_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; //::printf("debug : BatchLab::Rio::TH1D::stream : version %d\n",v); // Version 1 streaming (ROOT/v3-00-6). // Now we have to reconstruct a valid Histogram from a_buffer : hd_data data; data.m_dimension = 1; data.m_axes.resize(1); double fEntries; //in range + outflow. double fSw; //in range. double fSw2; //in range. double fSxw; //in range. double fSx2w; //in range. if(!TH_read_1D(a_buffer,data,fEntries,fSw,fSw2,fSxw,fSx2w)) return 0; // the upper set : //data.m_title //data.m_bin_number //data.m_axes //data.m_bin_Sw2 std::vector bins; //fArray TArrayD if(!Array_stream(a_buffer,bins)) return 0; if(!a_buffer.check_byte_count(s,c,"TH1D")) return 0; unsigned int binn = data.m_bin_number; data.m_bin_Sw = bins; data.m_bin_entries.resize(binn,0); {std::vector empty; empty.resize(1,0); data.m_bin_Sxw.resize(binn,empty); data.m_bin_Sx2w.resize(binn,empty);} data.m_all_entries = static_cast(fEntries); data.m_in_range_entries = 0; data.m_in_range_Sw = fSw; data.m_in_range_Sw2 = fSw2; data.m_in_range_Sxw.resize(1,0); data.m_in_range_Sx2w.resize(1,0); data.m_in_range_Sxw[0] = fSxw; data.m_in_range_Sx2w[0] = fSx2w; histo::h1d* h = new histo::h1d("",10,0,1); h->copy_from_data(data); return h; } inline histo::h2d* TH2F_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; //::printf("debug : BatchLab::Rio::TH2F::stream : version %d\n",v); // Version 3 streaming (ROOT/v3-00-6). // Now we have to reconstruct a valid Histogram from a_buffer : hd_data data; data.m_dimension = 2; //data.m_coords.resize(data.m_dimension,0); //data.m_ints.resize(data.m_dimension,0); data.m_axes.resize(2); data.m_in_range_plane_Sxyw.resize(1,0); double fEntries; //in range + outflow. double fSw; //in range. double fSw2; //in range. double fSxw; //in range. double fSx2w; //in range. double fSyw; //in range. double fSy2w; //in range. if(!TH_read_2D(a_buffer,data,fEntries,fSw,fSw2,fSxw,fSx2w,fSyw,fSy2w)) return 0; // the upper set : //data.m_title //data.m_bin_number //data.m_axes //data.m_bin_Sw2 std::vector bins; //fArray TArrayF if(!Array_stream(a_buffer,bins)) return 0; if(!a_buffer.check_byte_count(s,c,"TH2F")) return 0; unsigned int binn = data.m_bin_number; //::printf("debug : BatchLab::Rio::TH2F::stream : histo bins %d\n",binn); data.m_bin_Sw.resize(binn,0); {for(unsigned int index=0;index empty; empty.resize(2,0); data.m_bin_Sxw.resize(binn,empty); data.m_bin_Sx2w.resize(binn,empty);} data.m_all_entries = static_cast(fEntries); data.m_in_range_entries = 0; data.m_in_range_Sw = fSw; data.m_in_range_Sw2 = fSw2; data.m_in_range_Sxw.resize(2,0); data.m_in_range_Sx2w.resize(2,0); data.m_in_range_Sxw[0] = fSxw; data.m_in_range_Sx2w[0] = fSx2w; data.m_in_range_Sxw[1] = fSyw; data.m_in_range_Sx2w[1] = fSy2w; histo::h2d* h = new histo::h2d("",10,0,1,10,0,1); h->copy_from_data(data); return h; } inline histo::h2d* TH2D_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; //::printf("debug : BatchLab::Rio::TH2D::stream : version %d\n",v); // Version 3 streaming (ROOT/v3-00-6). // Now we have to reconstruct a valid Histogram from a_buffer : hd_data data; data.m_dimension = 2; //data.m_coords.resize(data.m_dimension,0); //data.m_ints.resize(data.m_dimension,0); data.m_axes.resize(2); data.m_in_range_plane_Sxyw.resize(1,0); double fEntries; //in range + outflow. double fSw; //in range. double fSw2; //in range. double fSxw; //in range. double fSx2w; //in range. double fSyw; //in range. double fSy2w; //in range. if(!TH_read_2D(a_buffer,data,fEntries,fSw,fSw2,fSxw,fSx2w,fSyw,fSy2w)) return 0; // the upper set : //data.m_title //data.m_bin_number //data.m_axes //data.m_bin_Sw2 std::vector bins; //fArray TArrayD if(!Array_stream(a_buffer,bins)) return 0; if(!a_buffer.check_byte_count(s,c,"TH2D")) return 0; unsigned int binn = data.m_bin_number; data.m_bin_Sw = bins; data.m_bin_entries.resize(binn,0); {std::vector empty; empty.resize(2,0); data.m_bin_Sxw.resize(binn,empty); data.m_bin_Sx2w.resize(binn,empty);} data.m_all_entries = static_cast(fEntries); data.m_in_range_entries = 0; data.m_in_range_Sw = fSw; data.m_in_range_Sw2 = fSw2; data.m_in_range_Sxw.resize(2,0); data.m_in_range_Sx2w.resize(2,0); data.m_in_range_Sxw[0] = fSxw; data.m_in_range_Sx2w[0] = fSx2w; data.m_in_range_Sxw[1] = fSyw; data.m_in_range_Sx2w[1] = fSy2w; histo::h2d* h = new histo::h2d("",10,0,1,10,0,1); h->copy_from_data(data); return h; } inline histo::h3d* TH3D_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; //::printf("debug : BatchLab::Rio::TH2D::stream : version %d\n",v); // Now we have to reconstruct a valid Histogram from a_buffer : hd_data data; data.m_dimension = 3; //data.m_coords.resize(data.m_dimension,0); //data.m_ints.resize(data.m_dimension,0); data.m_axes.resize(3); data.m_in_range_plane_Sxyw.resize(3,0); double fEntries; //in range + outflow. double fSw; //in range. double fSw2; //in range. double fSxw; //in range. double fSx2w; //in range. double fSyw; //in range. double fSy2w; //in range. double fSzw; //in range. double fSz2w; //in range. if(!TH_read_3D(a_buffer,data,fEntries,fSw,fSw2,fSxw,fSx2w,fSyw,fSy2w,fSzw,fSz2w)) return 0; // the upper set : //data.m_title //data.m_bin_number //data.m_axes //data.m_bin_Sw2 std::vector bins; //fArray TArrayD if(!Array_stream(a_buffer,bins)) return 0; if(!a_buffer.check_byte_count(s,c,"TH3D")) return 0; unsigned int binn = data.m_bin_number; data.m_bin_Sw = bins; data.m_bin_entries.resize(binn,0); {std::vector empty; empty.resize(3,0); data.m_bin_Sxw.resize(binn,empty); data.m_bin_Sx2w.resize(binn,empty);} data.m_all_entries = static_cast(fEntries); data.m_in_range_entries = 0; data.m_in_range_Sw = fSw; data.m_in_range_Sw2 = fSw2; data.m_in_range_Sxw.resize(3,0); data.m_in_range_Sx2w.resize(3,0); data.m_in_range_Sxw[0] = fSxw; data.m_in_range_Sx2w[0] = fSx2w; data.m_in_range_Sxw[1] = fSyw; data.m_in_range_Sx2w[1] = fSy2w; data.m_in_range_Sxw[2] = fSzw; data.m_in_range_Sx2w[2] = fSz2w; histo::h3d* h = new histo::h3d("",10,0,1,10,0,1,10,0,1); h->copy_from_data(data); return h; } inline histo::p1d* TProfile_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; // Version 3 streaming (ROOT/v3-00-6). //WARNING : the mapping histo::p1d / TProfile is not obvious. //p1d::m_bin_Svw <---> TProfile::fArray //p1d::m_bin_Sv2w <---> TProfile::fSumw2 //p1d::m_bin_Sw <---> TProfile::fBinEntries histo::h1d* h = TH1D_stream(a_buffer); if(!h) return 0; //NOTE : histo.m_bin_Sw <---> TH1D::TArrayD::fArray pd_data data(h->dac()); delete h; std::vector bins; //fBinEntries TArrayD if(!Array_stream(a_buffer,bins)) return 0; int errorMode; if(!a_buffer.read(errorMode)) return 0; double ymin; if(!a_buffer.read(ymin)) return 0; double ymax; if(!a_buffer.read(ymax)) return 0; if(v>=4) { double sumwy; if(!a_buffer.read(sumwy)) return 0; double sumwy2; if(!a_buffer.read(sumwy2)) return 0; } if(v>=5) { std::vector bins_sumw2; //fBinSumw2 TArrayD if(!Array_stream(a_buffer,bins_sumw2)) return 0; } if(!a_buffer.check_byte_count(s,c,"TProfile")) return 0; data.m_is_profile = true; data.m_cut_v = true; data.m_min_v = ymin; data.m_max_v = ymax; unsigned int binn = data.m_bin_number; data.m_bin_Svw.resize(binn); data.m_bin_Sv2w.resize(binn); for(unsigned int index=0;indexcopy_from_data(data); // We have now a valid histo::p1d. return p; } inline histo::p2d* TProfile2D_stream(buffer& a_buffer){ unsigned int s, c; short v; if(!a_buffer.read_version(v,s,c)) return 0; // Version 3 streaming (ROOT/v3-00-6). //WARNING : the mapping histo::p1d / TProfile is not obvious. //p1d::m_bin_Svw <---> TProfile::fArray //p1d::m_bin_Sv2w <---> TProfile::fSumw2 //p1d::m_bin_Sw <---> TProfile::fBinEntries histo::h2d* h = TH2D_stream(a_buffer); if(!h) return 0; //NOTE : histo.m_bin_Sw <---> TH2D::TArrayD::fArray pd_data data(h->dac()); delete h; std::vector bins; //fBinEntries TArrayD if(!Array_stream(a_buffer,bins)) return 0; int errorMode; if(!a_buffer.read(errorMode)) return 0; double zmin; if(!a_buffer.read(zmin)) return 0; double zmax; if(!a_buffer.read(zmax)) return 0; if(v>=5) { double sumwz; if(!a_buffer.read(sumwz)) return 0; double sumwz2; if(!a_buffer.read(sumwz2)) return 0; } if(v>=7) { std::vector bins_sumw2; //fBinSumw2 TArrayD if(!Array_stream(a_buffer,bins_sumw2)) return 0; } if(!a_buffer.check_byte_count(s,c,"TProfile2D")) return 0; data.m_is_profile = true; data.m_cut_v = true; data.m_min_v = zmin; data.m_max_v = zmax; unsigned int binn = data.m_bin_number; data.m_bin_Svw.resize(binn); data.m_bin_Sv2w.resize(binn); for(unsigned int index=0;indexcopy_from_data(data); return p; } class TDirectory : public rroot::directory { //public: // static const std::string& store_class() {return TDirectory_cls();} public: TDirectory(ifile& a_file):rroot::directory(a_file){} virtual ~TDirectory(){} protected: TDirectory(const TDirectory& a_from):rroot::directory(a_from){} TDirectory& operator=(const TDirectory&){return *this;} public: bool stream(buffer& a_buffer){ initialize(); short version; if(!a_buffer.read_version(version)) return false; unsigned int _date; if(!a_buffer.read(_date)) return false; //m_date_C.setDate(_date); if(!a_buffer.read(_date)) return false; //m_date_M.setDate(_date); if(!a_buffer.read(m_nbytes_keys)) return false; if(!a_buffer.read(m_nbytes_name)) return false; if((uint32)version>big_file_version_tag()) { if(!a_buffer.read(m_seek_directory)) return false; if(!a_buffer.read(m_seek_parent)) return false; if(!a_buffer.read(m_seek_keys)) return false; } else { {seek32 i; if(!a_buffer.read(i)) return false; m_seek_directory = i;} {seek32 i; if(!a_buffer.read(i)) return false; m_seek_parent = i;} {seek32 i; if(!a_buffer.read(i)) return false; m_seek_keys = i;} } //short v = version%big_file_version_tag(); if (m_seek_keys) { uint32 n; if(!read_keys(n)) { a_buffer.out() << "tools::rroot::TDirectory::stream :" << " cannot read keys." << std::endl; return false; } } return true; } protected: void initialize(){ // Initialise directory to defaults : // If directory is created via default ctor (when dir is read from file) // don't add it here to the directory since its name is not yet known. // It will be added to the directory in TKey::ReadObj(). m_date_C = 0;//m_date_C.set(); m_date_M = 0;//m_date_M.set(); m_nbytes_keys = 0; m_seek_directory = 0; m_seek_parent = 0; m_seek_keys = 0; } }; inline void dump(std::ostream& a_out, rroot::ifile& a_file, const std::vector& a_keys, bool a_recursive, unsigned int a_spaces = 0) { // dump non directory objects : {std::vector::const_iterator it; for(it=a_keys.begin();it!=a_keys.end();++it) { rroot::key& k = *(*it); if(k.object_class()==rroot::TDirectory_cls()) continue; {for(unsigned int index=0;index::const_iterator it; for(it=a_keys.begin();it!=a_keys.end();++it) { rroot::key& k = *(*it); if(k.object_class()!=rroot::TDirectory_cls()) continue; std::string label = k.object_name(); {for(unsigned int index=0;index& keys = tdir.keys(); dump(a_out,a_file,keys,a_recursive,a_spaces+1); } } }} } inline bool read_sinfos(rroot::ifile& a_file){ key& k = a_file.sinfos_key(); std::ostream& out = k.out(); if(k.object_class()!=rroot::TList_cls()) { out << "tools::rroot::read_sinfos :" << " key not a TList." << std::endl; return false; } unsigned int sz; char* buf = k.get_object_buffer(a_file,sz); //we don't have ownership of buf. if(!buf) { out << "tools::rroot::read_sinfos :" << " can't get data buffer of " << k.object_name() << "." << std::endl; return false; } rroot::buffer b(out,a_file.byte_swap(),sz,buf,k.key_length(),false); dummy_fac fac(out); obj_list infos(fac,true,true); if(!infos.stream(b)) return false; tools_vforcit(iro*,infos,it) { StreamerInfo* info = safe_cast(*(*it)); if(!info) return false; info->out(out); } return true; } }} #endif