histos and ntuples in a CERN-ROOT file

With the inlib/wroot classes you can write histograms and ntuples in a file at the CERN-ROOT format. Here an "ntuple" is understood as a "flat TTree". With inlib/rroot classes you can read this kind of file. And if the zip compression is used, the exlib/rroot code permits to read "zip compressed" files. You can have a writing example with :

    cd <path to inlib>
    cd examples/cpp
    c++ -I../.. wroot.cpp
    ./a.out

The program produces the out.root file that you can read with :

    <source setup CERN-ROOT> # in order to have root-config in your PATH.
    root ./rroot.C

You should see something as :

inlib_exa_rroot_C.png

You can also dump the list of "TKeys" of out.root by using the exlib/example/cpp/rroot.cpp program :

    cd <path to exlib>
    cd examples/cpp
    ./build rroot.cpp
    ./exlib_example_rroot -ls ../../../inlib/examples/cpp/out.root

You should see something as :

exlib_exa_rroot.png

rpawdemo.cpp

The rpawdemo.cpp program permits to read and dump an histo from the pawdemo.root file that can be found in the download area under : http://inexlib.lal.in2p3.fr/download/data/root

    cd <path to inlib>
    cd examples/cpp
    ./build rpawdemo.cpp
    <get the pawdemo.root file>
    ./inlib_example_rpawdemo

You should see something as :

inlib_exa_rpawdemo.png

wroot.cpp, rroot.cpp, rpawdemo.cpp

wroot.cpp

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file exlib.license for terms.

//  This program produces a out.root file.
//
//  See rroot.C for an example of how to manipulate
// (and check !) the content of this file with CERN-ROOT.

#ifdef INLIB_MEM
#include <inlib/mem>
#endif //INLIB_MEM

#include <inlib/wroot/file>
#include <inlib/wroot/to>

#include <inlib/histo/h1d>
#include <inlib/histo/h2d>
#include <inlib/histo/p1d>
#include <inlib/wroot/ntuple>

#include <inlib/random>
#include <inlib/randf>

#define HAS_EXLIB
#ifdef HAS_EXLIB
#include <exlib/wroot/zip>
#endif

#include <inlib/args>
#include <iostream>

int main(int argc,char** argv) {

#ifdef INLIB_MEM
  inlib::mem::set_check_by_class(true);{
#endif //INLIB_MEM
  inlib::args args(argc,argv);

  //////////////////////////////////////////////////////////
  /// create a .root file : ////////////////////////////////
  //////////////////////////////////////////////////////////
  std::string file = "out.root";
  inlib::wroot::file rfile(std::cout,file);
#ifdef HAS_EXLIB
  rfile.add_ziper('Z',exlib::wroot::zip);
  rfile.set_compression(9);
#endif

  inlib::wroot::directory* dir = rfile.dir().mkdir("histo");
  if(!dir) {
    std::cout << "can't create diectory." << std::endl;
    return EXIT_FAILURE;
  }

  //inlib::wroot::directory* dxxx = dir->mkdir("xxx");
  //if(!dxxx) {
  //  std::cout << "can't create diectory." << std::endl;
  //  return EXIT_FAILURE;
  //}

  //////////////////////////////////////////////////////////
  /// create some histos : /////////////////////////////////
  //////////////////////////////////////////////////////////

  unsigned int entries = 1000000;

  inlib::random::gauss rg(1,2);
  inlib::random::bw rbw(0,1);

 {inlib::histo::h1d h("Gauss",100,-5,5);
  for(unsigned int count=0;count<entries;count++) {
    h.fill(rg.shoot(),1.4);
  }
  if(!inlib::wroot::to(*dir,h,"rg")) return EXIT_FAILURE;}

 {inlib::histo::p1d h("Profile",100,-5,5,-2,2);
  for(unsigned int count=0;count<entries;count++) {
    h.fill(rg.shoot(),rbw.shoot(),1);
  }
  if(!inlib::wroot::to(*dir,h,"prof")) return EXIT_FAILURE;}

 {inlib::histo::h2d h("Gauss_BW",20,-5,5,20,-2,2);
  for(unsigned int count=0;count<entries;count++) {
    h.fill(rg.shoot(),rbw.shoot(),0.8);
  }
  if(!inlib::wroot::to(*dir,h,"rgbw")) return EXIT_FAILURE;}

  //////////////////////////////////////////////////////////
  /// create and fill a ntuple : ///////////////////////////
  //////////////////////////////////////////////////////////
 {//WARNING : the ntuple can't be on the stack. It is owned
  //          by the directory.
  inlib::wroot::ntuple* ntu = 
    new inlib::wroot::ntuple(rfile.dir(),"rg_rbw","Randoms");
  inlib::wroot::ntuple::column<int>* col_index =
    ntu->create_column<int>("index");
  inlib::wroot::ntuple::column<double>* col_rgauss =
    ntu->create_column<double>("rgauss");
  inlib::wroot::ntuple::column<float>* col_rbw =
    ntu->create_column<float>("rbw");

  if(args.is_arg("-large")){
    entries = 400000000; //to test >2Gbytes file.
    ntu->set_basket_size(1000000);
  }

  inlib::randf::bw rbw(0,1);
  for(unsigned int count=0;count<entries;count++) {    
    col_index->fill(count);
    col_rgauss->fill(rg.shoot());
    col_rbw->fill(rbw.shoot());
    if(!ntu->add_row()) {
      std::cout << "ntuple fill failed." << std::endl;
      break;
    }
  }}

  //////////////////////////////////////////////////////////
  /// write and close file : ///////////////////////////////
  //////////////////////////////////////////////////////////
 {unsigned int n;
  if(!rfile.write(n)) {
    std::cout << "file write failed." << std::endl;
  }}
  
  rfile.close();

  //////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////

#ifdef INLIB_MEM
  }inlib::mem::balance(std::cout);
#endif //INLIB_MEM

  return EXIT_SUCCESS;
}

