Segmentation Fault when accessing an array of TVector3 elements from Leaf

Hey all. I have a Tree measuring the results of an Eta Decay in our BGO. The ultimate goal here is to plot the invariant mass of the two photon system against our beam energy.

An event may look like this:

root [218] t1 -> Show(1)
======> EVENT:1
 lP4Tagger       = 1
 lP4Tagger.fUniqueID = 0
 lP4Tagger.fBits = 50331648
 lP4Tagger.fP    = TVector3
 lP4Tagger.fE    = 1530.35
 lP4BGONeutral   = 2
 lP4BGONeutral.fUniqueID = 0, 0
 lP4BGONeutral.fBits = 50331648, 50331648
 lP4BGONeutral.fP = TVector3, TVector3
 lP4BGONeutral.fE = 261.936, 288.509
 lP4FS           = 1
 lP4FS.fUniqueID = 0
 lP4FS.fBits     = 50331648
 lP4FS.fP        = TVector3
 lP4FS.fE        = 1861.76
 lP4FSMass       = 1
 lP4FSMass.fUniqueID = 0
 lP4FSMass.fBits = 50331648
 lP4FSMass.fP    = TVector3
 lP4FSMass.fE    = 903.884
 lP4GenTagger    = 1
 lP4GenTagger.fUniqueID = 0
 lP4GenTagger.fBits = 50331656
 lP4GenTagger.fP = TVector3
 lP4GenTagger.fE = 1530.35
 lP4GenPart      = 1
 lP4GenPart.fUniqueID = 0
 lP4GenPart.fBits = 50331656
 lP4GenPart.fP   = TVector3
 lP4GenPart.fE   = 1116.37

lP4BGONeutral measures two Photons for each event. I am trying to calculate the invariant mass of the two photons but I’m failing to extract the vectors. I have a working function for the Energies of the two photons:

void print_leaf_energy(TTree* tree, int nentries = 5) {

    Double_t energy[2];
    Int_t nParticles = 2;

    // Set branch addresses
    tree->SetBranchAddress("lP4BGONeutral.fE", energy);

    // Loop over entries
    for (int i = 0; i < nentries; ++i) {
        tree->GetEntry(i);
        std::cout << "Entry " << i << " has " << nParticles << " energies:\n";
        for (int j = 0; j < nParticles && j < 10; ++j) {
            std::cout << "  [" << j << "] " << energy[j] << "\n";
        }
    }
}

Which produces

Entry 0 has 2 energies:
  [0] 362.953
  [1] 228.767
Entry 1 has 2 energies:
  [0] 261.936
  [1] 288.509
Entry 2 has 2 energies:
  [0] 378.461
  [1] 251.108
Entry 3 has 2 energies:
  [0] 318.812
  [1] 275.832
...

However when I do the same with my momentum lP4BGONeutral.fP I get a segmentation fault:


void print_leaf_momentum(TTree* tree, int nentries = 5) {
    //gSystem->Load("libPhysics");

    // Declare array for momentum and variable for size
    TVector3 momentum[2];        //  I cranked this up to 900 without any change
    Int_t nParticles = 2; 

    // Set branch addresses
    tree->SetBranchAddress("lP4BGONeutral.fP", momentum);

    // Loop over entries
    for (int i = 0; i < 1; ++i) {
        tree->GetEntry(i); //Segmentation fault occurs here
        std::cout << "Entry " << i << " has " << nParticles << " momentum vectors:\n";
        for (int j = 0; j < nParticles; ++j) {
            std::cout << "  [" << j << "] ("
                      << momentum[j].X() << ", "
                      << momentum[j].Y() << ", "
                      << momentum[j].Z() << ")\n";
        }
    }
}

ChatGPT was unable to help me and I am completely out of ideas. I’m more familiar with python which is why I have quite a hard time debugging this

Thank you very much in advance


Appendix

Printing the tree gets me the following:

