TH3F/TH2F hist in root

Hi everybody!

In April/18 I post a topic here that the solution was:

{
  gROOT->cd();
  THStack *hs =
    new THStack("energy",
                "Energies 0.03509 a 0.13509MeV with Ti 0.05mm;ELost/EKin;Counts");
  TH1F *h = new TH1F("h", "h", 100, 0.2, 1.8);
  if (h->GetSumw2N() == 0) h->Sumw2(kTRUE);
  const char *files[] = { "Energy_350f.root",
                          "Energy_360f.root",
                          "Energy_370f.root",
                          "Energy_450f.root",
                          "Energy_550f.root",
                          "Energy_850f.root",
                          "Energy_1350f.root" };
  const int n = sizeof(files) / sizeof(char*);
  int color = 0;
  for (int i = 0; i < n; i++) {
    TFile *f = TFile::Open(files[i]);
    if ((!f) || f->IsZombie()) { delete f; continue; } // just a precaution
    TTree *t; f->GetObject("GmDataTTree", t);
    if (!t) { delete f; continue; } // just a precaution
    gROOT->cd();
    t->Project("h", // each file re-fills it from scratch
               "(Event_AccumulatedEnergyLost / Event_InitialKineticEnergy)");
if (i<9) {
    color = i + 1;
    h->SetLineColor(color);
    } else {
          if (i > 10 && i < 17) {
            color = 11 + i;
            h->SetLineColor(color);
           } else {
                 color = 20 + i;
                 h->SetLineColor(color);
                 }
            }
    h->SetLineWidth(2);
    h->SetTitle(files[i]);
    hs->Add((TH1F*)(h->Clone(TString::Format("h_%d", i))));
    delete f; // automatically deletes "t", too
  }
  delete h; // no longer needed
  TLegend *l = new TLegend(0.75, 0.9, 0.9, 0.25);
  for (int i = 0; i < hs->GetNhists(); i++)
    { l->AddEntry(hs->GetHists()->At(i), "", "l"); }
  hs->Draw("NOSTACK HIST L");
  l->Draw();
}

I have a doubt: If my tree (GmDataTTree) inside the file Energy_360f.root, has the same name of the file without the extension root, for example: the file Energy_360f.root has a tree named Energy_360f; the file Energy_370f.root has a tree named Energy_370f and so one, how can I chage this code to do that? I think in a for loop but I can’t know how define the variable. Could someone help me?

Thanks

A good starting point could be

const std::vector<TString> names = {“Energy_350f”,
                                    “Energy_360f”,
                                    “Energy_370f”,
                                    ... snip ...
                                    };

for (auto && name : names) {
   TString filename = name + ".root";
   TString treename = name;

   TFile * f = TFile::Open(filename);
   TTree * t = f->Get<TTree *>(treename);
   ... snip ...
}

Cheers,
Kim

@kialbert thanks for the help! But when I put the code you are suggested next to the expression:

if ((!f) || f->IsZombie()) { delete f; continue; }

And with the for loop finishing before the if (i<9) an error appears when I compile:

Processing en.cpp…
Error in TFile::TFile: file testSIConExGALAIR35.root does not exist
Error: Illegal initialization of names. Constructor exists en.cpp:32:
*** Interpreter error recovered ***

Am I doing something wrong?

Thanks

The idea is simply to create the list of (tree) names without “.root” and then just add that suffix for the file names inside the loop. Try this:

  const char *trees[] = { "Energy_350f",
                          "Energy_360f",
                          "Energy_370f",
                          "Energy_450f",
                          "Energy_550f",
                          "Energy_850f",
                          "Energy_1350f" };
  char fname[50];
  TFile *f = 0;
  TTree *t = 0;
  for (int i = 0; i < n; i++) {
    sprintf(fname,"%s%s",trees[i],".root");
    f->Open(fname);
    f->GetObject(trees[i], t);
   ... other stuff inside the loop ...
  }

Thanks @dastudillo! I did what you said with this inside the previously for loop until the end but an error message appears:

Error in TFile::TFile: file testSIConExGALAIR35.root does not exist
Error in TFile::TFile: file testSIConExGALAIR36.root does not exist
Error in TFile::TFile: file testSIConExGALAIR37.root does not exist
Error in TFile::TFile: file testSIConExGALAIR40.root does not exist
Error in TFile::TFile: file testSIConExGALAIR45.root does not exist
Error in TFile::TFile: file testSIConExGALAIR55.root does not exist
Error in TFile::TFile: file testSIConExGALAIR85.root does not exist
Error in TFile::TFile: file testSIConExGALAIR135.root does not exist
Error in TFile::TFile: file testSIConExG AALAIR235.root does not exist
Error in TFile::TFile: file testSIConExGALAIR535.root does not exist
Info in TCanvas::MakeDefCanvas: created default TCanvas with name c1

This files was in the same file that this code is, I just substitute the file “Energy_350f” by “testSIConExGALAIR35”, but this error message appears. Am I doing something wrong?

Thanks again for the help!

