Wrong number of elements for an array, member of a myclass element in a TTree

Hi everyone,

I’ve created a Class of Event objects which contains elements of Class station (1 element):

class Event
{
    private:
    public:
        Station stations[NSTATIONS];

which contains elements of class Module (4 elements)

class Station
{
    private:

    public:
        int position;
        Module modules[NMODULES_PERSTATION];

which contains a vector of Stubs elements

class Module
{
    private:
    public:

        vector<Stub>    stubs;

I would like to have a TTree filled with Event objects, with of course all the other class members in the branches (station[1], modules[4], stubs[N, dynamically filled]).
I’ve succeeded to create the dictionary for all the classes with rootcling and also the .so shared library (following this suggestion Error in <TTree::Branch> - Vector issue - #9 by dpiparo) but the problem is that in my tree I have only 1 Station (and there is Station [1]) and 4 modules, but the 4 modules are not displayed, as shown in the picture.

Anyone knows why this could happen? Could it be a problem of copy constructors, move assignment operator or other c++ classes stuff? Of course I can give more details on the classes if needed-
Thank you so much for any help

This is how I generate the .root file and the tree

    TFile froot (c_nrout,"RECREATE");
    TTree t2("tree","Events tree");
    Event treeEvent;
    t2.Branch("Event", &treeEvent, 64000, 99);

I say that it can be c++ classes stuff issue because when I was trying to generate the dictionary I’ve tried the MakeProject() function and It gave as an error the following:

MyProjectProjectSource.cxx: In copy constructor ‘Station::Station(const Station&)’:
MyProjectProjectSource.cxx:60:39: error: use of deleted function ‘Module& Module::operator=(const Module&)’
    for (Int_t i=0;i<4;i++) modules[i] = rhs.modules[i];
                                       ^
In file included from Station.h:13:0,
                 from Event.h:13,
                 from MyProjectProjectHeaders.h:1,
                 from MyProjectProjectSource.cxx:3:
Module.h:23:7: note: ‘Module& Module::operator=(const Module&)’ is implicitly declared as deleted because ‘Module’ declares a move constructor or move assignment operator
 class Module {
       ^
c++: error: MyProjectProjectSource.o: File o directory non esistente
Error in <TUnixSystem::FindDynamicLibrary>: MyProject/MyProject.so does not exist in /usr/lib64/root:.:/usr/lib64/root:/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64

Hi @EugeniaSpedicato,

For the latest error that you posted, it seems that the default copy-assignment operator was implicitly deleted because the definition is not trivial.

Other than that, I cannot help you much more because I am lacking the (complete) class definitions. Could you attach a reproducer?

Cheers,
J.

Thank you so much for the replay.

Here are the classes: Stub, Module, Station and Event.

class Stub
{
    private:

    public:

        int bend;
        int address;
        int CBCid;
        int CICid;

        Stub()
        {
            bend    = -999;
            address = -999;
            CBCid   = -999;
            CICid   = -999;
        }

        Stub(stubWord b)
        {
            bend    = b.bend;
            address = b.address;
            CBCid   = b.CBCid;
            CICid   = b.CICid;
        };

        Stub(int ben, int add, int cbc, int cic)
        {
            bend    = ben;
            address = add;
            CBCid   = cbc;
            CICid   = cic;
        };

        Stub(nlohmann::json j)
        {
            bend    = j["bend"];
            address = j["address"];
            CBCid   = j["CBCid"];
            CICid   = j["CICid"];
        };

[...methods...]

};

class Module
{
    private:
    public:

        vector<Stub>    stubs;
        int             isOn;
        double          positionX;
        double          positionY;
        double          positionZ;
        double          rotationX; //rotation angle in radiants -- All info for modules and stations must be implemented in an input file
        double          rotationY; //rotation angle in radiants -- All info for modules and stations must be implemented in an input file
        double          rotationZ; //rotation angle in radiants -- All info for modules and stations must be implemented in an input file
        
        Module()
        {
            
            stubs.clear();
            positionX = -999;
            positionY = -999;
            positionZ = -999;
            rotationX = -999;
            rotationY = -999;
            rotationZ = -999;

        }

        Module(double pX, double pY, double pZ, double rX, double rY, double rZ, int on)
        {
            stubs.clear();
            isOn      = on;
            positionX = pX;
            positionY = pY;
            positionZ = pZ;
            rotationX = rX;
            rotationY = rY;
            rotationZ = rZ;
        }
        
[...methods...]
        
};

class Station
{
    private:

    public:
        int position;
        Module modules[NMODULES_PERSTATION]; 
        
        Station()
        {
            for(int i=0; i<NMODULES_PERSTATION; i++) modules[i] = *(new Module());
            position = -999;
        }

        Station(int pos)
        {
            position = pos;
        }

        Station(Module mod0, Module mod1, Module mod2, Module mod3, Module mod4)
        {
            modules[0] = mod0;
            modules[1] = mod1;
            modules[2] = mod2;
            modules[3] = mod3;
            modules[4] = mod4;
        };
        
        [...methods...]
};

class Event
{
    private:
    public:
        Station stations[NSTATIONS];
        headerWord      headerInfo; 

        int BxId;

        Event()
        {
            headerInfo = *(new headerWord);
            for(int i = 0; i<NSTATIONS; i++) stations[i] = * (new Station);
            headerInfo.clearHeader();
            for(int i=0; i<NSTATIONS; i++) stations[i].clearStation();
        };

        Event(nlohmann::json j)
        {
            for(int i=0; i<NSTATIONS; i++) stations[i].clearStation();
            BxId = j["Bx"];
            for(int i=0; i < NSTATIONS; i++)
            {
                stations[i].setFromJson(j["Stations"][i]);
                //stations.push_back(s);
            }

            headerWord h(j["headerInfo"]);

            headerInfo = h;
        }
        
[...methods...]

};

and this is how I fill the tree;

    TTree t2("tree","Events tree");
    Event treeEvent;
    t2.Branch("Event", &treeEvent, 64000, 99);

    for(int i = 0; i < pktStubWords.size(); i++)

{Event CurrentEvent;
            CurrentEvent.BxId = bx; 
            CurrentEvent.setStations(capperi,mod_cap);
            CurrentEvent.addHeaderWord(header);
            
            
            
            if(CurrentEvent.nStubs()==0) cout << "ERROR nStubs mid" << bx <<endl;
            

            nlohmann::json j;
            nlohmann::json cerealOutput = CurrentEvent.jsonOut();
            if(fout.is_open())   fout << cerealOutput << endl;
            else cout << "out file ain't open" << endl;
            treeEvent = CurrentEvent;
            t2.Fill();
}

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

Hi @EugeniaSpedicato,

Sorry, I missed replying to this topic. The TBrowser view shows only TTree branches (i.e., data columns). Holding a fixed-size array as part of each entry does not create more columns; it just makes the nested columns contain N values for each entry.

In your particular use case, for each Station, the modules member will hold 4 values for each of the columns that Module is decomposed to - but the number of data columns is still the same.

Actually, if you try to read the TTree (see below), you will get the expected results:

std::unique_ptr<TFile> f(TFile::Open("file.root"));
auto tree = f->Get<TTree>("tree");

Event *CurrentEvent = nullptr;
tree->SetBranchAddress("Event", &CurrentEvent);

for (int i = 0; tree->LoadTree(i) >= 0; ++i) {
   tree->GetEntry(i);
   // do something with `CurrentEvent` here...
}

Also, if not all the entries contain exactly 4 instances of Module, note that TTree also supports variable-length arrays using the //[numer_of_elements] notation as part of the class definition. For more information, see Chapter: InputOutput, section 13.3.4 Variable Length Array.

Cheers,
Javier.