t1 -> Print()
******************************************************************************
*Tree    :t         : VectorExport                                           *
*Entries :      817 : Total =          532507 bytes  File  Size =     179886 *
*        :          : Tree compression factor =   2.88                       *
******************************************************************************
*Br    0 :lP4Tagger : Int_t lP4Tagger_                                       *
*Entries :      817 : Total  Size=      10022 bytes  File Size  =       1180 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.61     *
*............................................................................*
*Br    1 :lP4Tagger.fUniqueID : UInt_t fUniqueID[lP4Tagger_]                 *
*Entries :      817 : Total  Size=       7268 bytes  File Size  =       1174 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.65     *
*............................................................................*
*Br    2 :lP4Tagger.fBits : UInt_t fBits[lP4Tagger_]                         *
*Entries :      817 : Total  Size=       7248 bytes  File Size  =       1173 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.65     *
*............................................................................*
*Br    3 :lP4Tagger.fP : TVector3 fP[lP4Tagger_]                             *
*Entries :      817 : Total  Size=      36801 bytes  File Size  =       5030 *
*Baskets :        2 : Basket Size=      32000 bytes  Compression=   7.20     *
*............................................................................*
*Br    4 :lP4Tagger.fE : Double_t fE[lP4Tagger_]                             *
*Entries :      817 : Total  Size=      10509 bytes  File Size  =       3655 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   2.71     *
*............................................................................*
*Br    5 :lP4BGONeutral : Int_t lP4BGONeutral_                               *
*Entries :      817 : Total  Size=      10114 bytes  File Size  =       1170 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.66     *
*............................................................................*
*Br    6 :lP4BGONeutral.fUniqueID : UInt_t fUniqueID[lP4BGONeutral_]         *
*Entries :      817 : Total  Size=      10556 bytes  File Size  =       1116 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   8.87     *
*............................................................................*
*Br    7 :lP4BGONeutral.fBits : UInt_t fBits[lP4BGONeutral_]                 *
*Entries :      817 : Total  Size=      10536 bytes  File Size  =       1118 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   8.85     *
*............................................................................*
*Br    8 :lP4BGONeutral.fP : TVector3 fP[lP4BGONeutral_]                     *
*Entries :      817 : Total  Size=      69521 bytes  File Size  =      42376 *
*Baskets :        3 : Basket Size=      32000 bytes  Compression=   1.63     *
*............................................................................*
*Br    9 :lP4BGONeutral.fE : Double_t fE[lP4BGONeutral_]                     *
*Entries :      817 : Total  Size=      17057 bytes  File Size  =      13840 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.19     *
*............................................................................*
*Br   10 :lP4BGOProton : Int_t lP4BGOProton_                                 *
*Entries :      817 : Total  Size=      10091 bytes  File Size  =       1166 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.68     *
*............................................................................*
*Br   11 :lP4BGOProton.fUniqueID : UInt_t fUniqueID[lP4BGOProton_]           *
*Entries :      817 : Total  Size=       4013 bytes  File Size  =        143 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  23.51     *
*............................................................................*
*Br   12 :lP4BGOProton.fBits : UInt_t fBits[lP4BGOProton_]                   *
*Entries :      817 : Total  Size=       3993 bytes  File Size  =        139 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.16     *
*............................................................................*
*Br   13 :lP4BGOProton.fP : TVector3 fP[lP4BGOProton_]                       *
*Entries :      817 : Total  Size=       3978 bytes  File Size  =        136 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.67     *
*............................................................................*
*Br   14 :lP4BGOProton.fE : Double_t fE[lP4BGOProton_]                       *
*Entries :      817 : Total  Size=       3978 bytes  File Size  =        136 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.67     *
*............................................................................*
*Br   15 :lP4BGOPion : Int_t lP4BGOPion_                                     *
*Entries :      817 : Total  Size=      10045 bytes  File Size  =       1164 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.69     *
*............................................................................*
*Br   16 :lP4BGOPion.fUniqueID : UInt_t fUniqueID[lP4BGOPion_]               *
*Entries :      817 : Total  Size=       3999 bytes  File Size  =        141 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  23.83     *
*............................................................................*
*Br   17 :lP4BGOPion.fBits : UInt_t fBits[lP4BGOPion_]                       *
*Entries :      817 : Total  Size=       3979 bytes  File Size  =        137 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.50     *
*............................................................................*
*Br   18 :lP4BGOPion.fP : TVector3 fP[lP4BGOPion_]                           *
*Entries :      817 : Total  Size=       3964 bytes  File Size  =        134 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  25.02     *
*............................................................................*
*Br   19 :lP4BGOPion.fE : Double_t fE[lP4BGOPion_]                           *
*Entries :      817 : Total  Size=       3964 bytes  File Size  =        134 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  25.02     *
*............................................................................*
*Br   20 :lP4SciRi  : Int_t lP4SciRi_                                        *
*Entries :      817 : Total  Size=      10532 bytes  File Size  =       1162 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.69     *
*............................................................................*
*Br   21 :lP4SciRi.fUniqueID : UInt_t fUniqueID[lP4SciRi_]                   *
*Entries :      817 : Total  Size=       3985 bytes  File Size  =        139 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.16     *
*............................................................................*
*Br   22 :lP4SciRi.fBits : UInt_t fBits[lP4SciRi_]                           *
*Entries :      817 : Total  Size=       3965 bytes  File Size  =        135 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  24.84     *
*............................................................................*
*Br   23 :lP4SciRi.fX : Double_t fX[lP4SciRi_]                               *
*Entries :      817 : Total  Size=       3950 bytes  File Size  =        132 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  25.39     *
*............................................................................*
*Br   24 :lP4SciRi.fY : Double_t fY[lP4SciRi_]                               *
*Entries :      817 : Total  Size=       3950 bytes  File Size  =        132 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  25.39     *
*............................................................................*
*Br   25 :lP4SciRi.fZ : Double_t fZ[lP4SciRi_]                               *
*Entries :      817 : Total  Size=       3950 bytes  File Size  =        132 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=  25.39     *
*............................................................................*
*Br   26 :lP4FS     : Int_t lP4FS_                                           *
*Entries :      817 : Total  Size=       9930 bytes  File Size  =       1162 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.69     *
*............................................................................*
*Br   27 :lP4FS.fUniqueID : UInt_t fUniqueID[lP4FS_]                         *
*Entries :      817 : Total  Size=       7232 bytes  File Size  =       1170 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.66     *
*............................................................................*
*Br   28 :lP4FS.fBits : UInt_t fBits[lP4FS_]                                 *
*Entries :      817 : Total  Size=       7212 bytes  File Size  =       1169 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.66     *
*............................................................................*
*Br   29 :lP4FS.fP  : TVector3 fP[lP4FS_]                                    *
*Entries :      817 : Total  Size=      36689 bytes  File Size  =      21860 *
*Baskets :        2 : Basket Size=      32000 bytes  Compression=   1.65     *
*............................................................................*
*Br   30 :lP4FS.fE  : Double_t fE[lP4FS_]                                    *
*Entries :      817 : Total  Size=      10465 bytes  File Size  =       7609 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.30     *
*............................................................................*
*Br   31 :lP4FSMass : Int_t lP4FSMass_                                       *
*Entries :      817 : Total  Size=      10022 bytes  File Size  =       1166 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.67     *
*............................................................................*
*Br   32 :lP4FSMass.fUniqueID : UInt_t fUniqueID[lP4FSMass_]                 *
*Entries :      817 : Total  Size=       7260 bytes  File Size  =       1174 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.64     *
*............................................................................*
*Br   33 :lP4FSMass.fBits : UInt_t fBits[lP4FSMass_]                         *
*Entries :      817 : Total  Size=       7240 bytes  File Size  =       1173 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.65     *
*............................................................................*
*Br   34 :lP4FSMass.fP : TVector3 fP[lP4FSMass_]                             *
*Entries :      817 : Total  Size=      36721 bytes  File Size  =       9009 *
*Baskets :        2 : Basket Size=      32000 bytes  Compression=   4.01     *
*............................................................................*
*Br   35 :lP4FSMass.fE : Double_t fE[lP4FSMass_]                             *
*Entries :      817 : Total  Size=      10493 bytes  File Size  =       7575 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.31     *
*............................................................................*
*Br   36 :lP4GenTagger : Int_t lP4GenTagger_                                 *
*Entries :      817 : Total  Size=      10091 bytes  File Size  =       1188 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.57     *
*............................................................................*
*Br   37 :lP4GenTagger.fUniqueID : UInt_t fUniqueID[lP4GenTagger_]           *
*Entries :      817 : Total  Size=       7289 bytes  File Size  =       1175 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.65     *
*............................................................................*
*Br   38 :lP4GenTagger.fBits : UInt_t fBits[lP4GenTagger_]                   *
*Entries :      817 : Total  Size=       7269 bytes  File Size  =       1191 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.57     *
*............................................................................*
*Br   39 :lP4GenTagger.fP : TVector3 fP[lP4GenTagger_]                       *
*Entries :      817 : Total  Size=      36825 bytes  File Size  =       5023 *
*Baskets :        2 : Basket Size=      32000 bytes  Compression=   7.21     *
*............................................................................*
*Br   40 :lP4GenTagger.fE : Double_t fE[lP4GenTagger_]                       *
*Entries :      817 : Total  Size=      10530 bytes  File Size  =       3651 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   2.71     *
*............................................................................*
*Br   41 :lP4GenPart : Int_t lP4GenPart_                                     *
*Entries :      817 : Total  Size=      10045 bytes  File Size  =       1166 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.68     *
*............................................................................*
*Br   42 :lP4GenPart.fUniqueID : UInt_t fUniqueID[lP4GenPart_]               *
*Entries :      817 : Total  Size=       7267 bytes  File Size  =       1175 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.64     *
*............................................................................*
*Br   43 :lP4GenPart.fBits : UInt_t fBits[lP4GenPart_]                       *
*Entries :      817 : Total  Size=       7247 bytes  File Size  =       1176 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.63     *
*............................................................................*
*Br   44 :lP4GenPart.fP : TVector3 fP[lP4GenPart_]                           *
*Entries :      817 : Total  Size=      36729 bytes  File Size  =      21858 *
*Baskets :        2 : Basket Size=      32000 bytes  Compression=   1.65     *
*............................................................................*
*Br   45 :lP4GenPart.fE : Double_t fE[lP4GenPart_]                           *
*Entries :      817 : Total  Size=      10500 bytes  File Size  =       7513 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.32     *
*............................................................................*

