TPad.Print strange behaviour

Hi again,

I am trying to implement one script that reads data from a ntuple and prints it in a png file. Pretty simple…

So I read the data from “n” ntuples and fill a python array; then I create a canvas, split it in 5 pads (one for each channel which I am interested) , drawClone() them and print the canvas…

This procedure is repeated inside a for statement… about 250 times, So I am waiting for 250 plots in the end of the program’s execution…

Everything seems to work fine… Just TCanvas.Print() is giving me a headache…

First I tried

canvas.Print("%s%s_%s.png"%(PLOTPATH,drawer, brick))

It worked for 20 times… and in 21° time crashed with the following error message:

I though this was pretty strange, however I decide to change anyway to
canvas.Print(“%s%s_%s.png”%(PLOTPATH,drawer, brick), “png”)

For my surprise I got this message:

[quote]Traceback (most recent call last):
File “/afs/cern.ch/user/t/tilecom/public/www/DCS/version1.5/bin/dcsGenerateAnalysis.py”, line 329, in
Main(timeRange[0], timeRange[1])
File “/afs/cern.ch/user/t/tilecom/public/www/DCS/version1.5/bin/dcsGenerateAnalysis.py”, line 288, in Main
canvas.Print(“%s%s_%s.png”%(PLOTPATH,drawer, brick), “png”)
TypeError: none of the 2 overloaded methods succeeded. Full details:
void TPad::Print(const char* filename = “”) =>
takes at most 1 arguments (2 given)
problem in C++; program state has been reset
[/quote]

So now I am lost… I guess the “problem in C++; program state has been reset” warning is relevant, but I don’t know what I can do about…

FYI:
I am running it under lx32slc4
and my environment is set like this

                os.environ['ROOTSYS']  = "/afs/cern.ch/sw/lcg/external/root/5.18.00a/slc4_ia32_gcc34/root/"
                os.environ['PYTHONDIR']= "/afs/cern.ch/sw/lcg/external/Python/2.5/slc4_ia32_gcc34"
                os.environ['PYTHONPATH']="/afs/cern.ch/atlas/software/releases/14.0.0/external/NumPy/1.0.4/i686-slc4-gcc34-opt/lib/python2.5/site-packages:%s
/lib"%(os.environ["ROOTSYS"])

                os.environ['LD_LIBRARY_PATH'] = "%s/lib:%s/lib:%s"%(os.environ['ROOTSYS'], os.environ['PYTHONDIR'],os.environ['LD_LIBRARY_PATH'])
                os.environ['PATH'] = "%s/bin:%s/bin:%s"%( os.environ['ROOTSYS'], os.environ['PYTHONDIR'], os.environ['PATH'])

Can you help me???

Cheers

Means segfault or something similar. Ordinarily, there should be a stack trace through the C++ code in the logfile. Could you run your script under gdb (‘gdb python’ followed by ‘run myscript.py’).

Cheers,
Wim

I am not sure what is happening… Do you understand this log?

[/code]

Could you try to produce a canvas.root file instead of canvas.png?
Then in a different session, could you do the following ROOT session

root > TFile f("canvas.root"); root > canvas.Draw(); //or whatever the name of the canvas is root > canvas.Print("canvas.png")
if you still get tbe crash when producing the png file, post the canvas.root file and we will investigate.
I would also suggest to try with ROOT version 5.20. some fixes were introduced in the png file generator.

Rene

[quote=“brun”]Could you try to produce a canvas.root file instead of canvas.png?
Then in a different session, could you do the following ROOT session

root > TFile f("canvas.root"); root > canvas.Draw(); //or whatever the name of the canvas is root > canvas.Print("canvas.png")
if you still get tbe crash when producing the png file, post the canvas.root file and we will investigate.
I would also suggest to try with ROOT version 5.20. some fixes were introduced in the png file generator.

Rene[/quote]

Ok I tried the 5.20 and the problem changed

This is the piece of code that is crashing

                                canvas= TCanvas(drawer)
                                nPlots = len(dataset) -1
                                canvas.Divide(1,nPlots)
                                cCanvas = 1
                                data = array("d")

				for chId in dataset:
					if chId == "Temp3":
						continue
					canvas.cd(cCanvas)
					gPad.SetFillColor(17)
					gPad.SetGrid()
					gPad.SetFrameFillColor(20)
					gr = TGraph(len(dataset[chId]), timeset, dataset[chId])
					gr.SetMarkerColor(Colors[cCanvas-1])
					gr.SetMarkerStyle(1)
					gr.SetMarkerSize(5)
					gStyle.SetTitleW(0.10)
					gStyle.SetTitleH(0.2)
					gStyle.SetTitleX(0.90)
					gr.SetTitle(chId)
					maximum =  dataset[chId][argmax(dataset[chId])]
					minimum =  dataset[chId][argmin(dataset[chId])]
					maxValue = maximum + (maximum/10)
					minValue = minimum - (minimum/10)
					gr.GetYaxis().SetRangeUser(minValue, maxValue)
					gr.GetYaxis().SetLabelSize(0.15);
					gr.GetYaxis().SetLabelFont(21);
					gr.GetXaxis().SetTimeDisplay(1);
					gr.GetXaxis().SetLabelFont(12);
					gr.GetXaxis().SetLabelSize(0.03);
					gr.GetXaxis().SetLabelOffset(0.03);
					gr.GetXaxis().SetTimeFormat("#splitline{%d\/%m}{%H:%M}")
					gr.DrawClone("AP")
					cCanvas = cCanvas + 1
				canvas.SetTitle("%s_%s"%(drawer, brick))
				canvas.Print("%s%s_%s.png"%(PLOTPATH,drawer, brick), "png")
				lvpsValuesSummary.appendChild(bElem)
				del dataset

