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();
}
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.