ROOT Version: ROOT 6.34.08
Platform: linux
Compiler: gcc


Using SetBranchAddress for an inner object is ‘hard’. The simpler solution is to generate a skeleton via TTree::SetMakeSelector or better yet to switch mechanism/coding-style and using RDataFrame

Thank you for the pointer!

As of right now I am unfamiliar with RDataFrames. Could you provide an example on how I would get the events into the DataFrame so that I can access the events?

I imagine I could extract a list of all the TVector3 elements for Photon 1 and Photon 2?

Ideally I would like to work with this the way I worked with numpy arrays in python, so that I can apply array-wide operations to each element.

As a Minimal example I tried loading in the photons and adding them together. For this I referenced the the wiki under Defining custom columns


void compute_mass_df() {
    // Load the file and tree
    RDataFrame df("t", "Export_123456789_general_physics_trigger+40000_120k_events.root");
    //df.Display({"lP4BGONeutral.fP"})->Print();  // Optional: prints the first few rows

    //Define lambda to calculate the sum of the photon energies
    auto sum_elements = [](const std::vector<Double_t>& energies) {
        double sum = 0;
        for (auto e : energies) {
            sum += e;
        }
        return sum;
    };

    //Get total Photon Energy
    auto df2 = df.Define("TotalPhotonEnergy", sum_elements, {"lP4BGONeutral.fE"});

    std::cout << *df2 << std::endl;
    //Example from wiki throws error:
    //std::cout << *df2 << std::endl; -> error: indirection requires pointer operand

    df.Display({"TotalPhotonEnergy"})->Print();
    //This throws the following Error:
    //what():  Column "TotalPhotonEnergy" is not in a dataset and is not a custom column been defined.


    // Create a histogram for the total photon energy
    auto h2 = df2.Histo1D("TotalPhotonEnergy");
    //This line throws this error:
    //Error in <TTreeReaderValueBase::GetBranchDataType()>: Must use TTreeReaderArray to access a member of an object that is stored in a collection.

    // Draw the histogram
    h2->Draw();
}

