You are here

ROOT 7

For the first time since 20 year (i.e. ever), the ROOT team plans to break backward compatibility for crucial interfaces - once. This new major version of ROOT will make ROOT much simpler and safer to use: we want to increase clarity and usability. If you are a physicist, please read on - this is about your ROOT.

The release of ROOT 7 is planned to be in time for the long shutdown before LHC's run 3 (nicknamed LS2), i.e. it is currently expected to be released in 2018. Until then, ROOT 7 will gradually sneak into the ROOT sources, in the namespace ROOT::Experimental for those parts that are not yet cast in stone, and in the namespace ROOT for those that are. We will use standard C++ types, standard interface behavior, good documentation and tests: we are trying to be nice!

ROOT 7 Development

We meet about every second week to discuss topics and development of the new ROOT 7 interfaces. You can subscribe to root7-discussion@cern.ch to get the meeting announcements, and to participate at the discussions. The meeting presentations are available in Indico as "ROOT Interface Discussion".

We are happy to receive pull requests covering for instance Trello items or fixing bugs. Please submit them to our Github repo.

Feedback

The main point of the meeting and this page is to solicit your feedback. Most of it has been taken care of in the code already; those showing up at Trello are lined up. You're welcome to vote there, to signal the order!

Building ROOT 7

Pre-requisites

Support for the c++14 standard is required. Usage of g++ >= 5 or clang >= 3.4 is recommended.

Relevant cmake variables

The root7 and cxx14 cmake variables must be "ON".

Building from source would look similar to this:

$ mkdir root7_build
$ cd root7_build
$ cmake -Droot7=ON -Dcxx14=ON path/to/root/source
$ cmake --build . -- -j4

Examples

Fill a series of histograms

New interfaces
  1. #include "ROOT/TAxis.h"
  2. #include "ROOT/TFile.h"
  3. #include "ROOT/THist.h"
  4. #include "TTreeReader.h"
  5. #include "TTreeReaderArray.h"
  6. #include "TTree.h"
  7.  
  8. // Another function. Who knows what it does in a month from now.
  9. void someOtherFunction();
  10.  
  11. void fill(TTree* tree) {
  12. using namespace ROOT::Experimental;
  13. // Define the axes, we will re-use them
  14. TAxisConfig axisMuPt("muon pT [GeV]", {0., 1., 10., 100.});
  15. TAxisConfig axisJetEt("jet ET [GeV]", 10, 0., 1000.);
  16. TAxisConfig axisTag("tag value", 10, 0., 1.);
  17.  
  18. // Create the histograms
  19. TH2F hMuPtTag("muon pT versus tag value", axisMuPt, axisTag);
  20. TH2F hJetEtTag("jet ET versus tag value", axisJetEt, axisTag);
  21.  
  22. // Set up reading from the TTree
  23. TTreeReader reader(tree);
  24. TTreeReaderArray<float> jetEt(reader, "jet.ET");
  25. TTreeReaderArray<float> muPt(reader, "jet.lead_mu.pT");
  26. TTreeReaderArray<float> tag(reader, "jet.tag");
  27.  
  28. // Fill the histograms
  29. while (reader.Next()) {
  30. for (int iJet = 0; iJet < jetEt.size(); ++iJet) {
  31. hMuPtTag.Fill({muPt[iJet], tag[iJet]});
  32. hJetEtTag.Fill({jetEt[iJet], tag[iJet]});
  33. }
  34. }
  35.  
  36. someOtherFunction();
  37.  
  38. // Store the result; can create the file where really needed.
  39. TFilePtr file = TFile::Recreate("jetmuontag.root");
  40. file->Write("hist_mupt", hMuPtTag);
  41. file->Write("hist_jetet", hJetEtTag);
  42. }