Are you on Windows? Linux? If linux, open root in the folder where you have the macro (let’s say it is called “mymacro.C”) and the root files and type:
root [0] .! ls test*.root my*.C
On windows this should do the same:
root [0] .! dir test*.root my*.C
(the “.!” tells root that what follows is a system command).
If you don’t see all the expected files this way then the problem is clear, you are in the wrong place.
If the files are there, the issue could be typos (e.g., is the character after “test” a capital “i”, a “one” or a small “l”?). Try copy/pasting the root file names from this output into the trees array, instead of typing them by hand. A better way would be to get this list on the fly within your macro, or use with scripts or another root macro to get and save the list and then read it from your macro, but the manual method will work too. If you still have the same problem after this, I’m not sure… maybe remove the gROOT->cd() line?

Hi,

EDIT: Is see now I only repeated the question of @dastudillo. Sorry!

This means the file you are trying to open does not exist. From what directory are you running your script? What files exist in that directory? In other words, what is the output of pwd and ls -l .?

Considering the way your given example is written, you should take care to execute your script inside the directory where the files are located.

Cheers,
Kim

Thanks @kialbert I realized that, I’m run the code inside the file where the code and the files are. So I not understand why this error appears.
The ls -l return this:

-rw-rw-r-- 1 gamos gamos     2499 Jan 23 21:24 en.cpp
-rw-r--r-- 1 gamos gamos 31953162 Jan 23 12:28 testSIConExGALAIR135_tree_1000.root
-rw-r--r-- 1 gamos gamos 33913002 Jan 23 12:28 testSIConExGALAIR235_tree_1000.root
-rw-r--r-- 1 gamos gamos 19299974 Jan 21 22:42 testSIConExGALAIR35_tree_1000.root
-rw-r--r-- 1 gamos gamos 19891996 Jan 21 23:07 testSIConExGALAIR36_tree_1000.root
-rw-r--r-- 1 gamos gamos 20285512 Jan 21 23:17 testSIConExGALAIR37_tree_1000.root
-rw-r--r-- 1 gamos gamos 21282708 Jan 21 23:28 testSIConExGALAIR40_tree_1000.root
-rw-r--r-- 1 gamos gamos 22534236 Jan 23 11:46 testSIConExGALAIR45_tree_1000.root
-rw-r--r-- 1 gamos gamos 34598367 Jan 23 12:26 testSIConExGALAIR535_tree_1000.root
-rw-r--r-- 1 gamos gamos 24819152 Jan 21 23:29 testSIConExGALAIR55_tree_1000.root
-rw-r--r-- 1 gamos gamos 29267203 Jan 23 12:27 testSIConExGALAIR85_tree_1000.root

So I think it was ok, isn’t?

Cheers!

That file (as well as the others in those error messages) are not in that folder, according to your “ls” output:

You have to use the exact file names (testSIConExGALAIR135_tree_1000.root etc.)

@dastudillo and @kialbert Thanks! I see that error when I fixed this, this error occurs now:

Processing en.cpp...
Error: illegal pointer to class object f 0x0 5  en.cpp:47:
*** Interpreter error recovered ***

I will put here the code I’m doing:

#include "TFile.h"
#include "TTree.h"
#include "TRandom.h"
#include "TROOT.h"
#include "TBranch.h"
#include "TH1.h"
#include "Rtypes.h"

void en()
{
   gROOT->cd();
   THStack *hs =
   new THStack("energy",
                "Energy test; ELost/EKin;Counts");
   TH1F *h = new TH1F("h", "h", 100, 0.2, 1.8);
   if (h->GetSumw2N() == 0) h->Sumw2(kTRUE);
   const char *files[] = { "testSIConExGALAIR35_tree_1000.root",
                           "testSIConExGALAIR36_tree_1000.root",
                           "testSIConExGALAIR37_tree_1000.root",
                           "testSIConExGALAIR40_tree_1000.root",
                           "testSIConExGALAIR45_tree_1000.root",
                           "testSIConExGALAIR55_tree_1000.root",
                           "testSIConExGALAIR85_tree_1000.root",
                           "testSIConExGALAIR135_tree_1000.root",
                           "testSIConExGALAIR235_tree_1000.root",
                           "testSIConExGALAIR535_tree_1000.root" };
   const int n = sizeof(files) / sizeof(char*);
   int color = 0;
   for (int i = 0; i < n; i++) {
      TFile *f = TFile::Open(files[i]);
      if ((!f) || f->IsZombie()) { delete f; continue; } // just a precaution
        const char *trees[] = { "testSIConExGALAIR35",
                          "testSIConExGALAIR36",
                          "testSIConExGALAIR37",
                          "testSIConExGALAIR40",
                          "testSIConExGALAIR45",
                          "testSIConExGALAIR55",
			  "testSIConExGALAIR85",
			  "testSIConExGALAIR135",
			  "testSIConExGALAIR235",
			  "testSIConExGALAIR535" };
  	char fname[50];
  	TFile *f = 0;
  	TTree *t = 0;
  	for (int i = 0; i < n; i++) {
    	  sprintf(fname,"%s%s",trees[i],".root");
    	  f->Open(fname);
    	  f->GetObject(trees[i], t);
	  gROOT->cd();
      	  t->Project("h", // each file re-fills it from scratch
               "(Event_AccumulatedEnergyLost / Event_InitialKineticEnergy)");
      
       
   	 if (i<9) {
   	 color = i + 1;
   	 h->SetLineColor(color);
   	 } else {
   	       if (i > 10 && i < 17) {
  	          color = 11 + i;
 	           h->SetLineColor(color);
        	   } else {
        	         color = 20 + i;
        	         h->SetLineColor(color);
        	         }
        	    }
    	    h->SetLineWidth(2);
	    h->SetTitle(files[i]);
    	    hs->Add((TH1F*)(h->Clone(TString::Format("h_%d", i))));
    	    delete f; // automatically deletes "t", too
  	}
  }
  delete h; // no longer needed
  TLegend *l = new TLegend(0.75, 0.9, 0.9, 0.25);
  for (int i = 0; i < hs->GetNhists(); i++)
    { l->AddEntry(hs->GetHists()->At(i), "", "l"); }
  hs->Draw("NOSTACK HIST");
  l->Draw();
}

