ROOT script to superimpose histograms via a loop on objects

Hi ROTers,

I need to compare two sets of histograms stored in two different files. The two files have the very same structure and the histos have the same name, so looping on objects is much more efficient and makes it file-independent (provided the two files you open show the same structure).

Here is my code

TFile * reference = new TFile("535RootMC-wmunubb-p14.list.root");
TFile * comp = new TFile("MCMuNubbP17-JESBMu.root");
Double_t GetMaxRef=0;
Double_t GetMaxComp=0;

void SuperImpose2()
{
TCanvas *My = new TCanvas("title","title",600,800);
Int_t type = 111;
TPostScript* ps = new TPostScript("p14-p17--MCMuNubbJESBMu.ps",type);
ps->NewPage();
gROOT->SetStyle("Plain");
My->SetFillColor(0);
My->SetFillStyle(4000);
My->Range(0, 0, 10, 5);

  for(int i=0 ; i!=reference->GetListOfKeys()->GetN() ; i++)
    {
      if(reference->GetListOfKeys->At(i)->GetName() != comp->GetListOfKeys->At(i)->GetName())
	{//if the two files are not identical in structure, complain and stop processing
	  cout << "Can't compare two files with different structures!" << endl;
	  break;
	}
      reference->GetListOfKeys->At(i)->GetName();
      GetMaxRef=At(i)->GetMaximum;
      if(At(i)->Integral()!=0)  At(i)->Scale(1/(float) At(i)->Integral()); //Get histo in reference file, store maximum value and scale it
      comp->GetListOfKeys->At(i)->GetName();
      GetMaxComp=At(i)->GetMaximum;
      if(At(i)->Integral()!=0)  At(i)->Scale(1/(float) At(i)->Integral()); //Get histo in new file, store maximum value and scale it
      if(GetMaxRef > GetMaxComp)
	{
	  reference->GetListOfKeys->At(i)->GetName(); //Get reference histo
	  At(i)->Draw(); //Draw it
	  comp->GetListOfKeys->At(i)->GetName(); //Get new histo
	  At(i)->SetLineColor(kRed);
	  At(i)->Draw("SAME"); //Draw it on the same canvas
	  My->Update();
	  My->Clear();
	}
      else
	{
	  comp->GetListOfKeys->At(i)->GetName(); //Get new histo
	  At(i)->SetLineColor(kRed);
	  At(i)->Draw(); //Draw it
	  reference->GetListOfKeys->At(i)->GetName(); //Get reference histo
	  At(i)->Draw("SAME"); //Draw it on the same canvas
	  My->Update();
	  My->Clear();
	}
    }
My->Close();
ps->Close();
}

Root complains and says

What am I doing wrong here?
Thanks.

On line 17 you have: for(int i=0 ; i!=reference->GetListOfKeys()->GetN() ; i++) which reference being a TFile and thus reference->GetListOfKeys() is a TList which does not have a GetN method. Instead you need: for(int i=0 ; i!=reference->GetListOfKeys()->GetEntries() ; i++)

Thanks, it solved the error and now the code looks like that