ROOT6 interfaces
  1. #include "TFile.h"
  2. #include "TH2.h"
  3. #include "TTreeReader.h"
  4. #include "TTreeReaderArray.h"
  5. #include "TTree.h"
  6.  
  7. // Another function. Who knows what it does in a month from now.
  8. void someOtherFunction();
  9.  
  10. void fill(TTree* tree) {
  11. // Create the file before so it can own the histograms.
  12. TFile* file = TFile::Open("jetmuontag.root", "RECREATE");
  13.  
  14. // Create the histograms (cannot mix fixed and variable size bins)
  15. const double muonPtBins[] = {0., 1., 10., 100.};
  16. TH2* hMuPtTag = new TH2F("hMuPtTag", "muon pT versus tag value;muon pT [GeV];tag value",
  17. sizeof(muonPtBins) - 1, muonPtBins, 10, 0., 1.);
  18. TH2* hJetEtTag = new TH2F("hJetEtTag", "jet ET versus tag value;jet ET [GeV];tag value",
  19. 10, 0., 1000., 10, 0., 1.);
  20.  
  21. // Set up reading from the TTree
  22. TTreeReader reader(tree);
  23. TTreeReaderArray<float> jetEt(reader, "jet.ET");
  24. TTreeReaderArray<float> muPt(reader, "jet.lead_mu.pT");
  25. TTreeReaderArray<float> tag(reader, "jet.tag");
  26.  
  27. // Fill the histograms
  28. while (reader.Next()) {
  29. for (int iJet = 0; iJet < jetEt.size(); ++iJet) {
  30. hMuPtTag->Fill(muPt[iJet], tag[iJet]);
  31. hJetEtTag->Fill(jetEt[iJet], tag[iJet]);
  32. }
  33. }
  34.  
  35. someOtherFunction();
  36.  
  37. // Store the result. Ideally using file->Write() but very few people do that.
  38. hMuPtTag->Write();
  39. hJetEtTag->Write();
  40.  
  41. delete file; // but not the histograms!
  42. }

But the new interfaces are not about shortening your code - but about robustness. Here are a few examples of what can go wrong with the ROOT6 interfaces:

ROOT6 interfaces, showing what can go wrong.
  1. #include "TFile.h"
  2. #include "TH2.h"
  3. #include "TTreeReader.h"
  4. #include "TTreeReaderArray.h"
  5. #include "TTree.h"
  6.  
  7. // Another function. Who knows what it does in a month from now.
  8. void someOtherFunction();
  9.  
  10. void fill(TTree* tree) {
  11. // Create the file before so it can own the histograms.
  12. TFile* file = TFile::Open("jetmuontag.root", "RECRAETE");
  13.  
  14. // Create the histograms (cannot mix fixed and variable size bins)
  15. const double muonPtBins[] = {0., 1., 10., 100.};
  16. // The axis titles might have been changed. Impossible to see.
  17. TH2* hMuPtTag = new TH2F("hMuPtTag", "muon pT versus tag value;tag value;muon pT [GeV]",
  18. 4, muonPtBins, 10, 0., 1.);
  19. TH1* hJetEt = new TH1F("hJetEt", "jet ET versus tag value;jet ET [GeV];tag value",
  20. 10, 0., 1000.);
  21.  
  22. // Set up reading from the TTree
  23. TTreeReader reader(tree);
  24. TTreeReaderArray<float> jetEt(reader, "jet.ET");
  25. TTreeReaderArray<float> muPt(reader, "jet.lead_mu.pT");
  26. TTreeReaderArray<float> tag(reader, "jet.tag");
  27.  
  28. // Fill the histograms
  29. while (reader.Next()) {
  30. for (int iJet = 0; iJet < jetEt.size(); ++iJet) {
  31. hMuPtTag->Fill(muPt[iJet], tag[iJet]);
  32. hJetEtTag->Fill(jetEt[iJet], tag[iJet]);
  33. }
  34. }
  35.  
  36. someOtherFunction();
  37.  
  38. // Store the result. Ideally using file->Write() but very few people do that.
  39. hMuPtTag->Write();
  40. hJetEtTag->Write();
  41.  
  42. delete file; // but not the histograms!
  43. }

Here are the problems:

  • Constructing the TFile, "RECRAETE" is misspelled.
  • The axis titles of hMuPtJetET are inverted.
  • The number of muonPtBins is wrong.
  • The histogram hJetEtTag is filled with weights of *tag; that might be a leftover y coordinate.
  • You get two copies of the histogram in the file, one for histogram->Write(), one because the histogram is already associated with the file and will be written on file destruction.
  • The call to someOtherFunction() might change gDirectory and thus hMuPtJetET might not be written to jetmuontag.root.

To track these problems down you'd have to spend your time debugging them. Instead, the new interfaces will simply not allow this to happen: no debugging needed!