What’s wrong?

Cheers

Hi,

Unfortunately we can’t help you debug your code error by error. We are happy to answer questions regarding ROOT and, to some extent, general c++ questions.

I think you need to go through you code and make sure you understand what each line does (and verify that it does what you want it to). I would suggest that you also take some time to brush up on Modern C++, the current best practises e.g. focuses on avoiding pointers which usually brings clarity to one’s code. (I can give you some links if you are interested.)

For an example of what you need to make sure you understand: In this line, you open a file "testSIConExGALAIR35_tree_1000.root", which is fine.

Then a little bit further down you redefine the variable and throw away the pointer to the newly opened file. (Without closing it, which is considered bad practise).

Then you try to open a file named "testSIConExGALAIR35.root" (which according to your ls does not exist).

Also, adding a gratuitous amount of debug printouts (e.g. std::cout << "Debug: File to be opened: " << fname << std::endl;) usually helps alot!

Cheers,
Kim

Thanks @kialbert I appreciate your help!

I fixed the error, there is no error but my graphic appears empty! I put here the fix code and the histogram empty attached. What could I do?

code

#include "TFile.h"
#include "TTree.h"
#include "TRandom.h"
#include "TROOT.h"
#include "TBranch.h"
#include "TH1.h"
#include "Rtypes.h"

void en()
{
   gROOT->cd();
   THStack *hs =
   new THStack("energy",
                "Energy test; ELost/EKin;Counts");
   TH1F *h = new TH1F("h", "h", 100, 0.2, 1.8);
   if (h->GetSumw2N() == 0) h->Sumw2(kTRUE);
   
        const char *trees[] = { "testSIConExGALAIR35",
                          "testSIConExGALAIR36",
                          "testSIConExGALAIR37",
                          "testSIConExGALAIR40",
                          "testSIConExGALAIR45",
                          "testSIConExGALAIR55",
			  "testSIConExGALAIR85",
			  "testSIConExGALAIR135",
			  "testSIConExGALAIR235",
			  "testSIConExGALAIR535" };
  	char fname[50];
  	const int n = sizeof(trees) / sizeof(char*);
	int color = 0;
	 
	for(int i=0;i<n;i++){
    	  sprintf(fname,"%s%s",trees[i],"_tree_1000.root");
    	  TFile *f = TFile::Open(fname);
          if ((!f) || f->IsZombie()) { delete f; continue; } // just a precaution
    	  TTree *t;f->GetObject(trees[i], t);
	  if (!t) { delete f; continue; } // just a precaution
	  std::cout << "Debug: File to be opened: " << fname << std::endl;
	  gROOT->cd();
      	  t->Project("h", "(Event_AccumulatedEnergyLost / Event_InitialKineticEnergy)"); // each file re-fills it from scratch
          	  std::cout << "Debug: tree: " << trees[i] << std::endl;
        
   	 if (i<9) {
   	 color = i + 1;
   	 h->SetLineColor(color);
   	 } else {
   	       if (i > 10 && i < 17) {
  	          color = 11 + i;
 	           h->SetLineColor(color);
        	   } else {
        	         color = 20 + i;
        	         h->SetLineColor(color);
        	         }
        	    }
    	  h->SetLineWidth(2);
	  h->SetTitle(trees[i]);
    	  hs->Add((TH1F*)(h->Clone(TString::Format("h_%d", i))));
    	  delete f; // automatically deletes "t", too
 	}
  delete h; // no longer needed
  TLegend *l = new TLegend(0.75, 0.9, 0.9, 0.25);
  for (int i = 0; i < hs->GetNhists(); i++)
    { l->AddEntry(hs->GetHists()->At(i), "", "l"); }
  hs->Draw("NOSTACK HIST");
  l->Draw();
}

Best regards!

Maybe the “h” histogram has wrong axis limits. Try the “automatic binning”:

TH1F *h = new TH1F("h", "h", 100, 0., 0.);

Thanks @Wile_E_Coyote it’s work fine!

Hello. And how to connect the libraries Tfile.h and TH1.h in the root for building diagrams?

P.S.The question is not the most interesting, but I’m just starting to communicate with the root :))

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.