Create TH2F gamma-gamma matrix from TTree/TChain data

I’m working now on reading in data from a TTree/TChain attempting to create a 2D scatter plot for the purpose of using X/Y projections to study gamma ray concidences.

Previously, I was doing this using Fill() with a loop similar to:

[code]for (i=0; i<mult; i++) {
for (int ii=i+1; ii<mult; ii++) {
float x = gamma[i];
float y = gamma[ii];

histo->Fill(x,y);
histo->Fill(y,x);

}
}[/code]

where gamma energies are stored as floating-point numbers in an array of i values which I would store in an array using SetBranchAddress and GetEntry().

This would produce a nice symmetrical TH2 plot which we could gate on using X or Y projections to see which gamma-rays were coincident with which.

I am now faced with the problem of doing the same using TChain->Draw(), but so far I haven’t figured out how. I can do it with a single tree, but it doesn’t look I can use the same code with TChain as trying to call chain->GetEntry() throws a failure to evaluate. I need to use a chain because data is stored in multiple files containing parts of the same tree.

Is there a way that this can be done? I’ve been able to make all the other plots I want easily, but they’re simpler than this one.

In principle all you do with TTree can be done with chains. Can you give more details on the way GetEntry is failing ? also if you can provide a minimal example showing the problem that will help lot.

I’ll post the entire script, as I wrote a separate test script to experiment with how to do this before integrating back into the main script that makes all the other histos.

It looks like there is a scope issue somewhere.

[code]int GG () {

TChain tebchain(“teb”);

tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_1.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_2.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_3.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_4.root");

Double_t chainEntries = tebchain.GetEntries();

Float_t cc0[28] = {-1};
tebchain.SetBranchAddress(“xtals.cc”,&cc0);

/* draw and save histo we’ll be using as source /
tebchain.Draw("xtals.cc
xtals.doppler>>GGsource(4096,0,4096)");

/* declare histogram we’ll use as destination */
TH2F *GG_cc0_D = new TH2F(“GG_cc0_D”, “GG, cc0, Doppler corrected”, 4096,0,4096,4096,0,4096);

/* read bin contents into an array */
Double_t binContent[4096] = {0};
Double_t ggEntries = GGsource->GetEntries();

for (int i=1; i<=4096; i++) {
binContent[i] = GGsource->GetBinContent(i);
}

for (int e=0; e<chainEntries; e++) {

int gammaMult = 0;
for (int thisreset=0; thisreset<28; thisreset++) {
  cc0[thisreset] = -1;
}

tebchain.GetEntry();

for (int m=0; m<28; m++) {
  if (cc0[m] > -1) {gammaMult++;}
}

for (int j=0; j<gammaMult; j++) {	    	    		  
  for (int jj=j+1; jj<gammaMult; jj++) {
    float ex = cc0[j];
    float ey = cc0[jj];

    GG_cc0->Fill(ex,ey);
    GG_cc0->Fill(ey,ex);
  }
}

}

new TCanvas;
GG_cc0_D->Draw();

}[/code]

And this is what shows up when running the script:

root [0] .x /mnt/bigraid/treesort/GG.c Warning in <TClass::TClass>: no dictionary for class phosWallCalc is available Warning in <TClass::TClass>: no dictionary for class calEvent is available Warning in <TClass::TClass>: no dictionary for class phosWallRaw is available Warning in <TClass::TClass>: no dictionary for class hitEvent is available Warning in <TClass::TClass>: no dictionary for class phosWallAux is available Warning in <TClass::TClass>: no dictionary for class auxHit is available Warning in <TClass::TClass>: no dictionary for class g1OUT is available Warning in <TClass::TClass>: no dictionary for class g1GammaEvent is available Warning in <TClass::TClass>: no dictionary for class g2OUT is available Warning in <TClass::TClass>: no dictionary for class g2CrystalEvent is available Warning in <TClass::TClass>: no dictionary for class g3OUT is available Warning in <TClass::TClass>: no dictionary for class g3CrystalEvent is available Warning in <TClass::TClass>: no dictionary for class g4SimOUT is available Warning in <TClass::TClass>: no dictionary for class g4Sim_abcd1234 is available Warning in <TClass::TClass>: no dictionary for class g4Sim_emittedGamma is available Warning in <TClass::TClass>: no dictionary for class Bank29 is available Warning in <TClass::TClass>: no dictionary for class cloverEvent is available Warning in <TClass::TClass>: no dictionary for class cloverPacket is available Warning in <TClass::TClass>: no dictionary for class g2IntPt is available Info in <TCanvas::MakeDefCanvas>: created default TCanvas with name c1 Error: Symbol tebchain is not defined in current scope /mnt/bigraid/treesort/GG.c:41: Error: Failed to evaluate tebchain.GetEntry *** Interpreter error recovered *** root [1]

