ROOT Version 6.30 Release Notes

2023-11-06

Introduction

ROOT version 6.30/00 was released on November 6, 2023.

For more information, see:

http://root.cern

The following people have contributed to this new version:

Daniel Álvarez Conde, CERN/EP-SFT,
Guilherme Amadio, CERN/IT,
Bertrand Bellenot, CERN/EP-SFT,
Jakob Blomer, CERN/EP-SFT,
Patrick Bos, Netherlands eScience Center,
Rene Brun,
Carsten Burgard, TU Dortmund,
Will Buttinger, Rutherford Appleton Lab,
Philippe Canal, FNAL,
Olivier Couet, CERN/EP-SFT,
Marta Czurylo, CERN/EP-SFT,
Mattias Ellert, Uppsala Uni,
Edward Finkelstein, JGU Mainz,
Gerri Ganis, CERN/EP-SFT,
Paul Gessinger, CERN/EP-SFT,
Florine de Geus, CERN/ATLAS,
Andrei Gheata, CERN/EP-SFT,
Enrico Guiraud, CERN/EP-SFT and Princeton,
Ahmat Hamdan, CERN/EP-SFT,
Stephan Hageboeck, CERN/IT,
Jonas Hahnfeld, CERN/EP-SFT,
Fernando Hueso González, CSIC/UV,
Attila Krasznahorkay, CERN/ATLAS,
Baidyanath Kundu, CERN/EP-SFT and Princeton,
Giovanna Lazzari Miotto, CERN/EP-SFT,
Sergey Linev, GSI,
Jerry Ling, Harvard Uni,
Javier Lopez-Gomez, CERN/EP-SFT,
Pere Mato, CERN/EP-SFT,
Lorenzo Moneta, CERN/EP-SFT,
Ole Morud, CERN/EP-SFT,
Alja Mrak Tadel, UCSD/CMS,
Axel Naumann, CERN/EP-SFT,
Dante Niewenhuis, UvA and CERN/EP-SFT,
Vincenzo Eduardo Padulano, CERN/EP-SFT,
Ioanna Maria Panagou, CERN/EP-SFT,
Danilo Piparo, CERN/EP-SFT,
QuillPusher, Compiler Research Group,
Fons Rademakers, CERN/IT,
Jonas Rembser, CERN/EP-SFT,
Jakob Schneekloth, CERN/EP-SFT,
Sanjiban Sengupta, CERN/EP-SFT,
Neel Shah, GSoC,
Garima Singh, CERN/EP-SFT and Princeton,
Yash Solanki, GSoC,
Uri Stern, CERN/EP-SFT,
Silia Taider, CPE Lyon and CERN EP-SFT,
Enric Tejedor Saavedra, CERN/IT,
Matevz Tadel, UCSD/CMS,
Vassil Vassilev, Princeton/CMS,
Wouter Verkerke, NIKHEF/ATLAS,
Daniel Werner, CERN/EP-SFT,
Zef Wolffs, NIKHEF/ATLAS

Platform support

Deprecation and Removal

Deprecated and removed ROOT modules

The following previously deprecated build options have been removed:

The following build options have now been deprecated and will be removed in the future v6.32:

Please let us know at rootdev@cern.ch if their planned removal would cause problems for you!

Deprecated and removed interfaces

Core Libraries

I/O Libraries

RDataFrame

Distributed RDataFrame

TTree Libraries

Many bug fixes, improvements for multi-threaded usage, and optimizations.

RNTuple

ROOT’s experimental successor of TTree has seen a large number of updates during the last few months. Specifically, v6.30 includes the following changes:

auto model = RNTupleModel::Create();
auto fieldPt = model->MakeField<float>("pt", 42.0);
auto ntuple = RNTupleWriter::Recreate(std::move(model), "myNTuple", "out.ntuple");
ntuple->Fill();

auto modelUpdater = ntuple->CreateModelUpdater();
modelUpdater->BeginUpdate();
std::array<double, 2> fieldArray;
modelUpdater->AddField<std::array<double, 2>>("array", &fieldArray);
modelUpdater->CommitUpdate();

// After this point, entries will have a new field of type `std::array<double, 2>`
ntuple->Fill();
RNTupleWriteOptions options;
options.SetHasSmallClusters(true);
auto writer = RNTupleWriter::Recreate(std::move(model), "myNTuple", "out.ntuple");
auto model = RNTupleModel::Create();
auto fvec = model->MakeField<std::vector<float>>("vec");

auto aliasVec = RFieldBase::Create("aliasVec", "std::vector<float>").Unwrap();
model->AddProjectedField(std::move(aliasVec), [](const std::string &fieldName) {
   if (fieldName == "aliasVec") return "vec";
   else                         return "vec._0";
});

Projected fields are stored as part of the metadata.

Please, report any issues regarding the above mentioned features should you encounter them. RNTuple is still experimental and is scheduled to become production grade by end of 2024. Thus, we appreciate feedback and suggestions for improvement.

Histogram Libraries

