Spherical harmonics

Your logic is not appropriate because that’s not histograms which are in the list of primitives but TGraphs. So they do not have bins. The TH2 is there only as a container to hold the plot limits and the list of graphs. When it was implemented, I think it would have been much better to produce a multigraph instead of a TH2 with a list of graphs … well, thinking of it, it may well be that the TMultiGraph did not exist at that time. I will try to find the better way to do it.

Well, in case of graphs, the axes are still defined by a histogram. So, as soon as one “detects” (when switching to log-[XYZ] mode) that the [XYZ]-axis low-edge of this histogram is <=0, one could “loop” over all points of all involved graphs and find the lowest positive [XYZ] value that appears and then modify the corresponding [XYZ]-low-edge of this histogram.

More “funny”… it is not implemented the same way with or without COL option. Without COL the graphs are simply drawn in the Pad, after htemp, they are not stored in the list of fundtions. So the connection with the histogram is lost in THistPainter:

root [1] Can->ls()
Canvas Name=Can Title=Can Option=
 TCanvas fXlowNDC=0 fYlowNDC=0 fWNDC=1 fHNDC=1 Name= Can Title= Can Option=
  OBJ: TList	TList	Doubly linked list : 0

   TPad fXlowNDC=0.01 fYlowNDC=0.51 fWNDC=0.48 fHNDC=0.48 Name= Can_1 Title= Can_1 Option=
    OBJ: TList	TList	Doubly linked list : 0
     TFrame  X1= -0.698970 Y1=-0.698970 X2=1.342423 Y2=1.342423
     OBJ: TH2F	htemp	b:a : 1 at: 0x7fb53b0754a0
     OBJ: TPaveText	title  	X1= 0.202552 Y1=1.444492 X2=0.440900 Y2=1.584838
     OBJ: TGraph	Graph	Graph : 1 at: 0x7fb53973fa60

   TPad fXlowNDC=0.51 fYlowNDC=0.51 fWNDC=0.48 fHNDC=0.48 Name= Can_2 Title= Can_2 Option=
    OBJ: TList	TList	Doubly linked list : 0
     TFrame  X1= -0.698970 Y1=-0.698970 X2=1.342423 Y2=1.342423
     OBJ: TH2F	htemp	b:a:c : 1 at: 0x7fb5396943a0
     OBJ: TPaveText	title  	X1= 0.149034 Y1=1.444492 X2=0.494418 Y2=1.584838

   TPad fXlowNDC=0.01 fYlowNDC=0.01 fWNDC=0.48 fHNDC=0.48 Name= Can_3 Title= Can_3 Option=
    OBJ: TList	TList	Doubly linked list : 0
     TFrame  X1= -0.290306 Y1=-0.698970 X2=1.311754 Y2=1.311754
     OBJ: TH2F	htemp	b:a : 1 at: 0x7fb539744a30
     OBJ: TPaveText	title  	X1= 0.417198 Y1=1.412290 X2=0.604250 Y2=1.550527
     OBJ: TGraph	Graph	Graph : 1 at: 0x7fb539692570

   TPad fXlowNDC=0.51 fYlowNDC=0.01 fWNDC=0.48 fHNDC=0.48 Name= Can_4 Title= Can_4 Option=
    OBJ: TList	TList	Doubly linked list : 0
     TFrame  X1= -0.698970 Y1=-0.698970 X2=1.311754 Y2=1.311754
     OBJ: TH2F	htemp	b:a:c : 1 at: 0x7fb539697c30
     OBJ: TPaveText	title  	X1= 0.136294 Y1=1.412290 X2=0.476490 Y2=1.550527

