ROOT Version 6.42 Release Notes

2026-11-15

Introduction

ROOT version 6.42.00 is scheduled for release in November 2026.

For more information, see:

http://root.cern

The following people have contributed to this new version:

Bertrand Bellenot, CERN/EP-SFT,
Jakob Blomer, CERN/EP-SFT,
Lukas Breitwieser, CERN/EP-SFT,
Philippe Canal, FNAL,
Olivier Couet, CERN/EP-SFT,
Marta Czurylo, CERN/EP-SFT,
Florine de Geus, CERN/EP-SFT and University of Twente,
Andrei Gheata, CERN/EP-SFT,
Jonas Hahnfeld, CERN/EP-SFT and Goethe University Frankfurt,
Fernando Hueso Gonzalez, IFIC (CSIC-University of Valencia),
Stephan Hageboeck, CERN/EP-SFT,
Aaron Jomy, CERN/EP-SFT,
Sergey Linev, GSI Darmstadt,
Lorenzo Moneta, CERN/EP-SFT,
Vincenzo Eduardo Padulano, CERN/EP-SFT,
Giacomo Parolini, CERN/EP-SFT,
Danilo Piparo, CERN/EP-SFT,
Jonas Rembser, CERN/EP-SFT,
Silia Taider, CERN/EP-SFT,
Devajith Valaparambil Sreeramaswamy, CERN/EP-SFT,
Vassil Vassilev, Princeton,
Sandro Wenzel, CERN/EP-ALICE,
Tristan Wenzel, ETHZ,

Deprecation and Removal

Build System

CMake version

CMake versions below 3.26 will emit a warning during configure, since they will become obsolete soon: CMake 3.26 will be the minimum required in ROOT 6.44. It is the version shipped with RHEL 8.10, which is the oldest Linux distribution supported by that release.

After ROOT 6.44, the minimum may rise to 3.31 if an upgrade to LLVM 24 or later is performed, see the minimum version of CMake required by LLVM.

Optimization of ROOT header files

In ROOT 6.22, many (but not all) unused includes were removed from ROOT header files. The remaining unused includes will be removed after ROOT 6.44. For instance, #include "TBuffer.h" will be removed from TKey.h. This change may cause errors during compilation of ROOT-based code if one was implicitly relying on this transitive include on downstream code using TBuffer without actually including TBuffer.h. Another example: TStyle.h no longer includes internally TArrayI.h. To fix it well in advance on your side in downstream code, since no warnings are emitted in the meantime, we recommend getting a preview of those to-be errors by adding in your code #define R__LESS_INCLUDES, adding this at the very top before including any ROOT header. An alternative is to define this on CMake side via target_compile_definitions. This may also improve compile time and reduce code inter-dependency; see https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/WhyIWYU.md for a good overview of the motivation. The macro R__LESS_INCLUDES will no longer have an effect after ROOT 6.44 since it will be the new default behavior. Note: if you build ROOT with option dev=ON, the header RConfigure.h will already contain that definition, so in that case consider just including RConfigure.h at the very top, rather than redefining R__LESS_INCLUDES in downstream code, or alternatively guard the definition with #ifndef.

Moving from builtin dependencies to system-provided packages

Python Interface

ROOT dropped support for Python 3.10, meaning ROOT now requires at least Python 3.11.

Connecting Python callables to signals

TQObject::Connect() now directly accepts a Python callable as the slot, for example button.Connect("Clicked()", on_clicked). The arguments emitted by the signal are forwarded to the callable, as far as its signature accepts them, and the connection keeps the callable alive. Use Disconnect(signal, callable) to undo the connection. Signals of any signature are supported, no longer only those covered by the TPyDispatcher::Dispatch() overloads.

The TPyDispatcher class and its ROOT/TPyDispatcher.h header are removed: it required the user to create and keep alive a dispatcher object manually, and it was broken in recent releases anyway, since the interpreter could not resolve its symbols from the libROOTPythonizations Python extension module. Replace obj.Connect(signal, "TPyDispatcher", disp, "Dispatch()") with obj.Connect(signal, callable).

I/O

RFile

RFile, ROOT’s modern interface to ROOT file, has moved out of the ROOT::Experimental namespace.

