Hello!
I’m looking at the future of TTree with ROOT7, RNTuple
and running some test to understand its capabilities and limitations.
I noticed that custom class are currently not supported in RField. The following code stopping with an error:
terminate called after throwing an instance of 'ROOT::Experimental::RException'
what(): std::atomic<TClass*> is not supported
At:
ROOT::Experimental::RClassField::RClassField(std::string_view, std::string_view, TClass*) [/home/pronost/Software/root/root_src/tree/ntuple/v7/src/RField.cxx:782]
R__LOAD_LIBRARY(ROOTNTuple)
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <TCanvas.h>
#include <TH1F.h>
#include <TRandom.h>
#include <TRandom3.h>
#include <TSystem.h>
#include <cstdio>
#include <iostream>
#include <memory>
#include <vector>
#include <utility>
using RNTupleModel = ROOT::Experimental::RNTupleModel;
using RNTupleReader = ROOT::Experimental::RNTupleReader;
using RNTupleWriter = ROOT::Experimental::RNTupleWriter;
class PMTHit : public TObject {
public:
int PMT;
float T;
float Q;
void Reset() {
PMT=0;
T=0;
Q=0;
}
PMTHit() { Reset(); }
ClassDef(PMTHit,1)
};
class PMTHitCollection : public TObject {
public:
int nHits;
std::vector<PMTHit> hits;
void Reset() {
nHits=0;
hits.clear();
}
PMTHitCollection() { Reset(); }
ClassDef(PMTHitCollection,1)
};
class RecoInfo : public TObject {
public:
double vtx[4];
double goodness;
void Reset() {
vtx[0]=0;
vtx[1]=0;
vtx[2]=0;
vtx[3]=0;
goodness=0;
}
RecoInfo() { Reset(); }
ClassDef(RecoInfo,1)
};
void ntuple_write()
{
auto model = RNTupleModel::Create();
auto gRecoInfo = model->MakeField<RecoInfo>("RecoInfo");
auto gHitCollection = model->MakeField<PMTHitCollection>("HitInfo");
auto ntuple = RNTupleWriter::Recreate(std::move(model), "my_data", "ntuple_custom.root");
std::cout << "Filling NTuple" << std::endl;
TRandom* tRandom = new TRandom3();
for (int i = 0; i < 10000; i++) {
gRecoInfo->Reset();
gHitCollection->Reset();
gHitCollection->nHits = tRandom->Integer(100);
for ( int iHit = 0; iHit < gHitCollection->nHits; iHit++ ) {
PMTHit h;
h.PMT = tRandom->Integer(10);
h.Q = tRandom->Poisson(1000);
h.T = tRandom->Poisson(1000);
gHitCollection->hits.push_back(h);
}
gRecoInfo->goodness = tRandom->Gaus(0.5, 0.5);
gRecoInfo->vtx[0] = tRandom->Gaus(0, 10);
gRecoInfo->vtx[1] = tRandom->Gaus(0, 10);
gRecoInfo->vtx[2] = tRandom->Gaus(0, 10);
gRecoInfo->vtx[3] = tRandom->Gaus(1000, 10);
ntuple->Fill();
}
std::cout << "Closing NTuple" << std::endl;
}
Is there already a way to have custom class supported in RNTuple? Is it something which is planned for an upcoming release? Or is there another “more correct” way to deal with such data structure (specially the vector of another class) with RNTuple?