Hi,
I’ve also been interested in solving this problem for a while. When you draw multiple
histograms on a same canvas and later you want to normalize all the histograms, sometimes
you may have issues when the maximum of the first histogram is the smallest among all
the others, then the top of all other histograms with lower peaks would be chopped off…
It’s a brilliant idea to firstly draw a frame which is empty and manually set the max of y-axis
to 1 or other comfortable values. But the problem is, you have to set the limits MANUALLY,
which could be tedious especially when you want to draw multiple histograms at a time, though
it solves the problem ( by multiple I mean more than 10 histograms ).
Here is what I’ve done to have the histograms automatically adjust themselves.
Suppose I want to draw the first six elements of var1 — var1[ 0 ], var1[ 1 ] … var1[ 5 ]
and the first six of var2 — var2[ 0 ], var2[ 1 ] … var2[ 5 ].
Given three different samples I have, with the links given respectively addr1, addr2 and addr3,
and okay, let’s write it in python for simplicity’s sake.
samples_ = [ 's1', 's2', 's3' ] # call the sample s1, s2 and s3
links_ = { 's1' : "path/to/addr1", 's2' : "path/to/addr2", 's3' : "path/to/addr3" }
input_nm = [] # name of the x-axis
input_lb = [] # lower bound of the x-axis
input_ub = [] # upper bound of the x-axis
input_nbins = [] # bin numbers
### fill out all the attributes of the histograms
### for var1 series
for i range( 6 ):
input_nm.append( 'var1[' + str(i) + '];' )
input_lb.append( 40 )
input_ub.append( 100 )
input_nbins.append( 10 )
### then for var2 series
for i in range( 6 ):
input_nm.append( 'var2[' + str(i) + '];' )
input_lb.append( -1.0 )
input_ub.append( 1.0 )
input_nbins.append( 100 )
### next, let's create a list of histogram dictionaries
### to deal with different samples
hists_ = []
for i in range( len( input_nm ) ):
hists_.append( {} )
### sample files
f_in_ = {}
for s in samples_:
for i in range( len( input_nm ) ):
### set up all the histograms
hists_[ i ][ s ] = ROOT.TH1F( "hist"+str(i),
";"+input_nm[ i ]+"normalized units",
input_nbins[ i ], input_lb[ i ], input_ub[ i ] )
### set up all the sample files and the corresponding trees
f_in_[ s ] = ROOT.TFile( links_[ s ], "READ" )
f_in_[ s ].cd()
tr_in = f_in_[ s ].Get( "tree" ) # set up the input tree
for i in range( tr_in.GetEntries() ):
tr_in.GetEntry( i )
for k in range( len( input_nm ) ):
if k < 6:
hists_[ k ][ s ].Fill( tr_in.var1[ k ] )
else:
hists_[ k ][ s ].Fill( tr_in.var2[ k-6 ] )
### okay, we've finished the filling process
### now, let's draw histograms
for s in samples_:
for k in range( len( input_nm ) ):
### since we want to draw normalized histogram later on, and
### each sample may have events in different scale, we want
### to find an absolute max just so we could later compare
### different samples on the same scale
int_s1 = hists_[ k ][ 's1' ].Integral()
int_s2 = hists_[ k ][ 's2' ].Integral()
int_s3 = hists_[ k ][ 's3' ].Integral()
max_int_s = max( int_s1, int_s2, int_s3 )
scl_s1 = max_int_s / int_s1
scl_s2 = max_int_s / int_s2
scl_s3 = max_int_s / int_s3
### a crucial step here, here is how we automatically adjust
### the y-axis boundaries. Just keep in mind, we also want
### to give 20-30% whitespace above the highest peak
hists_[ k ][ s ].SetMaximum( 1.3*max(
scl_s1*hists_[ k ][ 's1' ].GetMaximum(),
scl_s2*hists_[ k ][ 's2' ].GetMaximum(),
scl_s3*hists_[ k ][ 's3' ].GetMaximum() ) )
### since now the correct limit of y-axis has been set,
### we could comfortably draw the normalized histograms
### without issues of top getting overlapped or chopped off
hists_[ k ][ s ].DrawNormalized( "samehist" )