O.K. Let me try to summarize it …
In case the user crested a histogram with xmin > 0, everything will be drawn fine.
You improved the procedure that automatically creates the histogram in the Tree Drawing part so that it also tries HARD to set xmin > 0.
Thus the remaining problems are related to cases in which xmin <= 0 (either explicitly set by the user or the automatic procedure needs it) but, when switching to the log mode, we usually do not have the connection to the “original object” any more (so that we cannot “scan” its [XYZ] values in order to find “correct” positive limits).
How about we close one eye in this case?
We simply unconditionally set the [XYZ]-low-limit to something like 1/5 or 1/10 of the first positive “upper-edge” (the “low-edge” of this bin will still be < 0 or = 0).
Well, in case someone complains that some points are missing, we just say we are sorry and advise him to define proper histogram limits himself.

Yes your summary is good.

This is where I am now. And I am tempted to stay there. I was looking looking at an other possibility which would be to pass inside the TH2 struct the real minima for X and Y.

The fix is now comited in 5.34 and trunk.

Try the attached “w2a.C” macro …
There are three things that seem strange to me …

  1. upper row, third pad -> the “auto_hba” histogram should be drawn, but an ordinary graph is there
  2. upper row, fourth pad -> it completely neglects marker settings
  3. lower row, first and second pads -> a TH2F “htemp” is drawn, but there should be a TPolyMarker3D and the “htemp” should be a simple TH1F which just defines the axes
    w2a.C (4.1 KB)

I am using ROOT 6. And your macro crashes with ROOT 6. It is fine with ROOT 5. I have reduced your example to the minimal one and made a bug report here: sft.its.cern.ch/jira/browse/ROOT-6557

I will look at your original macro using ROOT 5.

Sorry, ROOT 6 is not supported by my macro. :mrgreen:
I unconditionally assign:
TH2F *auto_hba = (TH2F *)gPad->GetPrimitive(“auto_hba”);
but ROOT creates a TH1F “auto_hba” -> see point 1. in my previous post
I unconditionally assign:
htemp = (TH1F *)gPad->GetPrimitive(“htemp”);
but, in the first two pads in the lower row ROOT creates a TH2F “htemp” -> see point 3. in my previous post

Let me give a first bunch of answers.
(Three more questions in that thread promise to makes it in the top longest thread of this forum :mrgreen:)

Yes… I think it is fine. You do not specify any drawing option, so a scatter plot is drawn.
It sounds correct seems to me…

Yes, true. … but is that cas that’s the histogram which is drawn as a scatter plot. May be having the default marker type (the dot) for histogram plotting makes it more clear… at least it attracts user attention.

A TPolyMarker3D ??? … [-X :question: :exclamation:

the command on pad 5 and 6 (lower row, first and second pads) is nt->Draw(“b:a:c”, “”, “colz”); … so according to the doc we draw a 2D scatter with a and b … and c define the color … that’s what all the previous examples we have exchange did … Sorry if I missed something there … but this point 3 is very obscure to me…

I fixed my “w2a.C” macro (see my previous post above) so that it no longer tries TH1F where it should find a TH2F and I also protected it against nonexistent primitives. This new version works on ROOT 6 every second time fine, but every other time it produces a “segmentation violation”.

  1. upper row, third pad -> I explicitly say “b:a>>auto_hba” so I’d expect ROOT to create, fill and draw a TH2F “auto_hba” -> so, this pad should look exactly like the fourth pad in this row (which has “b:a>>hba”)
  2. fine with me
  3. you’re right … I completely forgot about “colz” (without “colz” it would produce a TPolyMarker3D)

In fact it looks like this syntax is used to “rename htemp”. If you want to have the histogram filled you should do what you do in pad #4 … It was implemented like that since ever … don’t ask me why … I am not sure changing the behaviour now is a good idea.

Yes, if you want a 3D scatter plot with the COL option you need 4 variables.

O.K.
So maybe it would be a good idea to put an explicit note about this “rename-htemp” feature in the TTree::Draw method description (where “>>hnew” is described).

There’s an example there:
tree.Draw(“sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)”)
And the question is … what is the code supposed to do if “hsqrt” exists and it needs to be “redefined” with a new binning? Delete it, “rename-htemp” without filling it and draw the graph? Or delete it, create a new proper histogram, fill it and draw it?

Note also that if “hnew” does not exist in advance then in 2-d and 3-d cases “>>+hnew” will not work as the histogram is only used to keep axes descriptions (maybe one should describe it, too).

