Home | News | Documentation | Download

Problem when rescaling Y axis

Hi,

I am trying to rescale Y axis using the following code:

//Rescaling macro

#include "TAxis.h"
#include "TH1.h"
#include "TArrayD.h"

Double_t ScaleX(Double_t x)
{
  Double_t v;
  v = 10 * x + 100; // "linear scaling" function example
  return v;
}

Double_t ScaleY(Double_t y)
{
  Double_t v;
  v = 20 * y + 200; // "linear scaling" function example
  return v;
}

Double_t ScaleZ(Double_t z)
{
  Double_t v;
  v = 30 * z + 300; // "linear scaling" function example
  return v;
}

void ScaleAxis(TAxis *a, Double_t (*Scale)(Double_t))
{
  if (!a) return; // just a precaution
  if (a->GetXbins()->GetSize())
    {
      // an axis with variable bins
      // note: bins must remain in increasing order, hence the "Scale"
      // function must be strictly (monotonically) increasing
      TArrayD X(*(a->GetXbins()));
      for(Int_t i = 0; i < X.GetSize(); i++) X[i] = Scale(X[i]);
      a->Set((X.GetSize() - 1), X.GetArray()); // new Xbins
    }
  else
    {
      // an axis with fix bins
      // note: we modify Xmin and Xmax only, hence the "Scale" function
      // must be linear (and Xmax must remain greater than Xmin)
      a->Set( a->GetNbins(),
              Scale(a->GetXmin()), // new Xmin
              Scale(a->GetXmax()) ); // new Xmax
    }
  return;
}

void ScaleXaxis(TH1 *h, Double_t (*Scale)(Double_t))
{
  if (!h) return; // just a precaution
  ScaleAxis(h->GetXaxis(), Scale);
  return;
}

void ScaleYaxis(TH1 *h, Double_t (*Scale)(Double_t))
{
  if (!h) return; // just a precaution
  ScaleAxis(h->GetYaxis(), Scale);
  return;
}

void ScaleZaxis(TH1 *h, Double_t (*Scale)(Double_t))
{
  if (!h) return; // just a precaution
  ScaleAxis(h->GetZaxis(), Scale);
  return;
}

Its name is rescaling.cc and I use the following to call it then execute my macro:

.L rescaling.cc
.x myRootMacro.cc

the myRootMacro.cc includes these lines in the end:

  h->Draw();
  ScaleYaxis(h, ScaleY);
  h->Draw();
  h->ResetStats();

So far no error, but the generated histogram shows exactly the same Y axis, nothing changed. What could be the reason for that?

With this code, “scaling” of the Y-axis works only for TH2 and TH3 histograms.
For a TH1 histogram, only the X-axis can be “scaled” this way (i.e. you cannot change the “contents” of the histogram).

Thanks for the reply. So, could we maybe then accomplish it through a different way?

For instance, let’s assume this code:

  f = new TFile("myFile.root");
  if ((!f) || f->IsZombie()) {delete f; return;} // just a precaution
  f->GetObject("myTree", t);
  if (!t) {delete f; return;} // just a precaution
  gROOT->cd(); // all newly created histograms should be placed here
  h = new TH1D("h", "number of particles;A;counts", 100, 0., 55.);
  h->Sumw2(kTRUE); //makes sure errors are properly handled
  t->Project("h", "nParticles");
  delete f; // no longer needed (automatically deletes "t", too)
  
  integral = h->Integral();
  if (integral != 0) h->Scale(100. / integral);
  h->Draw()

This will draw histogram from branch in a tree, then normalize to 100. But what if you want to multiply the Y-axis (counts) by a factor? To be more specific, I wrote a code to convert counts to cross sections:

    TFile *file = new TFile("myFile.root");
    TTree *myTree= (TTree *) file->Get("myTree");
    myTree->GetEntry(myTree->GetEntries()-1);
    Float_t factor = myTree->GetLeaf("branch1")->GetValue()
                            / myTree->GetLeaf("branch2")->GetValue();
    Float_t cross_section = counts * factor;

Is there a way to link these two? Sorry if it was a bit confusing.

h->Scale(some_double_value);

But maybe you want to:
t->Project("h", "nParticles", "(branch1 / branch2)");

1 Like

I think the first approach maybe is what I need. It’s working well when I choose any double, but I’m trying to multiply by a calculated factor:

  TFile *f;
  TTree *t;
  TH1D *h;
  
  Double_t integral;
  f = new TFile("myFile.root");
  if ((!f) || f->IsZombie()) {delete f; return;} // just a precaution
  f->GetObject("myTree", t);
  if (!t) {delete f; return;} // just a precaution
  gROOT->cd(); // all newly created histograms should be placed here
  
  TTree *myTree= (TTree *) f->Get("myTree");
  et->GetEntry(myTree->GetEntries()-1);
  Float_t factor = myTree->GetLeaf("branch1")->GetValue()
                          / myTree->GetLeaf("branch2")->GetValue();
  
  h = new TH1D("h", "title;A;Cross section", 100, 0., 55.);
  h->Sumw2(kTRUE); //makes sure errors are properly handled
  t->Project("h", "branch3");
  delete f; // no longer needed (automatically deletes "t", too)
  
  h->Scale(factor);
  h->Draw();

I am then getting an error:

Error in <TRint::HandleTermInput()>: cling::InvalidDerefException caught: Trying to dereference null pointer or trying to call routine taking non-null arguments

Try to (re)use the existing “t” pointer instead of creating another “myTree” pointer and add “Double_t factor;” definition in the beginning.

It is working fine now thanks. Another question if I may, I modified the code a bit to draw two branches against one another as follows:

{

  h = new TH1D("h", "Title;x-titel;y-title", 100, 0., 200.);
  t->Project("h","branch1","branch2");
  h->Draw();

}

Branch1 data are being drawn correctly, but branch2 (on Y axis) was drawn after some calculations which I’m not familiar with. Do you know what this method do to the second input (branch2)?

See: TTree::Draw

{
  TH2D *h2 = new TH2D("h2", "Title;branch 1; branch 2", 100, 0., 200., 100, 0., 200.);
#if 0 /* 0 or 1 */
  t->Project("h2", "branch2:branch1");
#else /* 0 or 1 */
  t->Draw("branch2:branch1 >> h2", "", "goff");
#endif /* 0 or 1 */
  h2->Draw("colz");
}
1 Like

Thanks Wile. I’ve been trying to convert branch2 values by multiplying by a mean value (from another histo). I did:

  Double_t x = h->GetMean(); //to get the mean from another histo
  t->Project("h2", "x * branch2:branch1");
  h2->Draw();

It’s however, giving this error:

Bad numerical expression : "x"
Info in <TSelectorDraw::AbortProcess>: Variable compilation failed: {x / branch2:branch1 ,}

t->Project("h2", TString::Format("%g * branch2 : branch1", x));

1 Like

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