2D Scatter plots are a very popular way to represent scientific data. Many scientific plotting packages have this functionality. For many years ROOT itself as offered this kind of visualization dedicated drawing options for TGraph or TTree. But there was no simple way to produced 4D scatter plots from data stored in simple vectors. To fulfil these requirements the new class, TScatter, has been implemented. It is able to draw a four variables scatter plot on a single plot. A detailed description was given on the website as a blog-post.

Math Libraries

Minuit2 is now the default minimizer

Many ROOT-based frameworks and users employ Minuit2 as the minimizer of choice for a long time already. Therefore, Minuit2 is now the default minimizer used by ROOT. This affects also RooFit, which inherits the default minimizer from ROOT Math.

The default can be changed back to the old Minuit implementation as follows:

ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit");

Alternatively, you can add this line to your ~/.rootrc file:

Root.Fitter: Minuit

Behavior change of TMath::AreEqualAbs()

The TMath::AreEqualAbs() compares two numbers for equality within a certain absolute range. So far, it would tell you that inf != inf if you define inf as std::numeric_limits<double>::infinity(), which is inconsistent with the regular == operator.

This is unexpected, because one would expect that if two numbers are considered exactly equal, they would also be considered equal within any range. Therefore, the behavior of TMath::AreEqualAbs() was changed to return always true if the == comparison would return true.

RooFit Libraries

Changes in RooFormulaVar and RooGenericPdf

The TFormula-based RooFit classes RooFormulaVar and RooGenericPdf change a bit their behavior to be more consistent:

  1. No matter which variables you pass to the constructor, only the variables that the formula depends on are registered as value servers.
  2. Similarly, the dependents() method of RooFormulaVar and RooGenericPdf will only return the list of actual value servers.

Removal of the RooGenFunction and RooMultiGenFunction classes

The RooGenFunction was only a lightweight adaptor that exports a RooAbsReal as a ROOT::Math::IGenFunction. The same can be easily achieved with the generic ROOT::Math::Functor1D, so in the spirit of not duplicating interfaces, the RooGenFunction is removed in this release.

Here is an example that shows how to replace it in the unlikely case you were using it:

RooArgSet normSet{x}; // normalization set

// Old way 1: create a RooGenFunction:
RooGenFunction func1{pdf, x, {}, normSet};

// Old way 2: use `RooAbsReal::iGenFunction()`:
std::unique_ptr<ROOT::Math::IGenFunction> func2{
    pdf.iGenFunction(x, normSet)
};

// How to do it now:
RooFunctor functor{pdf, x, {}, normSet};
ROOT::Math::Functor1D func3{functor};
// Functor1D takes by reference, so the RooFunctor also needs to stay alive.

For the same reason, the RooMultiGenFunction class that implements a multidimensional ROOT::Math::IMultiGenFunction is removed too. It can easily be replaced by a ROOT::Math::Functor:

RooFunctor functor{pdf, observables, {}, normSet};
ROOT::Math::Functor func4{functor, static_cast<unsigned int>(functor.nObs())};
// Functor takes by reference, so the RooFunctor also needs to stay alive.

Define infinity as std::numeric_limits<double>::infinity()

RooFit has its internal representation of infinity in RooNumber::infinity(), which was 1e30 before.

Now, it is defined as std::numeric_limits<double>::infinity(), to be consistent with the C++ standard library and other code.

This change also affects the RooNumber::isInfinite() function.

Remove add(row, weight, weightError) from RooAbsData interface

It was not good to have this signature in RooAbsData, because the implementations in the two derived classes RooDataHist and RooDataSet were inconsistent.

The RooDataSet indeed took the weight error as the third argument, but the RooDataHist version instead took the sum of weights squared, which is equivalent to the squared weight error.

Therefore, the virtual RooAbsData::add(row, weight, weightError) function was removed.

Removal of RooMomentMorphND class

The RooMomentMorphND and RooMomentMorphFuncND were almost exactly the same, only that one inherited from RooAbsPdf and the other from RooAbsReal.

Thanks to the RooWrapperPdf, this code duplication in the RooFit implementation can now be avoided. Instead of using the removed RooMomentMorphND (which is the pdf), you now need to use the RooMomentMorphFuncND, change its behavior to exactly match the former RooMomentMorphND, and then wrap it into a pdf object:

RooMomentMorphFuncND func{<constructor args you previously passed to RooMomentMorphFunc>};

func.setPdfMode(); // change behavior to be exactly like the former RooMomentMorphND

// Pass the selfNormalized=true` flag to the wrapper because the
RooMomentMorphFuncND already normalizes itself in pdf mode.
RooWrapperPdf pdf{"pdf_name", "pdf_name", func, /*selfNormalized=*/true};

Removal of several internal classes from the public RooFit interface