RNTupleProcessor

The RNTupleProcessor is a new, standalone interface for creating chains (similar to TTree’s TChain) and joins (similar to TTree friends) from RNTuples in a composable way, and iterating over their entries. Until this release, it was available in the experimental namespace. With ROOT v6.42:

RNTuple SoA I/O

The RNTuple SoA I/O classes moved out of experimental. These classes and the related dictionary options provide a mechanism to read and write a collection of a class, i.e. an “array of struct” (AoS), as “struct of array” (SoA) in memory. This is useful, e.g., for efficient consumption of data structures by GPUs. This new feature comes with a technical documentation (SoA.md) and a tutorial (ntpl020_SoA.C).

Core

Histograms

Cumulative histograms in more than one dimension

TH1::GetCumulative() now computes a true multi-dimensional cumulative for 2D (TH2) and 3D (TH3) histograms, using the inclusion-exclusion principle: each bin of the result holds the sum of all bins whose indices are no greater than (forward) or no less than (backward) those of the target bin along every axis. Previously the method accumulated a single running sum over the flattened bin iteration, which did not correspond to a meaningful cumulative distribution in more than one dimension.

The behavior for one-dimensional histograms is unchanged. Code that relied on the previous 2D/3D output (for example to build per-axis selection efficiency maps) will now obtain different, mathematically consistent values.

New histogram package

The new histogram package continues development in the ROOT::Experimental namespace. This release introduces RHistEngine::SnapshotAtomic to obtain a consistent copy during concurrent filling. There is now a class ROOT::Experimental::RProfile for (multidimensional) profile histograms. RHist and RHistEngine with two or three dimensions can be converted to TH2 or TH3. More conversion functions will continue to be added in the future (THn, TProfile).

Math

Skipping identically-vanishing second derivatives in numerical Hessian evaluation

Minuit2 objective functions can now advertise pairs of parameters whose mixed second derivative is identically zero, via the new virtual function ROOT::Minuit2::FCNBase::SecondDerivativeAlwaysVanishes() (with corresponding setters on ROOT::Minuit2::FCNAdapter and ROOT::Minuit2::Minuit2Minimizer). The numerical Hessian computation in Minuit2 (MnHesse) skips the finite-difference evaluations for such parameter pairs, which can speed up Hesse significantly for likelihoods with many mutually independent parameters. The parameter indices in this interface always refer to the function’s own full (external) parameter space, including parameters that are fixed in the minimizer, and the advertised information must hold for all parameter values; see the FCNBase documentation for the full contract.

RDataFrame

Trees

Behavior change: sqrt() of negative arguments in TTreeFormula now returns NaN

Since its introduction in 1995, the formula engine used by TTree::Draw(), TTree::Scan() and TTreeFormula silently evaluated sqrt(x) as sqrt(abs(x)) for negative arguments (or as 0 in the optimized evaluation path of the legacy ROOT::v5::TFormula). This could produce silently wrong results, e.g. in selections involving sqrt of an expression that can become negative. sqrt() now returns NaN for negative arguments, consistent with TMath::Sqrt(), the standard C sqrt(), and the modern TFormula used by TF1. Note that in a selection, a NaN evaluates as false, so entries where the sqrt argument is negative now fail the cut instead of being selected based on sqrt(abs(x)).

RooFit

RooFit::MultiProcess without ZeroMQ, now enabled by default

The RooFit::MultiProcess package that implements the parallel gradient minimization with fitTo(..., RooFit::Parallelize(n)) previously communicated between the forked processes with ZeroMQ sockets, which required building ROOT with roofit_multiprocess=ON and the ZeroMQ (with draft API) and cppzmq dependencies. The interprocess communication is now implemented directly on top of plain socketpair() pipes that are inherited by the forked worker processes, so the ZeroMQ and cppzmq dependencies and the RooFitZMQ library are removed entirely. Since the feature no longer needs extra dependencies, it is now always built on non-Windows platforms and the roofit_multiprocess build option has no effect anymore; it is deprecated and will be removed in ROOT 6.44. For implementers of custom RooFit::MultiProcess::Job subclasses, the message type in the Job interface changed from zmq::message_t to the new RooFit::MultiProcess::Message byte-buffer class, which supports the same usage patterns.

