How to adjust range in canvas?

Hi,

I have a quick question, I have two TH1F and a TLine object in a canvas and i want to change the range of the canvas and save it as pdf. I tried something like:

#include "TFile.h"
#include "TH1F.h"
#include "TCanvas.h"
#include <string>

using namespace std;

void make_plots(string ifile)
{
    TFile f(ifile.c_str(),"read");
    
    TCanvas *c = (TCanvas*)f.Get("test_can");
    c->SetLogy();

    TH1F *h = (TH1F*)c->GetPrimitive("S+B model_shaded");
    h->GetXaxis()->SetRangeUser(0,20);
    h->GetYaxis()->SetRangeUser(1e-4,2);
    
    TH1F *g = (TH1F*)c->GetPrimitive("B Model_shaded");
    g->GetXaxis()->SetRangeUser(0,20);
    g->GetYaxis()->SetRangeUser(1e-4,2);
    
    string pdf_name = ifile + string(".pdf");
    c->SaveAs(pdf_name.c_str());
}

But it does not work. I attached one of the hundreds of files that I have, could you please attach a piece of code that does the job? Oh and if I want to put a title on the Y axis how can I do that?

Thanks.
file.root (15.4 KB)

On the Y axis, for 1D histograms, you should use the SetMaximum() and SetMinimum() methods of TH1.
One way to see what to do is to set the range interactively on the canvas (using your mouse) and then save the result in a .C file. Then look at the saved .C file. You will see which commands are needed.

I’m afraid each canvas / pad will have a different name for its “frame” histogram and so you need to play a bit with the TList returned by the “TList *l = c->GetListOfPrimitives();” in order to find it (for example, find the first key which name begins with “frame_” or maybe it’s sufficient to find the first key which is a TH1D or maybe it’s simply always the second key in the list). Your attached “file.root” has a “frame_2a3b440”.

[code]#include “TFile.h”
#include “TCanvas.h”
#include “TH1.h”
#include

void make_plots(std::string ifile)
{
TFile f(ifile.c_str(),“read”);

TCanvas c = (TCanvas)f.Get(“test_can”);
c->SetLogy();

// c->Draw();
// c->GetListOfPrimitives()->ls();
// c->GetListOfPrimitives()->Print();

TH1D *h = (TH1D *)c->GetPrimitive(“frame_2a3b440”);
h->SetAxisRange(0, 20, “X”);
h->SetAxisRange(1e-4, 2, “Y”);
// h->SetXTitle(“Something?”);
h->SetYTitle(“What’s this?”);

c->Modified(); c->Update();
std::string pdf_name = ifile + string(".pdf");
c->SaveAs(pdf_name.c_str());
}[/code]

Yes, SetAxisRange does the SetMinimum and SetMaximum in case of Y axis on 1D.
The HowTo has been updated.

How about someone improves the existing “How to set ranges on axis ?”:
root.cern.ch/drupal/content/how-set-ranges-axis
using the following old posts (note that they cover graphs, histograms, profile histograms, histogram stacks):
[root.cern.ch/phpBB3/viewtopic.ph … 988#p64988](SetRangeUser doesn’t work well
[root.cern.ch/phpBB3/viewtopic.ph … 412#p62341](SetAxisRange(0.0,1.0,“Y”); is ineffective
[root.cern.ch/phpBB3/viewtopic.ph … 742#p64742](Palette on a TProfile2d
[root.cern.ch/phpBB3/viewtopic.ph … 618#p68618](Changing TMultiGraph Axis range results in bus error

Note also an unanswered question in:
[root.cern.ch/phpBB3/viewtopic.ph … 577#p62823](Drawing a TGraphAsymmErrors

Actually I just tried SetRangeUser on Y axis with TGraph and TH1 it works well …
The howto has been updated

Hi,

Thanks for your help, you were right about setaxisrange. When I try to see the contents of the canvas I get:

root [2] test_can->ls()

Canvas Name=test_can Title= Option=

 TCanvas fXlowNDC=0 fYlowNDC=0 fWNDC=1 fHNDC=1 Name= test_can Title=  Option=

  OBJ: TList	TList	Doubly linked list : 0

   OBJ: TH1D	frame_324f090	 : 1 at: 0x7fee0d627cb0

   OBJ: TH1F	S+B model	S+B model : 1 at: 0x7fee0d666f10

   OBJ: TH1F	S+B model_shaded	S+B model : 1 at: 0x7fee0d673800

   OBJ: TH1F	B Model	B Model : 1 at: 0x7fee0d674170

   OBJ: TH1F	B Model_shaded	B Model : 1 at: 0x7fee0d674ac0

   TLine  X1=-0.000051 Y1=0.000000 X2=-0.000051 Y2=0.937242

   OBJ: TLegend	TPave  X1= 0.550000 Y1=0.752000 X2=0.950000 Y2=0.950000

   OBJ: TH1D	frame_324f090	 : 1 at: 0x7fee0d627cb0

So it has a list that stores two histograms a legend and a line, but furthermore a frame whose name is different for each file. If I use the B Model or S+M model or any model histogram it does not work, but if I use the frame_* it does work. You were also right about playing with the TList, I got the list, the first element in the list seems to be the frame_* object, I set the range on it and it worked, as you see in the code below.

#include "TFile.h"
#include "TCanvas.h"
#include "TH1.h"
#include <iostream>
#include <string>
#include "TList.h"
#include "TCollection.h"

void make_plots(std::string ifile)
{
    TFile f(ifile.c_str(),"read");
    
    TCanvas *c = (TCanvas*)f.Get("test_can");
    c->SetLogy();
    
    TIter iter(c->GetListOfPrimitives());
    
    TH1D *h = (TH1D*)iter.Next();
    
    if(!h) {std::cout<<"NO HISTOGRAM FOUND"<<std::endl; return;}
    h->SetAxisRange(0, 20, "X");
    h->SetAxisRange(1e-4, 2, "Y");
    h->SetYTitle("Entries (Normalized)");
    
    c->Modified(); c->Update();
    std::string pdf_name = ifile + string(".pdf");
    c->SaveAs(pdf_name.c_str());
}

Thanks.

Canvases hold the graphics objects do be drawn. It is a display list, not a directory holding histograms. So the order is important. In this canvas it is very likely that the first histogram “frame…” has been put there to define the frame and the other histogram have been drawn in that frame using the option “SAME”… so it is the first histogram “frame…” which defines the axis limits and titles for all the others in the list. That’s why when you act on any other histogram but “frame…” it has no effect.