TCanvas::Update required when re-drawing a histogram

The following python code will show an empty histogram in a canvas:

import ROOT
h = ROOT.TH1F (“hi”, “there”, 10, 0.0, 100.0)
h.Draw()
h.Fill(4)
h.Fill(40)
h.Draw()

If you then do something like
ROOT.gROOT.FindObject(“c1”).Update()

you’ll get a histogram with 2 entries drawn, as expected. The canvas is correctly updated when the above code is run in CINT.

This is with root 5.14.00/b built with MSVC 2005 SP1 and python 2.5.

Cheers,
Gordon.

Hi Gordon,

The following code w/ “Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32” and root “Version 5.14/00 14 December 2006” (from root_v5.14.00.win32gdk.msi)
shows a histogram with two entries as expected.

import ROOT
h=ROOT.TH1F("hi","there",10,0.0,100.0)
h.Fill(4)
h.Fill(40)
h.Draw()

My understanding is that if you Draw() an empty histogram at first as you did then you have to Update().

I don’t think this is a PyRoot specific behavior…

Yours,
Kazuyoshi

Gordon,

all work ok on Linux; haven’t got time to setup the new windows box that I have, so I didn’t try that platform. Here’s the piece that’s supposed to cause the update (this code is in ROOT.py):

[code]def _displayhook( v ):
_root.gInterpreter.EndOfLineAction()
return _orig_dhook( v )

_orig_dhook = sys.displayhook
sys.displayhook = _displayhook[/code]
Can you put in a print statement in _displayhook(), and see whether it is properly called in the case of your setup? Thanks!

Cheers,
Wim

Hi,
I modified it to print out “hi”:

def _displayhook( v ):
print “hi”
_root.gInterpreter.EndOfLineAction()
return _orig_dhook( v )

and never saw the word “hi” printed out. From the python command line:

sys.displayhook

If I do the following:

from ROOT import gInterpreter
gInterpreter.EndOfLineAction()

I still don’t get the proper display.

Gordon,

perhaps a silly question, but just to exclude: did you edit pyroot/ROOT.py or $ROOTSYS/lib/ROOT.py? If the former in a from CVS build, you’ll have to run make in order to install the modified version in $ROOTSYS/lib/ROOT.py.

[quote]>>> sys.displayhook
[/quote]
This is odd: either it should say that _displayhook is installed, or the built-in function displayhook. At least, that’s what I get (Linux, CVS HEAD). Are you running within another environment, such as e.g. ipython (I get differences in that case, but not the above)?

Since “gInterpreter.EndOfLineAction()” doesn’t work for you: what happens if you click anywhere in the image?

Cheers,
Wim

Hi,
I edited bin/ROOT.py. When I double checked to make sure I had it right by putting a “hi there” printout – which correctly appears during the import operation.

I now realize that some of the text I entered had angle brackets in it, and the form re-interprted those. Here it is again:

sys.displayhook
hi
<function _displayhook at 0x011E4FB0>

You’ll note the “hi” there – that is from the “print hi” that is in the new display hook function. So it is in there.

Also, I think the cut/past must have dropped it (ah, angle bracket), but I do get the hi when I do something like “h.Draw()”. I’m sorry if this was confusing:

h = ROOT.TH1F(“hi”, “there”, 100, 0.0, 10.0)
h.Draw()
TCanvas::MakeDefCanvas: created default TCanvas with name c1
hi

h.Fill(5)
hi
51

h.Draw()
hi

and at this point I have an empty histogram on the canvas.

When I click in it, as you suggest, it correctly updates.

Calling end of line action directly does not update the display. The only way to get it to update is to click in it (neat trick).

Sorry for making things more confusing not less!

Let me know what to try next, or if this doesn’t make sense let me know and I can make a virtual machine you can remote desktop into and test it out for yourself.

Gordon,

well, it doesn’t make sense for the following reason: gInterpreter.EndOfLineAction() basically calls TCint::UpdateAllCanvases(), which simply loops over all canvases that gROOT knows about, and calls Update() on them, which according to your first post actually works.

As another test, can you call ‘gInterpreter.UpdateAllCanvases()’ where in the previous test you called ‘gInterpreter.EndOfLineAction()’?

There is a set of locks and other conditions that need to be passed before UpdateAllCanvases() is called in EndOfLineAction(). Perhaps that one of them fails in your case.

Cheers,
Wim

Hi Wim,
UpdateAllCanvases works just fine – the canvas is correctly updated. So perhaps there is some lock that isn’t being released?

I follwed the rabit down the EndOfLineAction method in TCint, but didn’t see anything obvious (i.e. I didn’t run a debugger).

Cheers,
Gordon.

Hallo,

I may add something to this issue that I noticed with IPython (working under Debian Linux).

I used IPython and ROOT by starting it and enter as a first line “from ROOT import *”, with that I did not have any problems with not updating canvases.

Now I changed something in my IPython configuration, so that I can use profiles which executes some command before the IPython shell starts, in this case of course it should execute “from ROOT import *” (by adding “import_all ROOT” in an ipythonrc file) and suddenly I observe the same behaviour as Gordon.

Maybe this has to do something with namespace clashes. E.g. I don’t have access to ROOT if I import a module that uses and imports ROOT before I import everything from ROOT (i.e. “import useful_root_module” then “from ROOT import *” does not work).

I hope someone has more new ideas with this hint.

Duc

Duc,

IPython is notorious for not playing nice, and in particular for not properly restoring/calling the old excepthook and displayhook if it replaces such. The updating of canvases requires that the PyROOT displayhook is called normally. This should be fine, if ipython comes first (b/c PyROOT will call the old display hook as appropriate), but is likely trouble the other way around (which is how I read your putting the import in ipythonrc).

As for “from ROOT import " not working the same within other constructs: the code underneath relies on the calling module being the one that actually does the import. If there is an intermediate layer (ipython, if you use one of its special commands for import), then that intermediate layer will receive "”. If this is specifically for startup code, you could use directly:import libPyROOT import my_target_module libPyROOT.SetRootLazyLookup( my_target_module.__dict__ )
Best regards,
Wim