Small changes

Faster Hesse for likelihoods with many independent parameters

RooFit now analyzes the computation graph of the minimized function to find pairs of parameters that never appear in the same additive term of the likelihood, meaning their mixed second derivative is identically zero. This information is forwarded to Minuit2, which skips the corresponding finite-difference evaluations in the numerical Hessian computation (see the Math section above). For likelihoods with many mutually independent parameters, such as the per-channel nuisance parameters of large combined HistFactory models, this can speed up RooMinimizer::hesse() by 30 % or more, with results identical up to floating-point noise. This optimization is automatic and requires no user action.

Deprecation of the legacy evaluation backend

The legacy evaluation backend for likelihood and chi-square fits is deprecated and will be removed in ROOT 6.44. It was superseded by the vectorized cpu backend, which is the default since ROOT 6.32. After the removal of the constant term optimization (see below), the legacy backend also has no performance-relevant feature left that would justify its continued maintenance.

Selecting the legacy backend with RooFit::EvalBackend("legacy") now prints a deprecation warning whenever a likelihood or chi-square object is created with it, and the RooFit::EvalBackend::Legacy() factory function is marked as deprecated, resulting in compiler warnings.

The RooFit::BatchMode() command argument, which was superseded by RooFit::EvalBackend() in ROOT 6.28, is deprecated at the same time and will also be removed in ROOT 6.44. Note that the C++ declarations of RooFit::BatchMode() had been unintentionally absent since ROOT 6.30; they are restored in this release, marked as deprecated, to give downstream code a proper migration window.

The removal in ROOT 6.44 will also include:

Users are strongly encouraged to switch to the default cpu evaluation backend, i.e., to simply not pass any EvalBackend() or BatchMode() command argument. If the default backend does not work for a given use case, please report it by opening an issue on the ROOT GitHub repository.

Removal of the constant term optimization for legacy test statistic classes

The RooFit::Optimize() option (constant term optimization) was deprecated in ROOT 6.40, and its functionality is now removed. The RooFit::Optimize() and RooMinimizer::optimizeConst() methods are kept for API consistency across ROOT versions, but they have no effect anymore.

In practice this option only affected the legacy evaluation backend.

Together with the mechanism itself, the public interfaces that only existed to drive it were removed. Code that called or overrode any of the following needs to be adapted:

Since the cache-and-track hints are gone, the "CacheAndTrack", "NOCacheAndTrack" and "NeverConstant" attributes no longer have any effect.

The default vectorized CPU evaluation backend (introduced in ROOT 6.32) already performs these optimizations automatically and is not affected by this change. Users are strongly encouraged to switch to the vectorized CPU backend if they are still using the legacy backend.

If the vectorized backend does not work for a given use case, please report it by opening an issue on the ROOT GitHub repository.

Default binning of RooFit variables changed to zero bins

A freshly-constructed RooRealVar (or RooErrorVar) no longer has a default binning of 100 bins. Instead, RooAbsRealLValue::getBins() now returns 0 until a binning is explicitly set (e.g. via RooRealVar::setBins()). This makes it possible to distinguish a variable whose binning was deliberately chosen from one that was left at the default, which avoids writing redundant nbins fields when serializing workspaces to HS3 JSON.

For the cases that previously relied on the default of 100 bins, that value is now injected by the relevant routine: unbinned-dataset plotting (RooAbsRealLValue::frame()), RooAbsPdf::generateBinned(), and RooAbsRealLValue::createHistogram() all fall back to RooAbsRealLValue::DefaultNBins (100) when the variable has no binning set. As a result, plotting, generating binned data and creating histograms from a default-constructed variable behave exactly as before.

Code that reads getBins()/numBins() of a bare variable and expected the value 100 should either set the binning explicitly, or read the bin count from the relevant histogram or plot frame instead.

Resolution models are no longer imported into the workspace as standalone objects

When a RooResolutionModel (like RooGaussModel or RooTruthModel) is used wi th a RooAbsAnaConvPdf (like RooDecay, RooBDecay, etc.), it acts as a configuration object that specifies which model to convolve the basis functions with, rather than as a nod e of the pdf’s computation graph. The RooAbsAnaConvPdf builds its own internal basis-function convolutions from it and evaluates those.