The 1D spectrum displays properly, so I can see that it is getting the data from the chain just fine.

On a side note, is there any way to get those warnings to not display? An older script that would work with a single file containing this tree also displayed those warnings but they seem to not cause any interference with what I’m trying to do, so I don’t want to confuse users with them.

I have fixed a typo in my call of GetEntry() and the scope error has disappeared. Now I have an issue with the script not reading any data from the tree, though similar code worked fine for a TTree (rather than a TChain).

The script as it is is now:

[code]int GG () {

TChain tebchain(“teb”);

tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_1.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_2.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_3.root");
tebchain.Add("/mnt/bigraid/gretina-runs/atlas1593/staged/merged/Run0667/Run0667_4.root");

Double_t chainEntries = tebchain.GetEntries();

/* declare histogram we’ll use as destination */
TH2F *GG_cc0_D = new TH2F(“GG_cc0_D”, “GG, cc0, Doppler corrected”, 4096,0,4096,4096,0,4096);

cout << chainEntries << " entries." << endl;

Int_t ent;
cout << "Pick an entry to show: ";
cin >> ent;

/* tebchain.Show(ent); */

Float_t cc0[28] = {0}; Float_t doppler[28] = {0};

tebchain.SetBranchStatus("*",0);

tebchain.SetBranchStatus(“xtals.cc”,1);
tebchain.SetBranchStatus(“xtals.doppler”,1);

tebchain.SetBranchAddress(“xtals.cc”,&cc0);
tebchain.SetBranchAddress(“xtals.doppler”,&doppler);

for (int e=0; e<chainEntries; e++) {

for (int thisreset=0; thisreset<28; thisreset++) {
  cc0[thisreset] = 0; doppler[thisreset] = 0;      
} /* resets done */

int gammaMult = 0;

/* Int_t entryBytes = */ tebchain.GetEntry(e,0);

if (e == ent) {tebchain.Show(e);}

for (int m=0; m<28; m++) {
  if (cc0[m] != 0) {gammaMult++;}
}

if (gammaMult > 0) {
  cout << "Mult: " << gammaMult << endl;
}

for (int j=0; j<gammaMult; j++) {
  for (int jj=j+1; jj<gammaMult; jj++) {
    float ex = cc0[j];
    float ey = cc0[jj];

    GG_cc0_D->Fill(ex,ey);
    GG_cc0_D->Fill(ey,ex);
  }
}

}

new TCanvas;
GG_cc0_D->Draw();
}[/code]

And this is the output; Notice that the ‘Mult:’ display never shows, so not a single event read in properly. Yet the event randomly chosen to display on the screen does show the desired data:

Warning in <TClass::TClass>: no dictionary for class phosWallCalc is available Warning in <TClass::TClass>: no dictionary for class calEvent is available Warning in <TClass::TClass>: no dictionary for class phosWallRaw is available Warning in <TClass::TClass>: no dictionary for class hitEvent is available Warning in <TClass::TClass>: no dictionary for class phosWallAux is available Warning in <TClass::TClass>: no dictionary for class auxHit is available Warning in <TClass::TClass>: no dictionary for class g1OUT is available Warning in <TClass::TClass>: no dictionary for class g1GammaEvent is available Warning in <TClass::TClass>: no dictionary for class g2OUT is available Warning in <TClass::TClass>: no dictionary for class g2CrystalEvent is available Warning in <TClass::TClass>: no dictionary for class g3OUT is available Warning in <TClass::TClass>: no dictionary for class g3CrystalEvent is available Warning in <TClass::TClass>: no dictionary for class g4SimOUT is available Warning in <TClass::TClass>: no dictionary for class g4Sim_abcd1234 is available Warning in <TClass::TClass>: no dictionary for class g4Sim_emittedGamma is available Warning in <TClass::TClass>: no dictionary for class Bank29 is available Warning in <TClass::TClass>: no dictionary for class cloverEvent is available Warning in <TClass::TClass>: no dictionary for class cloverPacket is available Warning in <TClass::TClass>: no dictionary for class g2IntPt is available 6.97731e+06 entries. Pick an entry to show: 43746 ======> EVENT:43746 g2 = (g2OUT*)0x1470150 xtals = (vector<g2CrystalEvent>*)0x1470190 xtals.cc = 1003.247864 xtals.doppler = 1.034173

Is there a difference in how SetBranchAddress and SetBranchStatus work in TChain vs. TTree? Because the multiplicity never goes above 0, the matrix never fills.

I think, the best for you would be to try an “analysis skeleton”. See, for example, links in: How are multiple TTree->Draw()s done?
Note: you need to generate the “analysis skeleton” for your TChain, not for your single TTrree.