1

I am trying to read a branch of TH1D objects in uproot4. A sample rootfile can be created with:

TFile * f = new TFile("new.root","RECREATE");
TTree * t = new TTree("mytree","mytree");

t->SetMakeClass(1); //See note later

TH1D * histo;
t->Branch("myhisto","TH1D",&histo);

for(int i=0;i<100;i++){
  t->GetEntry(i);
  histo = new TH1D(Form("histo_%d",i),Form("histo_%d",i),100,0,100);
  histo->Fill(i);
  t->Fill();
}

t->Print();
t->Write();

In uproot:

Python 3.8.6 (default, Jan 27 2021, 15:42:20) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.17.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import uproot

In [2]: uproot.__version__
Out[2]: '4.0.5'

In [3]: uproot.open("new.root:mytree/myhisto")
Out[3]: <TBranchElement 'myhisto' at 0x7f91da583e50>

In [4]: uproot.open("new.root:mytree/myhisto").interpretation
Out[4]: AsObjects(Model_TH1D)

However, when I try to read the array, it fails with a long Traceback. The last calls are:

~/.local/lib/python3.8/site-packages/uproot/model.py in read(cls, chunk, cursor, context, file, selffile, parent, concrete)
    798         )
    799 
--> 800         self.read_members(chunk, cursor, context, file)
    801 
    802         self.hook_after_read_members(

~/.local/lib/python3.8/site-packages/uproot/models/TArray.py in read_members(self, chunk, cursor, context, file)
     41             )
     42         self._members["fN"] = cursor.field(chunk, _tarray_format1, context)
---> 43         self._data = cursor.array(chunk, self._members["fN"], self.dtype, context)
     44 
     45     def __array__(self, *args, **kwargs):

~/.local/lib/python3.8/site-packages/uproot/source/cursor.py in array(self, chunk, length, dtype, context, move)
    308         if move:
    309             self._index = stop
--> 310         return numpy.frombuffer(chunk.get(start, stop, self, context), dtype=dtype)
    311 
    312     _u1 = numpy.dtype("u1")

~/.local/lib/python3.8/site-packages/uproot/source/chunk.py in get(self, start, stop, cursor, context)
    366 
    367         else:
