Write TH1 to Ttree

Hi

Is there any “fast” (and maybe “dirty” ) way of having a TH1F and auto-save it also as ttree ?

Thanks in advance

To be more certain, this is what I want to do - I have a root file with many histograms, which names are saved in the vector lstVar . So, what I want, is to save to another file , fout_, a copy of these histograms and a tree containing the TH1 info - I tried something similar to root.cern.ch/root/html/tutorials … est.C.html but, it does not work as the Branches are created correctly but are empty… So , I guess I need a loop inside TH1 entries ? How to ?

[code]for (unsigned int v = 0; v < lstVar.size (); v++) {
string GetHistos = “Process_”+lstVar[v];
TH1F htemp = (TH1F)finn_->Get(GetHistos.c_str());
htemp->SetName(lstVar[v].c_str());
sprintf (arg, “%s/F”, lstVar[v].c_str());
fout_->cd();

 tree->Branch(lstVar[v].c_str(), &htemp, "htemp/F"); 
 htemp->Write();

 tree->Fill();
}
tree->Write();
fout_->Write();
fout->Close();

[/code]

Thanks in advance

Hi,

In the example you refer to, the histogram are stored as whole object while you sample code seems to tries to store each bin entry as a individual float in the TTree (each bin value being in a different entry of the TTree). However in your example you call Fill only once per histogram, in additional even-though the TTree is told it is being passed a float (via “htemp/F”), it is actually pass a pointer to an histogram (&htemp and TH1F *htemp). So this can not possibly work. So the main question is how do you intend on storing the histogram values?

Philippe.

Hi Philippe

Thanks for your time

Yes, actually, I want to store each bin entry as a individual float in the TTree so at the end, I will have at the Tree as much entries as the histo entries and furthermore, with the “correct” info , ie for each entry in the TTree I will have stored the bin content… To put it differently, consider, that you have a initial TH1, which you rebin for example, and now you want both the new rebinned TH1 and the “corresponded” event-by-event TTree structure to be filled/saved… So, what should I change ?

Thanks!

[quote], I will have at the Tree as much entries as the histo entries and furthermore, with the “correct” info , ie for each entry in the TTree I will have stored the bin content…[/quote]Those 2 parts are not consistent :slight_smile:. If you each entry you store the bin content then the total number of entries will be the number of bins (and not the number of histogram entries).

Note that when the original data was histogram some of the information was lost; i.e. for each bin you only know how many values where between the lower edge and upper by not exactly which number it was ; so you can not recreate the original TTree.

Anyway to you would need to do some variation of:[code]for (unsigned int v = 0; v < lstVar.size (); v++) {
string GetHistos = “Process_”+lstVar[v];
TH1F htemp = (TH1F)finn_->Get(GetHistos.c_str());
Float_t value;
TString leaflist;
leaflist.Form("%s/F", lstVar[v].c_str());
fout_->cd();

 TBranch *br = tree->Branch(lstVar[v].c_str(), &value, leaflist.Data() );
 for(int b = 0; b < htemp->GetNbins(); ++b) {
     value = htemp->GetBinCenter( b );
     Double_t weight = htemp->GetBinContent( b );
     // Assuming that weight is actually an integer ... probably not such a good assumption
     for(int w = 0; w < weight; ++w) {
          br->Fill();
     }
  } 
  htemp->Write();
}
tree->SetEntries(); // Needed because we fill each branch individually.

[/code]All in all, a bit complex and I am not sure it is worth it … What is it that you are really trying to do? Would be keep the original and the ‘rebin’ histogram as is sufficient?

Philippe.

Hi again!

I will try what you suggest, but to answer your question

-I am having an original histogram as well as the TTree for the initial data .

-Now, I need to rebin the histo according to some specific number of entries / bin (see also my post /viewtopic.php?f=10&t=10747 when I tried to do this, but fails…) and

-at the end, saving the new rebinned histo and the new TTree…Nevertheless, I understand, that making the second TTree is not filled with the actual value of each bin…

-So, I need the second TTree in order to produce “new” rebinned TH2 histos and getting the correlation factor, rather than storing the TH2 itself… Is this too complex ??

Again, thanks for your time

[quote=“pcanal”][quote], I will have at the Tree as much entries as the histo entries and furthermore, with the “correct” info , ie for each entry in the TTree I will have stored the bin content…[/quote]Those 2 parts are not consistent :slight_smile:. If you each entry you store the bin content then the total number of entries will be the number of bins (and not the number of histogram entries).

Note that when the original data was histogram some of the information was lost; i.e. for each bin you only know how many values where between the lower edge and upper by not exactly which number it was ; so you can not recreate the original TTree.

Anyway to you would need to do some variation of:[code]for (unsigned int v = 0; v < lstVar.size (); v++) {
string GetHistos = “Process_”+lstVar[v];
TH1F htemp = (TH1F)finn_->Get(GetHistos.c_str());
Float_t value;
TString leaflist;
leaflist.Form("%s/F", lstVar[v].c_str());
fout_->cd();

 TBranch *br = tree->Branch(lstVar[v].c_str(), &value, leaflist.Data() );
 for(int b = 0; b < htemp->GetNbins(); ++b) {
     value = htemp->GetBinCenter( b );
     Double_t weight = htemp->GetBinContent( b );
     // Assuming that weight is actually an integer ... probably not such a good assumption
     for(int w = 0; w < weight; ++w) {
          br->Fill();
     }
  } 
  htemp->Write();
}
tree->SetEntries(); // Needed because we fill each branch individually.

