2D Scatter Plot Only Shows Null Stats

Hello Everyone,
I am very new to ROOT and am trying to plot a 2D scatter plot of some simulated data from GEANT4. This data comes in the form of a TTree (called ‘Scintillator’) that lives in a directory (‘ntuple’). In this data, I am trying to plot ‘NumGammaProduced’ vs. ‘Edep’.

I can get the plot working using the TTree::Draw function but, whenever I try to show the stats of the plot, I only see 0s. I am very new to this software so please excuse any beginner mistakes. Attached is the macro that I am currently using in case it helps - it should be relatively simple.

void test(string fName){

// add extension
if (fName.find('.') == std::string::npos) {
	fName.append(".root");
}

// load file
cout << "Loading " << fName << "..." << endl;
TFile f(fName.c_str());

// grab data
TTree* tScint = (TTree*)f.Get("ntuple/Scintillator");

// plot scintillator ntuple details
tScint->Draw("NumGammaProduced:Edep>>h","");

auto h = (TH2F*)gPad->GetPrimitive("h");
h->SetTitle("Scintillation Yield");
h->GetXaxis()->SetTitle("Energy Deposited [eV]");
h->GetYaxis()->SetTitle("# Gamma Produced");
h->SetStats(kTRUE);

}

The plot of my output is attached, showing the null stats.

Any help would be greatly appreciated!

broken.pdf (367.1 KB)

You can create, fill, and draw a 2-d histogram (TH2F). You will see its 40x40 grid of bins, drawn with the default “scatter plot” option.

  gROOT->cd(); // newly created histograms should go here
  delete gROOT->FindObjectAny("h"); // make sure it will be (re)created below
  TString varexp = "NumGammaProduced:Edep";
  TString selection = "";
#if 1 /* 0 or 1 */
  tScint->Project("h", varexp, selection);
#else /* 0 or 1 */
  tScint->Draw(varexp + " >> h", selection, "goff");
#endif /* 0 or 1 */
  TH1 *h = (TH1*)gROOT->FindObjectAny("h");
  if (h) {
    h->SetTitle("Scintillation Yield;Energy Deposited [eV];# Gamma Produced");
    h->SetStats(kTRUE);
    h->Draw();
    if (gPad) { gPad->Modified(); gPad->Update(); } // really (re)draw it
  }

You can create, fill, and draw an unbinned 2-d scatter-plot (TGraph). You will see all individual TTree’s data points.

  gROOT->cd(); // newly created histograms should go here
  TString varexp = "NumGammaProduced:Edep";
  TString selection = "";
  tScint->Draw(varexp, selection); // an unbinned 2-d scatter-plot (TGraph)
  TH2F *h = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but provides axes
  if (h) {
    TDirectory *d = h->GetDirectory();
    h->SetDirectory(gROOT); // needed for "Project" and / or "Draw" below
    // h->Reset("M"); // make sure it's "clean"
#if 1 /* 0 or 1 */
    tScint->Project("+htemp", varexp, selection);
#else /* 0 or 1 */
    tScint->Draw(varexp + " >> +htemp", selection, "goff");
#endif /* 0 or 1 */
    ((TArrayF*)h)->Reset(); // "reset" histogram's bins' contents
    h->SetName("h"); // empty, except for "statistics" (and axes, of course)
    h->SetTitle("Scintillation Yield;Energy Deposited [eV];# Gamma Produced");
    h->SetStats(kTRUE);
    h->SetDirectory(d); // where it originally belonged to
    gPad->Modified(); gPad->Update(); // make sure it's really (re)drawn
    TPaveText *t = (TPaveText*)gPad->GetPrimitive("title");
    if (t) { // move the "title" to the middle
      Double_t x1 = t->GetX1NDC();
      Double_t x2 = t->GetX2NDC();
      Double_t dx = (x1 + x2) / 2.0 - 0.5;
      t->SetX1NDC(x1 - dx);
      t->SetX2NDC(x2 - dx);
      gPad->Modified(); gPad->Update(); // make sure it's really (re)drawn
    }
  }

BTW. For "e1:e2:e3" and / or "e1:e2:e3:e4" draw expressions, which produce unbinned 3-d scatter-plots (TPolyMarker3D), there is this thread and that thread.

Hello,
Thank you very much for that help - it has allowed me to produce my desired plots

One note, while I would love to default to the first recommendation that you provided (since it is simpler), it appears to cause the plotting itself to fail. To demonstrate this, look at the following correct plot of the distribution using your second recommended method:


Comparing that to the plot from the first method (shown below), some issue becomes apparent

While the statistics are identical in both methods, the plot from the first-suggested method appears to have noise roughly uniformly distributed between energy deposits of 0<=E<=14000 eV and # Gamma Produced between 0<=n<=60:
image
I copied the code directly from the above post so I do not imagine this is due to an error on my part, but I am very new to this software so it very well could be. I can recreate this behavior in your second-suggested method (the ‘good’ method; plot shown at very top) by commenting out the line “((TArrayF*)h)->Reset();”, so I assume this issue is somehow due to improper ‘resetting’ of the histogram bins.

Focusing on the second method as that appears to work properly for me, it appears that the issue was that my histograms were somehow never filled - is that correct? In my minimal example of this second method (pasted below)

gROOT->cd(); // newly created histograms should go here

TString varexp = "NumGammaProduced:Edep";
TString selection = "";

tScint->Draw(varexp, selection); // an unbinned 2-d scatter-plot (TGraph)
TH2F *h = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but provides axes

h->SetDirectory(gROOT); // needed for "Project" and / or "Draw" below
tScint->Draw(varexp + " >> +htemp", selection, "goff");
((TArrayF*)h)->Reset(); // "reset" histogram's bins' contents
h->SetStats(kTRUE);

it appears that the essence of the modification is in calling the Draw function twice - is that correct? I would imagine that simply calling the following code would suffice, but clearly even after calling GetPrimitive, the TH2F that h points to stays empty.

TString varexp = "NumGammaProduced:Edep";
TString selection = "";

tScint->Draw(varexp, selection); // an unbinned 2-d scatter-plot (TGraph)
TH2F *h = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but provides axes

Any further explanation/discussion on this code (or just pointers on places to look, such as in your previous two linked threads) would be greatly appreciated.

Thank you, again, very much for all of the help!

See “Retrieving the result of Draw” and “Saving the result of Draw to an histogram” in the TTree::Draw method description.

Perfect - that resource clears up my conceptual lack of understanding!

There still seems to be the issue of the two methods resulting in different outputs (but identical statistics), as demonstrated in my previous post. In brief, the first-suggested method seems to be broken in that it shows incorrect data near the origin while the second-suggested method does not have this issue. Do you/anyone else have insight on this?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.