There’s an additional note for ROOT 6 … in the upper row, third pad … in my “w2a.C” macro I ask for “auto_hba”, but it creates a “auto_hba_copy” (ROOT 5 correctly renames “htemp” into “auto_hba”) and I get a strange message “Warning in TSelectorDraw::Begin: Deleting old histogram with different dimensions” from somewhere (don’t know where from).

May be with this on you can make a bug report in Jira and assign it to Vassil.
I will look how to improve the doc.

On second thought, there are another “rename-htemp” related traps …

Assume the user did NOT create “hnew” … then he calls “x:y>>hnew”, so the “hnew” is created by NOT filled … and then the user calls …

  1. “x:y>>hnew” again … well, “hnew” exists so ROOT will fill it …
  2. “x:y>>+hnew” … well, “hnew” exists so ROOT will start to fill it, adding entries (but the user will probably NOT notice that entreis from the first call, which created “hnew”, are missing) …

Assume there is something drawn in the canvas so that “htemp” exists … then the user calls “x:y>>htemp” or “x:y>>+htemp” … well, “htemp” exists so ROOT will fill it …

Assume the user did NOT create “hnew” … then he calls “x>>hnew” … and then the user calls “x:y>>hnew” … well, “hnew” exists (though it needs to be redefined as a TH2F) so ROOT will fill it …

I think I don’t like the “rename-htemp” philosophy at all.
I think as soon as the user says “>>hnew” (">>htemp"), it should unconditionally start to fill “hnew” (“htemp”).

Yes, what you says make sense. May be the solution will be to always fill the histogram and, if there is no plotting option, then we internally plot the histogram with the new option FUNC I implemented for 2D. This way only the axis are plotted and the TGraphs holding the points are drawn cleanly without the “histogram scatter plot option” in background.

Well, I think if the users asks for “a:b>>hnew” or “a:b:c>>hnew”, he should get the “hnew” histogram created (or simply reset, if it already exists), filled and finally drawn (so, the TGraph or TPolyMarker3D should not be created at all), REGARDLESS whether “hnew” existed prior to the TTree:Draw call or not.

There’s no problem if someone wants to get the TGraph or TPolyMarker3D … just don’t use “>>hnew”.

No no no … this does not work … the TGraph and TPolyMarker3D should be created when you draw “a:b” without any drawing option. In that case we want to draw a scatter plot with one point at each (a[i], b[i]) position. What you suggest will end up with a crazy result. We will get a scatter plot but drawn with random points in each histogram cell. That will be a disaster.
We have to take care of the drawing option in that game.
I agree we should may be always fill the histogram but we cannot get rid of the TGraph and TPolyMarker3D if there is no drawing option.

Note that, EVEN NOW, when “hnew” existed prior to the “>>hnew” call, I do get a “scatter plot but drawn with random points in each histogram cell”. Yes I know it. See the fourth pad in the upper row of my “w2a.C” macro -> that’s where you can clearly see it.
But I DID ASK FOR IT MYSELF explicitly (by saying “>>hnew”), didn’t I?
When I complained that “it completely neglects marker settings”, you said “… at least it attracts user attention”. =D> :mrgreen:

I think the whole point now is to make this behavior consistent in both cases … regardless whether the “hnew” (or “htemp”) existed prior to the call or not, it should produce exactly the same results.

And my point is clear … is one wants a TGraph or TPolyMarker3D, one will NOT ask for a histogram, and vice versa. 8)

How about this …
As soon as you see “>>[+]hnew” and there’s no “user’s special 2-d / 3-d” drawing option, you enforce some “2-d / 3-d default” drawing option appropriate for such a 2-d / 3-d histogram?

Maybe on that occasion I would like to ask another question …
The following works fine:
ntuple->Draw(“hsimple.cxx”);
but this does NOT:
ntuple->Draw(“hsimple.cxx>>[+]hnew”);
Would it be possible to add such feature?
It could really be useful, I believe.