[/code]All in all, a bit complex and I am not sure it is worth it … What is it that you are really trying to do? Would be keep the original and the ‘rebin’ histogram as is sufficient?

Philippe.[/quote]

Hi again

I tried what you suggest, and here are the two plots . An obvious difference is the XAxis range, but the most “worrying” is the wrong binning… Do I get it right ? Also, the

[quote]
Double_t weight = htemp->GetBinContent( b );
// Assuming that weight is actually an integer … probably not such a good assumption[/quote]

was indeed integer…

So, how could I fix the above problems ?

Cheers




[quote]An obvious difference is the XAxis range, but the most “worrying” is the wrong binning… Do I get it right ? [/quote]Why do you consider the binning wrong? How did you create the ‘htemp’ histogram? Does it get the number of bins that you implicitly requested?

Cheers,
Philippe.

Hi Philippe

I just used your script…So, maybe you are right, the “binning” itself is correct, but should not the two “plots” be identical?

Cheers

[quote]I just used your script.[/quote]Humm … you must something slightly as the code snippet I shown does create an htemp histogram. Aren’t you opening the file and doing:tree->Draw("AllJetsPt");and didn’t you double check the documentation of TTree::Draw to see what it chooses as default for the histogram limits and how to override it?

Cheers,
Philippe.

Well, yes, this is how I draw the TTree (or by TBrowsing in the root and double-click on the leaf)… Anyway, I looked, and it looks like that TTree::Draw does not gives you the option to change axis range etc… Would be most obliged if you could think of something so that I will have the two “identical” plots at the end…

Cheers

[quote] Anyway, I looked, and it looks like that TTree::Draw does not gives you the option to change axis range etc…[/quote]It definitively does. Where did you look?

Cheers,
Philippe

[quote=“pcanal”][quote] Anyway, I looked, and it looks like that TTree::Draw does not gives you the option to change axis range etc…[/quote]It definitively does. Where did you look?

Cheers,
Philippe[/quote]

root.cern.ch/root/html/TTree.html#TTree:Draw

if it is there, then I need new glasses :wink:))

Yes you need better glasses. ::slight_smile:

tree.Draw("myvar>>myhist(50,-3,7)","selection",..)
will histogram variable myvar into histogram myhist with 50 bins going from -3 to 7

Rene

Thank you so much…Indeed this works…almost … I also added some lines and now the code looks like

 for (unsigned int v = 0; v < lstVar.size (); v++) {
     string GetHistos = lstVar[v];
     TH1F *htemp = (TH1F*)finn_->Get(GetHistos.c_str());
     Float_t value;float lowedge;
     TString leaflist;
     leaflist.Form("%s/F", lstVar[v].c_str());
     fout_->cd();

     TBranch *br = tree->Branch(lstVar[v].c_str(), &value, leaflist.Data() );

     for(int b = 0; b < htemp->GetNbinsX(); ++b) {
       value = htemp->GetBinCenter( b );
         Double_t weight = htemp->GetBinContent( b );
         for(int w = 0; w < weight; ++w) {
              br->Fill();
         }
     }
      htemp->Write();
    TH1 * h1;
    tree->Draw("htemp>>h1(200,0,5000)");
    tree->Fill();

    }

  tree->SetEntries(); // Needed because we fill each branch individually.
  tree->Write();
     fout_->Write();
    fout_->Close();

But, I get an output

which is so many times as many lstVar histos as I have (it occurs when tree->Fill() ) . Also, at the final root file, the tree is written, and the TTree leaf/histos have the correct range (0->5000), but not the correct binning (I define 200). So, I guess, this could be caused, as initially, the leafs are created and then I am trying to “overwrite” the ttree with the histo (h1)out of it ?

Also

Warning in <TTree::SetEntries>: Tree branches have different numbers of entries, with 21734 maximum
For this, I would not worry , as I know that not all my initial histos have the same entries, and thus, makes sence to complain when ttree->SetEntries() is called

Again, thanks for your time

Cheers!

[quote]For this, I would not worry , as I know that not all my initial histos have the same entries, and thus, makes sence to complain when ttree->SetEntries() is called[/quote]You should worry. This will render any of the automatic tools (include TTree::Draw) unreliable (in particular in regard to the number of entries being plotted). If 2 branches are going to have a different number of entries, you ought to be put them in a different TTree.

Philippe.

True! This work just fine, but in the final root, only the leafs with the “wrong” binning are saved … I understand that this is due to the

tree->Draw(TString::Format("%s>>h1(200,0,5000)",lstVar[v].c_str())); tree->Fill()

just draws, and does not save the inherited h1 info to the Ttree (event-by-event as we were discussing) , but this is the key-point for my code ie I need the initial TH1 to be “exported” as TTree with the correct binning…

Sorry for this long-going discussion and thanks again!

Cheers

[quote]and does not save the inherited h1 info to the Ttree (event-by-event as we were discussing) ,[/quote]Why do you need to save that one? You already have the data in the TTree (i.e. you can very easily regenerate it) an you already have the original histogram with its binning and range information (you saved it via htemp->Write():wink:

[quote]tree->Fill();[/quote]Why did you re-introduce this command? I wonder if would help if you re-read carefully the User’s Guide, in particular the chapter on I/O and on the TTree.

Cheers,
Philippe.

Hi Philippe

Yes ,you are right…I ve got all I need via the htemp and tree…

Again, thanks for your time and help!