Until now, the resolution model was nevertheless kept as a (non-value, non-shape) server of the RooAbsAnaConvPdf. As a side effect, importing such a pdf into a RooWorkspace also imported the original resolution model as a standalone workspace object, and it leaked into HS3/JSON exports, even though it played no role in the computation.

Starting with ROOT 6.42, a resolution model that is only used as the configuration of a RooAbsAnaConvPdf is no longer a server of that pdf, and is therefore not imported into the workspace on its own anymore. The model remains accessible via RooAbsAnaConvPdf::getModel().

This is not expected to affect typical usage, since the resolution model was never part of the actual likelihood. Workspaces written with older ROOT versions are read back correctly via schema evolution.

Graphics and GUI

New POLF and POLN draw options for TH2

Since ROOT 6.36 implementation of “POL” draw option was changed. Angle and radius range automatically scaled to visible histogram range filling full 2*Pi angle and full radius range. This let display TH2 in polar coordinates for any provided range settings, but produced plots are not intuitive. Therefore two new options for polar coordinates were introduced.

“POLF” - fixed polar coordinates. In such case full histogram X range mapped to -PI .. +Pi. And Y axis mapped to radius. In case of histogram zooming angle and radius of each bin remains the same (therefore name “fixed”), just number of displayed bins are reduced.

“POLN” - natural polar coordinates. In this case X axis directly represents angle value in radians (therefore name “natural”) and Y axis is just radius.

Store canvas as HTML file

Now canvas (or several canvases) can be stored in portable HTML file. Just call c1->SaveAs("canvas.html") or invoke correspondent menu item. To store several canvases in single HTML file one can use:

   auto c1 = new TCanvas("c1", "c1", 4);
   auto c2 = new TCanvas("c2", "c2", 4);
   auto c3 = new TCanvas("c3", "c3", 4);
   TCanvas::SaveAll({c1, c2, c3}, "canvases.html");

Produced HTML file will include canvas JSON data and JavaScript code to load and display canvas. Such file can be loaded locally in any web browser or send as attachment in email to colleagues.

Other graphics improvements

Geometry

Improved multithreaded TGeo navigation

Multithreaded TGeo navigation is now faster and more scalable, with improved thread-local state management that avoids false sharing, releases temporary memory during geometry cleanup, and correctly supports concurrent navigation of multiple geometries.

For ALICE material-budget lookup-table generation on 28 cores, these changes reduced the runtime from 139 s to 72 s and improved scaling from 12x to 23x.

The TGeometry classes (Geant 3 shapes) have been moved out of Graf3D into their own library. To link to these classes, use the cmake target TGeometry (preferred), root-config --libs, or link with -lTGeometry. When ROOT is configured with -Dgeom=Off, these classes are now off as well.

The header X3DBuffer.h is no longer part of the installed ROOT headers.

Documentation and Examples

Build, Configuration and Testing

Building the CUDA backend of RooFit separately

RooFit evaluates its models with backend libraries that libRooBatchCompute loads at runtime, one of which, libRooBatchCompute_CUDA, is the only part of ROOT that requires the CUDA toolkit. It is now possible to build that backend on its own against an already installed ROOT, so that distributions can ship a CUDA-free ROOT and provide the GPU backend as a separate package:

cmake -S <root-source-dir>/roofit/batchcompute -B build -DCMAKE_PREFIX_PATH=<root-install-prefix>
cmake --build build
cmake --install build

roofit/batchcompute/CMakeLists.txt doubles as the top-level CMakeLists.txt of that standalone project, so no CMake code has to be maintained downstream. By default the library is installed into the library directory of the ROOT installation it was configured against, which is where RooFit looks for it. See roofit/batchcompute/README.md for the details. Nothing changes for the regular ROOT build: -Dcuda=ON still builds the CUDA backend together with everything else.

Built-in packages

It is strongly recommended to rely on sytem packages, and not built-in ones. All the built-in packages are now collected in the builtins directory. The version of the following packages has been updated:

Tracker Items addressed

More than 180 items in ROOT’s trackers have been addressed in this release: