Stats Box (TPaveStats) in PyRoot

I’m trying to edit the default location of a stats box for histograms. I haven’t found something that can go in the rootlogon.C so I figure I have to put it in my drawing script itself.

I’ve tried this, but get an error:

st = hist.FindObject("stats") st.SetX1NDC(0.65)
with the error:

Traceback (most recent call last): File "", line 36, in <module> st.SetX1NDC(0.65) AttributeError: 'TObject' object has no attribute 'SetX1NDC'
What do I have to do in PyRoot to be able to set that?


as long as the histogram has not been drawn, the stats object will be NULL. It’ll be a TPaveStats after hist.Draw().

AFAICS, that behavior is equivalent to .C:root [0] h = new TH1F() (class TH1F*)0x842c198 root [1] h.FindObject( "stats" ) (const class TObject*)0x0 root [2] h.Draw() <TCanvas::MakeDefCanvas>: created default TCanvas with name c1 root [3] h.FindObject( "stats" ) (const class TObject*)0x8678398 root [4]

Hi there,
I don’t know if the problem in this rather old post was resolved, but I am also having a problem moving the default position of TPaveStats. I can’t seem to retrieve the stats box.

I followed the previous advice in the post about ensuring that the histo is drawn first.
If I check that the stats box is in the list of functions :
print hist.GetListOfFunctions()
print hist.GetListOfFunctions().FindObject(“stats”)

I get:
<ROOT.TList object (“TList”) at 0xa50f688>
<ROOT.TObject object at 0x(nil)>

If someone could help me to see my error that would be very much appreciated!
Many thanks


After the Draw, did you call gPad->Update(); to make sure the TPaveStats is created.


Hi Philippe,
ah yes that was the problem!
Sorry for the bother over what turned out to be a trivial problem, but thank you very much for replying.
Best regards

One easy way that I couldn’t find posted anywhere and fortunately I remembered out of nothing is that it is possible to change python class by force.

That is, it is possible to do:

stats = hist.FindObject( "stats" ) if not stats: continue stats.__class__ = ROOT.TPaveStats

… then use stats as a TPaveStats.


Which in the case of C++ bound objects is actually the same as a reinterpret_cast (the bound C++ object is referenced with a void* pointer and in use the type is picked up from the python proxy object, without further checks). Iow., can’t recommend that. I’m sitting on some patches that provide a proper cast() function, but have not had time to vet and check those in.

Beyond that, this:

will auto-cast to the actual object, so if the result is non-NULL, it will be of a TPaveStats type (or any derived type in the future). Iow., changing the class should not be needed, and if you do anyway, it may break (crash) in the future.