Several RooFit classes of which the headers are publicly exposed in the interface were only meant as implementation details of other RooFit classes. Some of these classes are now removed from the public interface:

  1. RooGenProdProj, which was an implementation detail of the RooProdPdf
  2. RooScaledFunc, which was an implementation detail of the plotting in RooFit In the supposedly very rare case where you used this class in your own implementations, just multiply the underlying RooAbsReal function with the scale factor and create a RooRealBinding, e.g.:

    instead of:

  3. The RooAbsRootFinder, which was the base class of RooBrentRootFinder. The RooAbsRootFinder was only used as the base class of RooBrentRootFinder, which is an implementation detail of several RooFit/RooStats functions. However, polymorphism never not relevant for root finding, so the RooAbsRootFinder is removed. In the rare case where you might have used it, please ROOT’s other functionalities: RooFit is not for root finding.
  4. The RooFormula class, which was not meant as a user-facing class, but as a shared implementation detail of RooFormulaVar and RooGenericPdf.
  5. The RooIntegratorBinding, which was an implementation detail of the RooIntegrator2D and RooSegmentedIntegrator2D classes.
  6. The RooRealAnalytic, which was an implementation detail of the RooRealIntegral class.

Consistent default for Extended() command in RooAbsPdf::fitTo() and RooAbsPdf::chi2FitTo()

If no RooFit::Extended() command argument is passed, RooAbsPdf::chi2FitTo() method now does an extended fit by default if the pdf is extendible. This makes the behavior consistent with RooAbsPdf::fitTo(). Same applies to RooAbsPdf::createChi2().

TMVA

SOFIE : Code generation for fast inference of Deep Learning models

TMVA SOFIE now supports parsing and further inference of Graph Neural Networks based on DeepMind’s graph_nets. The list of all operators supported in the RModel class is the one provided below for the ONNX parser.

SOFIE-GNN

  1. The SOFIE-GNN implementation brought a major change in SOFIE’s architecture. Instead of having only the RModel class to store model information, now SOFIE has RModel, RModel_GNN and RModel_GraphIndependent classes which are inherited from RModel_Base.
  2. RModel_GNN is used to store a GNN model having nodes, edges, and globals with functions for their update and aggregate(for inter-relationships).
  3. RModel_GraphIndependent is used to store an independent Graph model with nodes, edges and globals with their individual update functions.
  4. RFunctions are used to declare update/aggregate operations over graph components. Currently supported RFunctions include:
  5. Pythonized functions for parsing a Graphnets’ model can be used to generate inference code
   import graph_nets as gn
   from graph_nets import utils_tf

   GraphModule = gn.modules.GraphNetwork(
      edge_model_fn=lambda: snt.nets.MLP([2,2], activate_final=True),
      node_model_fn=lambda: snt.nets.MLP([2,2], activate_final=True),
      global_model_fn=lambda: snt.nets.MLP([2,2], activate_final=True))

   GraphData = get_graph_data_dict(2,1,2,2,2)

   model = ROOT.TMVA.Experimental.SOFIE.RModel_GNN.ParseFromMemory(GraphModule, GraphData)
   model.Generate()
   model.OutputGenerated()

A complete tutorial for the SOFIE-GNN implementation can be found here

SOFIE ONNX Parser

The ONNX parser supports now several new ONNX operators. The list of the current supported ONNX operator is the following: - Gemm - Conv (in 1D,2D and 3D) - RNN, GRU, LSTM - Relu, Selu, Sigmoid, Softmax, Tanh, LeakyRelu - BatchNormalization - MaxPool, AveragePool, GlobalAverage - ConvTranspose - Gather - Expand, Reduce - Neg, Exp, Sqrt, Reciprocal - Add, Sum, Mul, Div - Reshape, Flatten, Transpose - Squeeze, Unsqueeze, Slice - Concat, Reduce - Identity - Shape - Custom - Error - Log

SOFIE Keras Parser

2D Graphics Libraries

Machine Learning integration

Language Bindings

JavaScript ROOT

Tutorials

Class Reference Guide

Build, Configuration and Testing Infrastructure

root-config (and many other versioning interfaces) now reports 6.30.00 instead of 6.30/00. This allows many tools to understand ROOT’s version number, better than before.

If -Droottest=ON is specified, the ROOT build system used to clone a matching branch of the roottest repository. This logic has been improved and is now as follows:

Bugs and Issues fixed in this release

Release 6.30/02

Published on November 27, 2023

Bugs and Issues fixed in this release

This release addresses a security issue. More details will follow.

Release 6.30.04

Published on January 31, 2024

Bugs and Issues fixed in this release

This release addresses many items, thanks to an effort made during the break at the end of the year. Not only problems were removed, but runtime performance was greatly improved, especially the one of the interpreters. The memory footprint of the plugin manager has been reduced. Moreover, the mechanism by which symbols are looked up by the interpreter was improved, avoiding to open and close a large number of libraries at startup, which improves considerably the user experience as well as cpu efficiency on batch jobs. More verbose output is now provided if wrong settings are used for the web-based widgets, the usage of the loopback device is enforced and only one connection is allowed to RBrowser.

HEAD of the v6-30-00-patches branch

These changes will be part of a future 6.30.06.