How to Manually Edit X Axis Range for TEfficiency object

I am trying to plot a set of efficiency curves. For some reason, the x limits on the plot are not consistent with those I set for xup and xlow when I initialized the TEfficiency objects. I’ve tried TEfficiency::GetPaintedGraph::GetXaxis::SetRange; as well as SetLimits (after drawing the TEfficiency objects). I have also tried manually altering it by right clicking on the TCanvas, and clicking on range, and setting it to these values.

Is there no way to just manually fix the plot settings for the canvas before plotting anything on it? I tried creating a blank histogram and plotting that first, which works, but then the xticks and yticks disappear because I am drawing an empty histogram.

As an aside, for drawing multiple objects, is the generic construction always to copy and paste the drawing code once before you enter the loop, then to pass “SAME” to TObject::Draw while inside the loop? Or is there a better accepted way of doing this?

Also, if I want to create a title that isn’t the title of the first object I happen to be drawing, the accepted way to do this is to create a TPaveLabel object, call gSystem->SetOpttitle(0), and center it manually?

Thanks,
Joseph

Hi Joseph,

try SetRangeUser(). SetRange reacts to bin numbers, but SetRangeUser reacts to the bare x values.

As to the drawing, you can of course do something like

if (i == 0 / obj == collection.front() / etc...) Draw("...");
else Draw("... SAME");

or any smarter version of this using string formatting.

The easiest concerning the title might be

if (**first**) {
  obj.SetTitle("Good title");
  obj.Draw("...")
}
else {
  obj.Draw("... SAME");
}

Hi Stephan,

Thank you for your reply. I discovered that the issue was not with SetRange or SetLimits or SetRangeUser, but with my specific TEfficiency objects. When I plotted a single one of the efficiency curves that behaved the most nicely, I didn’t have issue setting these properties the way it is described in other answers. The issue is with one of my TEfficiency objects that takes on weird values in some places and messes with the automatic axis setting.

I was able to fix the issue by permuting the order in which I draw the TEfficiencies. So for example, if I draw the first element in the TObjArray last (and the second element drawn first) , it works fine and takes on the values I specified for xlow and xup automatically, as I expect. It is slightly troublesome that I will have to re-evaluate whether or not I have to permute the order in which I draw the TEfficiencies every time I change parameters about my fitting routine, and that the method by which I can manually specify the ranges didn’t work in general, but for now I think I have a workaround. Thanks!

Best,
Joseph

Hi Joseph,

I understand. You should be able to manually SetMin or SetMax for both x and y axis on the first histogram before you draw it. It’s true that automatic ranges are only taken from the first histogram you draw. The others will just be drawn on top, whether they will be visible or not.

Hi Stephan,

It is useful to know that the automatic ranges are only taken from the first histogram I draw. The only issue with that is that I am not drawing histograms, but I am actually trying to draw TEfficiency objects. Although I know TEfficiency objects are made of fPassedHisto and fTotalHisto, I was lead to believe the only way of manually setting the ranges for TEfficiency objects directly was to draw the object first, then update the current pad, then get the painted graph, and then get the axis objects, and then set the axis ranges on those. So I am not quite sure how I can set SetMin or SetMax for both the x or y axes before I draw the first efficiency object. The way I had originally tried was indeed to set the range on the axes in the manner i just described for the first object, but that didn’t work. But it seems if I can set the axis ranges before the first TEfficiency is drawn, then it might work. Perhaps I am missing something? Thanks.

Best,
Joseph

Hi Joseph,

indeed it’s a bit cumbersome to draw TEfficiencies and manipulate their axes. One thing you could probably do is to draw an empty histogram, and change its limits such that a nice canvas is predefined. Then you draw all efficiencies on top of that.
The code could look like (untested!):

TH1D background("background", "background", 1, 0, <insert x axis limit>);
background.SetMaximum(<max>);
background.SetMinimum(<min>);
background.Draw();
[efficiencies].Draw("Same");

The reason why I believe this works is that TEfficiency uses TGraphs to draw, and these in turn use a histogram to draw. If you draw a histogram first, this defines axes, and therefore drawing the graph is just overlaying it.

Hi Stephan,

Thank you for your answer. This was actually one of the first things I tried. This has the expected behavior. However, as it is an empty histogram, everything disappears from the pad, except for the x axis labels I set when creating the histogram (as it is an empty histogram). So I could do this, fill the histogram and control the properties of the canvas that way. However, at this point I think it’s fine if I just draw the TEfficiencies in the order that doesn’t mess with the formatting of the ranges in the first place. I discovered the reason why the axis drawing gets messed up is because of outlying values in the first TEfficiency object which results from just the statistics at low values of MET. I think my issue is solved, in that it will always be sufficient for me to draw for instance the second TEfficiency object, as none of the other ones have this issue.

Anyways, thanks for all your help.

Best,
Joseph

It’s good that you made progress. Maybe I can help with the issue you mentioned here:

Is this maybe because the histogram is on the stack, and therefore destroyed when the function exits? (The same happens form Python when you leave on indented block).
This can be fixed by new-ing the histogram in C++, or by adding it into a list of objects or binding it to a reference that lives outside of the block.

Hi Stephan,

I don’t think this is the case, as I always place my complex dataobjects on the heap (TH1, etc.). I don’t think this is because the object is being destroyed, it’s just because drawing with an empty object will cause some of the plot settings to be overwritten.

Thank you for all your help,
Joseph