rroot.cpp

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file exlib.license for terms.


#include <inlib/mem>

#include <inlib/args>
#include <inlib/file>

#include <inlib/rroot/file>
#include <inlib/rroot/rall>

#include <exlib/rroot/unzip>

#include <iostream>

int main(int argc,char** argv) {

#ifdef INLIB_MEM
  inlib::mem::set_check_by_class(true);{
#endif

  inlib::args args(argc,argv);

  std::string file;
  if(!args.file(file)) {
    std::cout << " give a root file." << std::endl;
    return EXIT_FAILURE;
  }

  bool verbose = args.is_arg("-verbose");
  bool ls = args.is_arg("-ls");
  bool dump = args.is_arg("-dump");

 {bool is;
  inlib::file::is_root(file,is);
  if(!is) {
    std::cout << " file is not a root file." << std::endl;
    return EXIT_FAILURE;
  }}

  inlib::rroot::file rfile(std::cout,file,verbose);
  rfile.add_unziper('Z',exlib::rroot::unzip);

  if(ls) {
    std::cout << "format version " << rfile.version() << std::endl;
  }
      
  const std::vector<inlib::rroot::key*>& keys = rfile.dir().keys();
  inlib::rroot::read(std::cout,rfile,keys,true,ls,dump,0);

#ifdef INLIB_MEM
  }inlib::mem::balance(std::cout);
#endif

  return EXIT_SUCCESS;
}

rpawdemo.cpp

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file inlib.license for terms.

#include <inlib/mem>

#include <inlib/args>
#include <inlib/rroot/file>
#include <inlib/rroot/streamers>

#include <iostream>

int main(int argc,char** argv) {

#ifdef INLIB_MEM
  inlib::mem::set_check_by_class(true);{
#endif

  inlib::args args(argc,argv);

  bool verbose = args.is_arg("-verbose");

  std::string file = "pawdemo.root";
  inlib::rroot::file rfile(std::cout,file,verbose);

  inlib::rroot::key* key = rfile.dir().find_key("h10");
  if(!key) {
    std::cout << "key for h10 not found." << std::endl;
    return EXIT_FAILURE;
  }
  unsigned int sz;
  char* buf = key->get_object_buffer(sz);
  if(!buf) {
    std::cout << "can't get data buffer for h10." << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "size of h10 : " << sz << std::endl;

  inlib::rroot::buffer b(std::cout,rfile.byte_swap(),
                         sz,buf,key->key_length(),verbose);
  inlib::histo::h1d* h = inlib::rroot::TH1F_stream(b); //we get ownership on h.
  if(!h) {
    std::cout << "streaming failed for h10." << std::endl;
    return EXIT_FAILURE;
  }

  h->hprint(std::cout);

  delete h;
  
#ifdef INLIB_MEM
  }inlib::mem::balance(std::cout);
#endif

  return EXIT_SUCCESS;
}