void SuperImpose2()
{
  TFile * reference = new TFile("535RootMC-wmunubb-p14.list.root");
  TFile * comp = new TFile("MCMuNubbP17-JESBMu.root");
  Double_t GetMaxRef=0;
  Double_t GetMaxComp=0;


  TCanvas *My = new TCanvas("title","title",600,800);
  Int_t type = 111;
  TPostScript* ps = new TPostScript("p14-p17--MCMuNubbJESBMu.ps",type);
  ps->NewPage();
  gROOT->SetStyle("Plain");
  My->SetFillColor(0);
  My->SetFillStyle(4000);
  My->Range(0, 0, 10, 5);
  
  
  for(int i=0 ; i!=reference->GetListOfKeys()->GetEntries() ; i++)
    {
      /*if(reference->GetListOfKeys()->At(i)->GetName() != comp->GetListOfKeys()->At(i)->GetName())
	{//if the two files are not identical in structure, complain and stop processing
	  cout << "Can't compare two files with different structures!" << endl;
	  break;
	}*/
      reference->GetListOfKeys()->At(i)->GetName();
      GetMaxRef=reference->GetListOfKeys()->At(i)->GetMaximum();
      if(reference->GetListOfKeys()->At(i)->Integral()!=0)  reference->GetListOfKeys()->At(i)->Scale(1/(float) reference->GetListOfKeys()->At(i)->Integral()); //Get histo in reference file, store maximum value and scale it
      comp->GetListOfKeys()->At(i)->GetName();
      GetMaxComp=comp->GetListOfKeys()->At(i)->GetMaximum;
      if(comp->GetListOfKeys()->At(i)->Integral()!=0)  comp->GetListOfKeys()->At(i)->Scale(1/(float) comp->GetListOfKeys()->At(i)->Integral()); //Get histo in new file, store maximum value and scale it
      if(GetMaxRef > GetMaxComp)
	{
	  reference->GetListOfKeys()->At(i)->GetName(); //Get reference histo
	  reference->GetListOfKeys()->At(i)->Draw(); //Draw it
	  comp->GetListOfKeys()->At(i)->GetName(); //Get new histo
	  comp->GetListOfKeys()->At(i)->SetLineColor(kRed);
	  comp->GetListOfKeys()->At(i)->Draw("SAME"); //Draw it on the same canvas
	  My->Update();
	  My->Clear();
	}
      else
	{
	  comp->GetListOfKeys()->At(i)->GetName(); //Get new histo
	  comp->GetListOfKeys()->At(i)->SetLineColor(kRed);
	  comp->GetListOfKeys()->At(i)->Draw(); //Draw it
	  reference->GetListOfKeys()->At(i)->GetName(); //Get reference histo
	  reference->GetListOfKeys()->At(i)->SetLineColor(kBlack);
	  reference->GetListOfKeys()->At(i)->Draw("SAME"); //Draw it on the same canvas
	  My->Update();
	  My->Clear();
	}
    }
My->Close();
ps->Close();
}

but ROOT is still unhappy and outputs

Hi,

TList::At(int) returns a TObject*, and that doesn’t have a method Maximum. You’ll need to cast it.

Please note that while we’re try to be as helpful as possible with ROOT questions, it’s not really our job to give introductory courses in C++ on this forum, nor to do a compiler’s job and check the syntax of code. So, please, get a C++ introduction and read it :slight_smile:

What will probably help you is to compile your code. That way you’ll see the (familiar?) compiler errors, instead fo Cint’s. Simply do
.x SuperImpose2.C+

Cheers, Axel.

So here is another question.

for(int i=0 ; i!=reference->GetListOfKeys()->GetEntries() ; i++)
{
char * classname;
classname = reference->GetListOfKeys()->At(i)->ClassName();
printf("%s",classname);

}

outputs TKey, so it would mean At(i) is indeed a TKey.
But if I do classname = comp->GetListOfKeys()->At(i)->GetClassName();
it complains that At(i) is a TObject - so what, TKey or TObject??
The question is, looping on keys in a file, how do I, for a given key, get the class name of the object it indexes? So then, knowing the name of the key I can load the object into the appropriate container (TH1 if it;s a TH1, TH2 is it’s a TH2,…).

Thank you for your help.

Hi,

again - please read a C++ introduction. I’m not saing that to annoy you, but because I believe you will benefit from it (and because it will save our time :-).

[quote]But if I do classname = comp->GetListOfKeys()->At(i)->GetClassName();
it complains that At(i) is a TObject - so what, TKey or TObject??[/quote]
It complains that At(i) returns a TObject*. That’s correct, see root.cern.ch/root/htmldoc/TList#TList:At. You know it’s a TKey, so you’ll have to tell the compiler (or Cint in this case). This is called casting from a base class pointer, and it’s a very basic C++ approach (nicely explained in any C++ introduction). So

TList* keys=comp->GetListOfKeys(); TObject* keyObj=0; if (keys) keyObj=keys->At(i); const char* classname=0; if (keyObj) classname=((TKey*)keyObj)->GetClassName();
will do it. dynamic_cast<TKey*> is actually what you’d want to use, but (TKey*) is a first step.
Cheers, Axel.