--> 368             raise uproot.deserialization.DeserializationError(
    369                 """attempting to get bytes {0}:{1}
    370 outside expected range {2}:{3} for this Chunk""".format(

DeserializationError: while reading

    TH1D version 8 as uproot.dynamic.Model_TH1D_v3 (514 bytes)
        TH1 version 1 as uproot.dynamic.Model_TH1_v8 (18 bytes)
            (base): <TNamed '' at 0x7f91da38d430>
            (base): <TAttLine (version 2) at 0x7f91da38d700>
            (base): <TAttFill (version 2) at 0x7f91da38da30>
            (base): <TAttMarker (version 2) at 0x7f91da38dd90>
            fNcells: 0
            TAxis version 2 as uproot.dynamic.Model_TAxis_v10 (12 bytes)
                (base): <TNamed '' title='\x00\x00' at 0x7f91da398910>
                (base): <TAttAxis (version 4) at 0x7f91da398bb0>
                fNbins: 81920
                fXmin: 8.34406940932277e-309
                fXmax: 2.0000190735445362
                TArrayD version None as uproot.models.TArray.Model_TArrayD (? bytes)
                    fN: 81792
                    TH1D version 8 as uproot.dynamic.Model_TH1D_v3 (514 bytes)
                        TH1 version 1 as uproot.dynamic.Model_TH1_v8 (18 bytes)
                            (base): <TNamed '' at 0x7f91da495850>
                            (base): <TAttLine (version 2) at 0x7f91da398970>
                            (base): <TAttFill (version 2) at 0x7f91da48cdc0>
                            (base): <TAttMarker (version 2) at 0x7f91da3773d0>
                            fNcells: 0
                            TAxis version 2 as uproot.dynamic.Model_TAxis_v10 (12 bytes)
                                (base): <TNamed '' title='\x00\x00' at 0x7f91da3779d0>
                                (base): <TAttAxis (version 4) at 0x7f91da377d30>
                                fNbins: 81920
                                fXmin: 8.34406940932277e-309
                                fXmax: 2.0000190735445362
                                TArrayD version None as uproot.models.TArray.Model_TArrayD (? bytes)
                                    fN: 81792

attempting to get bytes 58:654394
outside expected range 0:542 for this Chunk
in file new.root
in object /mytree;1

If I set SetMakeClass(0); at the creation of the file, the read fails instead with:

~/.local/lib/python3.8/site-packages/uproot/model.py in read(cls, chunk, cursor, context, file, selffile, parent, concrete)
    798         )
    799 
--> 800         self.read_members(chunk, cursor, context, file)
    801 
    802         self.hook_after_read_members(

<dynamic> in read_members(self, chunk, cursor, context, file)

NotImplementedError: memberwise serialization of Model_TAxis_v10
in file new.root

Tested with ROOT 6.22/06 and also 5.34/21, uproot 4.0.5 and 4.0.6, using both python 2.7.18 and 3.8.6 interpreters. Am I doing something wrong?

Progman
  • 16,827
  • 6
  • 33
  • 48
crisgen
  • 23
  • 3

2 Answers2

1

Please check Jim's answer and follow the link therein to see if Issue #38 of uproot was fixed.

The following is not a solution, it's a workaround. If you have access to ROOT, you can retrieve the bin edges and content from the TH1D branch and save them as two separate branches of TArrayD that can be read by uproot. A sample macro to do this is (referring to the variable names in the original question):

void dumpTH1Array(){

//See the original question for the content of new.root
TFile * f = new TFile("new.root","UPDATE");
TTree * t = (TTree*)f->Get("mytree");

//Branch to read TH1D
TH1D    * histo   = 0;
TBranch * b_histo = 0;
t->SetBranchAddress("myhisto",&histo,&b_histo);

//Create new branches of TArrayD objects.
TArrayD * hx = new TArrayD();
TArrayD * hy = new TArrayD();
TBranch * b_hx = t->Branch("myhisto_x","TArrayD",&hx);
TBranch * b_hy = t->Branch("myhisto_y","TArrayD",&hy);

UInt_t nentries = t->GetEntries();

for(UInt_t i = 0; i<nentries; ++i){

    //Get the stuff
    Long64_t localEntry = t->LoadTree(i);
    b_histo->GetEntry(localEntry);
    b_hx->GetEntry(localEntry);
    b_hy->GetEntry(localEntry);

    //nbins includes the under- and overflow bins,
    //so it is actually the user defined nbins+2.
    UInt_t nbins = histo->GetSize(); 

    //We suppose that the TH1D has fixed binning
    //so histo->GetXaxis()->GetXbins() would just
    //return a null pointer. We rebuild the edges
    //array.
    Double_t * binedges = new Double_t[nbins-1];
    TAxis * xaxis = histo->GetXaxis();
    xaxis->GetLowEdge(binedges);
    binedges[nbins-2]=xaxis->GetBinUpEdge(nbins-2);

    //Set them.
    hx = new TArrayD(nbins-1,binedges);
    hy = new TArrayD(nbins,histo->GetArray());

    //Fill them back.
    b_hx->Fill();
    b_hy->Fill();
} 

t->Write();
f->Close();

//Goodbye
}

You will end up with two new branches, "myhisto_x" and "myhisto_y", including the bins edges in ascending order (size: user defined bins +1) and their contents (size: user defined bins +2, including the underflow and overflow bins). These can be easily read in uproot.

crisgen
  • 23
  • 3
0

You're not doing something wrong: it's a NotImplementedError because memberwise serialization has not been implemented in Uproot. That's Issue #38, which has been getting a lot of attention recently.

Other people finding this question, years later: check to see if Issue #38 has been resolved.

Jim Pivarski
  • 5,568
  • 2
  • 35
  • 47
  • Hi Jim, thank you! What about the Deserialization error that one gets instead if SetMakeClass(1) is called when creating the file? It is the same issue? Is there any possible way to read such a TH1D branch in uproot? – crisgen Mar 06 '21 at 00:08