using RNTupleModel = ROOT::Experimental::RNTupleModel; using RNTupleWriter = ROOT::Experimental::RNTupleWriter; using RNTupleReader = ROOT::Experimental::RNTupleReader; struct Hit { float se_x; float se_y; float se_z; float ss_x; float ss_y; float ss_z; }; struct Track { std::vector hits; }; struct Event { std::vector tracks; }; void Generate() { auto model = RNTupleModel::Create(); auto fldEvent = model->MakeField("events"); auto writer = RNTupleWriter::Recreate(std::move(model), "NTuple", "data.root"); TRandom r; for (int i = 0; i < 1000; ++i) { fldEvent->tracks.clear(); auto nTracks = r.Integer(100); for (unsigned t = 0; t < nTracks; ++t) { Track track; auto nHits = r.Integer(10); for (auto h = 0; h < nHits; ++h) { Hit hit; hit.se_x = r.Gaus(100,10); hit.se_y = r.Gaus(200,10); hit.se_z = r.Gaus(300,10); hit.ss_x = r.Gaus(400,10); hit.ss_y = r.Gaus(500,10); hit.ss_z = r.Gaus(600,10); track.hits.emplace_back(hit); } fldEvent->tracks.emplace_back(track); } writer->Fill(); } } void ReadWithViews() { TH1F h("se_z", "se_z", 100, 250, 350); auto reader = RNTupleReader::Open("NTuple", "data.root"); auto view_tracks = reader->GetViewCollection("events.tracks"); auto view_hits = view_tracks.GetViewCollection("Track.hits"); auto view_se_z = view_hits.GetView("Hit.se_z"); for (auto i : view_se_z.GetFieldRange()) { h.Fill(view_se_z(i)); } h.DrawCopy(); } void traces() { Generate(); // Only read se_z ReadWithViews(); }