dataset is a dictionary of python arrays

dataset = {chId: array, …} and it is filled when the tree is readed… I am deleting the dataset to avoid data overlap during the interactions… This error message appears after the 20th interaction…

Is it still worthful generate the root files??

Cheers

This means that the code runs out of memory. Are you closing the files once used?

Cheers,
Wim

This means that the code runs out of memory. Are you closing the files once used?

Cheers,
Wim[/quote]

Yes I believe so…

Maybe it is better attach the entire code… I hope it is not so confuse…
dcsGenerateAnalysis.py (9.15 KB)

Hi,

yes, files etc. seem to be ok. As for the ‘gr.DrawClone(“AP”)’ I notice that it is returning a new-ed object. The python interpreter does not presume ownership of objects returned by pointer, so from the looks of it, you are supposed to delete it. For example, by taking ownership:temp = gr.DrawClone("AP") ROOT.SetOwnership( temp, True )
I’m not 100% sure on this one, as the TCanvas on which is drawn may have taken ownership already. Do give it a try, though.

HTH,
Wim

This means that the code runs out of memory. Are you closing the files once used?

Cheers,
Wim[/quote]

Can it be too much data?? I am running under lx32slc4

Cheers…

Hi,

if there’s proper cleanup after every file (should be pretty much automatic, as the same variables name are used over and over in a loop), and all files have a similar amount of data, “too much data” would cause full stop at file 1, not file 21.

Cheers,
Wim

[quote=“wlav”]Hi,

yes, files etc. seem to be ok. As for the ‘gr.DrawClone(“AP”)’ I notice that it is returning a new-ed object. The python interpreter does not presume ownership of objects returned by pointer, so from the looks of it, you are supposed to delete it. For example, by taking ownership:temp = gr.DrawClone("AP") ROOT.SetOwnership( temp, True )
I’m not 100% sure on this one, as the TCanvas on which is drawn may have taken ownership already. Do give it a try, though.

HTH,
Wim[/quote]

yes I will give a try…

Thanx

[quote=“wlav”]Hi,

yes, files etc. seem to be ok. As for the ‘gr.DrawClone(“AP”)’ I notice that it is returning a new-ed object. The python interpreter does not presume ownership of objects returned by pointer, so from the looks of it, you are supposed to delete it. For example, by taking ownership:temp = gr.DrawClone("AP") ROOT.SetOwnership( temp, True )
I’m not 100% sure on this one, as the TCanvas on which is drawn may have taken ownership already. Do give it a try, though.

HTH,
Wim[/quote]

Great!!! It works fine now… It didn’t crash…

But I didn’t understand what happened… Could you explained to me again?

Thanx,

Cheers

Hi,

The method ‘DrawClone()’ is implemented in TObject and does:// ... some code ... TObject *newobj = Clone(); // ... some more code ... return newobj;So someone needs to delete that clone after its return. Although I should implement some code that captures “Clone()” and “DrawClone()” as returning new objects that should be owned, I haven’t done so yet. So the clone leaks. By adding the line as posted, ownership is taken by the python interpreter, and the clone is deleted once the ‘temp’ reference goes out of scope.

Cheers,
Wim

[quote=“wlav”]Hi,

The method ‘DrawClone()’ is implemented in TObject and does:// ... some code ... TObject *newobj = Clone(); // ... some more code ... return newobj;So someone needs to delete that clone after its return. Although I should implement some code that captures “Clone()” and “DrawClone()” as returning new objects that should be owned, I haven’t done so yet. So the clone leaks. By adding the line as posted, ownership is taken by the python interpreter, and the clone is deleted once the ‘temp’ reference goes out of scope.

Cheers,
Wim[/quote]

Thanks

[quote=“wlav”]Hi,

The method ‘DrawClone()’ is implemented in TObject and does:// ... some code ... TObject *newobj = Clone(); // ... some more code ... return newobj;So someone needs to delete that clone after its return. Although I should implement some code that captures “Clone()” and “DrawClone()” as returning new objects that should be owned, I haven’t done so yet. So the clone leaks. By adding the line as posted, ownership is taken by the python interpreter, and the clone is deleted once the ‘temp’ reference goes out of scope.

Cheers,
Wim[/quote]

SO after running the code I realize that the code didn’t quite work well…

No seg faults… No memory leaks, However, instead of 5 pads plotted, just the last one was being drawn… So what I did

temp = []
       for:
       ...... canvas declaration....
       ...... Plotting things...........
       temp.append(gr.DrawClone(AP))
       canvas.Print()
del temp

and worked fine…

It might not be the most beautiful, but worked…

If you have other idea, please tell me…

Cheers[/code]