However I get two errors as noted above and I’m a bit stumped on how to resolve them.

Edit

The first error above happens because I called display on the wrong dataframe. using the correct dataframe I also get this error:

Error in <TTreeReaderValueBase::GetBranchDataType()>: Must use TTreeReaderArray to access a member of an object that is stored in a collection.
Error in <TTreeReaderValueBase::CreateProxy()>: The branch lP4BGONeutral.fE contains data of type {UNDETERMINED TYPE}, which does not have a dictionary.

I’ll answer my own question here for anyone experiencing the same problem. As can be seen under working with collections on the Manuals page (Dataframes - ROOT) collections are not stored in the std::vector format but in an ROOT::RVec format. The call fails at a low level because it misinterprets the datatype. Correcting that mistake fixes the issue. Here is a working prototype:

#include "ROOT/RDataFrame.hxx"
#include "TFile.h"
#include "TLorentzVector.h"
#include "TVector3.h"

using namespace ROOT;
using namespace std;


void compute_mass_df() {
    // Load the file and tree
    RDataFrame df("tree", "Filename.root");

    //print the first few rows of the raw dataset
    df.Display({"lP4BGONeutral.fE", "lP4BGONeutral.fP"})->Print();

    //Define lambda to calculate the sum of the photon energies
    auto sum_elements = [](const ROOT::RVec<double>& energies) {
        double sum = 0;
        for (auto e : energies) {
            sum += e;
        }
        return sum;
    };

    auto sum_vectors = [](const ROOT::RVec<TVector3>& vecs) {
        TVector3 sum(0, 0, 0);
        for (const TVector3& v : vecs) {
            TVector3 sum = sum + v;
        }
        return sum;
    };
    

    //Get total Photon Energy
    auto df2 = df.Define("TotalPhotonEnergy", sum_elements, {"lP4BGONeutral.fE"});
    auto df3 = df2.Define("TotalPhotonMomentum", sum_vectors, {"lP4BGONeutral.fP"});


    df3.Display({"TotalPhotonEnergy", "TotalPhotonMomentum"})->Print();
    
    //Calculate Lorentz Vector
    auto get_lv = [](const TVector3& p, double E) {
        TLorentzVector lv;
        lv.SetVect(p);
        lv.SetE(E);
        return lv;
    };
    
    auto lv_df = df3.Define("P4", get_lv, {"TotalPhotonMomentum", "TotalPhotonEnergy"});

    //Calculate invariant mass
    auto get_mass = [](const TLorentzVector& p4) {
        return p4.M();
    };

    auto df_out = lv_df.Define("M", get_mass, {"P4"}); //Is equal to TotalPhotonEnergy because the momentum is 0
  
    df_out.Display({"P4", "M"})->Print();

I would also like to note for any future travellers: Photons are massless. Their Three-Momentum is Zero!