ROOT 6.36.00, released on May 26th 2025, is the first release of the
ROOT 6.36 LTS cycle. The new ROOT comes with many great features that
have the potential of making you even more productive - see release
notes below. The effort made by the contributors, experiments and core
developers is testified by the 202 items in the ROOT trackers that have
been addressed for this release.
As previously announced, the 6.36 cycle supersedes the STS 6.34 one,
which will be stopped in June.
The following people have contributed to this new version:
Samantha Abbott, UC Davis,
Bertrand Bellenot, CERN/EP-SFT,
Jakob Blomer, CERN/EP-SFT,
Lukas Breitwieser, CERN/EP-SFT,
Will Buttinger, RAL,
Philippe Canal, FNAL,
Emanuele Chiamulera, University of Padova
Eric Cano, CERN/EP-SFT Olivier Couet, CERN/EP-SFT,
Marta Czurylo, CERN/EP-SFT,
Tomas Dado, CERN/EP-ADP,
Monica Dessole, CERN/EP-SFT,
Mattias Ellert, Uppsala University,
Mateusz Fila, CERN EP-SFT,
Martin Føll, CERN/EP-SFT and University of Oslo,
Declan Garvey, CSIC/University of Valencia,
Florine de Geus, CERN/EP-SFT and University of Twente,
Massimiliano Galli, Princeton,
Jamie Gooding, TU Dortmund,
Jonas Hahnfeld, CERN/EP-SFT and Goethe University Frankfurt,
Fernando Hueso Gonzalez, CSIC/University of Valencia,
Stephan Hageboeck, CERN/EP-SFT,
Aaron Jomy, CERN/EP-SFT,
Marta Krawczyk, CERN/EP-AID,
Vit Kucera, Inha University,
Stephanie Kwan, Princeton,
Sergey Linev, GSI Darmstadt,
Enrico Lusiani, INFN Padova,
Alberto Mecca, University of Turin,
Lorenzo Moneta, CERN/EP-SFT,
Mark Owen, University of Glasgow,
Vincenzo Eduardo Padulano, CERN/EP-SFT,
Giacomo Parolini, CERN/EP-SFT,
Daniel Perez Astudillo, QEERI/HBKU,
Danilo Piparo, CERN/EP-SFT,
Alexandr Prozorov, CTU Prague,
Jonas Rembser, CERN/EP-SFT,
Grigori Rybkin, Paris-Saclay University,
Manuel Tobias Schiller, University of Glasgow,
Surya Somayyajula, UMass Amherst,
Petr Stepanov, @petrstepanov,
Maciej Pawel Szymanski, ANL,
Andres Rios, Princeton,
Sanjiban Sengupta, CERN/EP-SFT and Manchester University,
Silia Taider, CERN/EP-SFT,
Florian Uhlig, GSI,
Devajith Valaparambil Sreeramaswamy, CERN/EP-SFT,
Vassil Vasilev, Princeton,
Dongliang Zhang, University of Science and Technology of China
Deprecation and Removal
The RooFit legacy interfaces that were deprecated in ROOT 6.34 and
scheduled for removal in ROOT 6.36 are removed. See the RooFit section
in the 6.34 release notes for a full list.
The TPython::Eval() function that was deprecated in
ROOT 6.34 and scheduled for removal in ROOT 6.36 is removed.
The RooDataSet constructors to construct a dataset from
a part of an existing dataset are deprecated and will be removed in ROOT
6.38. This is to avoid interface duplication. Please use
RooAbsData::reduce() instead, or if you need to change the
weight column, use the universal constructor with the
Import(), Cut(), and WeightVar()
arguments.
The ROOT splash screen was removed for Linux and macOS
Proof support has been completely removed from RooFit and RooStats,
after it was already not working anymore for several releases
The build options mysql, odbc,
pgsql have been deprecated. Please complain with
root-dev@cern.ch should you still need one!
The build options html and qt5web have
been removed.
The ClassImp macro and derived macros have no effect now and will be
deprecated in ROOT 6.38.
The default TTreeFormula constructor (without arguments) is now
deleted, since it lead to an unusable and unsafe object. Instead, this
implementation has been reserved now for ROOT I/O exclusively via the
TRootIOCtor argument tag.
The RooStats::HLFactory class was deprecated will be
removed in ROOT 6.38. It provided little advantage over using the
RooWorkspace directly or any of the other higher-level frameworks that
exist in the RooFit ecosystem.
Python Interface
UHI
ROOT histograms now comply with the Unified Histogram
Interface (UHI) specification, enhancing interoperability with other
UHI-compatible libraries and standardizing histogram operations. The
following features were added:
Implemented the UHI PlottableHistogram protocol
enabling ROOT histograms to be plotted by any library supporting
PlottableHistogram objects.
Introduced UHI-style indexing for access and setting bin
values.
Introduced UHI-style slicing for selecting histogram ranges.
Implemented the ROOT.uhi.loc,
ROOT.uhi.underflow, ROOT.uhi.overflow,
ROOT.uhi.rebin, and ROOT.uhi.sum tags.
Core Libraries
Existing code can now be interpreted and just-in-time compiled
according to the C++23 standard for the platforms that support it. The
new standard can be enabled with the CMake option
-DCMAKE_CXX_STANDARD=23.
RDataFrame
When running multiple computation graphs concurrently using RunGraphs(),
the pool of slot numbers that a thread can pick from is now shared
across all graphs. This enables use cases where a single resource, which
may be expensive to create or copy, is shared across tasks belonging to
different computation graphs.
RDataFrame’s RResultPtr now allow direct access to the underlying
shared_ptr using GetSharedPtr().
See also the new tutorial df040
for details of lifetime management of RDataFrame results.
Support for single-threaded snapshotting to RNTuple has been
added. This can be enabled through RSnapshotOptions. Note
that snapshotting from a TTree-based RDataFrame to RNTuple is not yet
supported in this release, but will be added in a future version. The
current recommended way to convert from TTree to RNTuple is through the
RNTupleImporter.
The support for reading CSV file inputs has been extended with
the following capabilities:
Left/right trimming
Skipping of a given number of header/footer lines
Comment character to skip lines / line remainders
Override column names
The Display operation has been extended to support
different printing options. Notably, it now includes the possibility to
display the table in Markdown or HTML formats. When using RDataFrame in
an IPython-based environment, e.g. a Jupyter notebook, the output format
will be HTML by default. This will be parsed and displayed nicely in the
notebook cell output.
The RNTuple data source has been moved out of the experimental
namespace, now in namespace ROOT::RDF. In the transition,
the support to read a raw RNTuple pointer was removed in order to ensure
a simpler and more sustainable API.
The Report action is now supported in the case of
systematic variations, i.e. it is now possible to call
VariationsFor(report). This produces the usual map of
varied Report nodes.
New alerts have been put in place when a user requests entry
ranges out of the bounds of the data source, addressing the following
situations (nEntries is the total number of entries in the dataset):
begin<nEntries or end>nEntries:
raise a warning at the end of the execution
begin==nEntries: throw an exception as soon as this is
detected
Fixed a faulty interaction between sample paths in an RDataFrame
execution and the corresponding redirected URL in case the path is
pointing to a FUSE-mounted EOS location. The map of available samples
now contains both the FUSE-mounted location and the redirected xroot
URL. For more info, see
https://github.com/root-project/root/pull/17544.
The RNTuple data source now follows the automatic conversion to
ROOT::RVec in-memory when the corresponding on-disk type of
the column is one of ROOT::RVec, std::vector,
std::array. This follows the same logic used for TTree. In
all other cases, the RNTuple data source will use the same in-memory
type as the on-disk type.
The Python usability of RDataFrame when reading a TTree-based
dataset with a TChain has been improved. Specifically, the ownership of
the TChain is now shared between the RDataFrame object(s) and the Python
interpreter. The following Python function would have previously
returned an RDataFrame with a dangling reference to the underlying
dataset, whereas now the TChain will stay alive as long as the
RDataFrame will:
A new option for Snapshot has been added to the
RSnapshotOptions, namely the possibility to specify the
output TTree basket size. Users can set the fBasketSize
data member to the desired basket size.
The RNTuple data source now supports reading the same column with
different valid column types, for example reading a
std::vector<T> column as
ROOT::RVec<T> and vice-versa. An exception is thrown
in case a requested type is incompatible with the actual column
type.
The treatment of TTree datasets in RDataFrame has been completely
overhauled and is now aligned with all other data sources, i.e. a new
RDataSource-derived class was introduced to manage TTree
processing. These changes are completely transparent to the user, but
improve sustainability of the code base. At the same time, the need to
JIT the column readers for TTree dataset was removed thus slightly
improving runtime performance.
The behaviour of Snapshot with the TTree output in
case no entries pass the selections has been changed. Now, both in
single- and multi-thread mode, the operation will produce an output
file, with a TTree inside. The TTree will contain the complete dataset
schema (i.e. the column names) requested during the
Snapshot call and it will have no entries.
It is now possible to read a string column type with a
pandas.DataFrame data source.
It is now possible to create an RDataFrame wrapping an empty
pandas.DataFrame, as long as all the columns of the
pandas.DataFrame are of supported types.
The behaviour of AsNumpy has been modified,
depending on whether the input column type is a scalar or collection. In
the case of scalar, the output numpy array will have its
dtype of the corresponding Python type when the input type
is a fundamental type (e.g. integer or float). Columns containing
non-fundamental types will result in a numpy array with
dtype=object. In the case of a collection, the output numpy
array will have dtype=object, where each element is itself
a numpy array representing the collection for its corresponding entry in
the column. If the collection at a certain entry contains values of
fundamental types, or if it is a regularly shaped multi-dimensional
array of a fundamental type, then the numpy array representing the
collection for that entry will have the dtype associated
with the value type of the collection. If the collection at a certain
entry contains values of a non-fundamental type, it will be represented
as a numpy array with dtype=object.
Distributed RDataFrame
The local and distributed APIs of RDataFrame have been made
completely uniform. Using the keyword argument executor, an
RDataFrame can run on a distributed set of nodes. Furthermore,
distributed RDataFrame (ROOT.RDF.Distributed) is now out of
the experimental namespace. We recommend that users switch to using the
new version as soon as possible. Note the following changes between the
old and the new code:
# Old version - not recommended:# This will still work in 6.36 but will raise a warningconnection = ... # your distributed Dask client or SparkContextRDataFrame = ROOT.RDF.Experimental.Distributed.[Backend].RDataFramedf = RDataFrame(..., [daskclient,sparkcontext] = connection)# New version - recommendedconnection = ... # your distributed Dask client or SparkContextdf = ROOT.RDataFrame(..., executor = connection)
In case of using the old version, with Experimental
keyword, a warning will be raised. In ROOT 6.38, the
Experimental name will be removed completely and using it
will result in an exception.
A set of new features is now available to the distributed RDataFrame
users:
It is now much easier to inject the C++ code into the distributed
RDF application. The following functions are available:
DistributeHeaders - include and distribute headers
DistributeSharedLibs - load and distribute shared libraries
DistributeCppCode - declare and distribute the C++ code, the C++
code is available to all dataframes in the application
DistributeFiles - distribute other files (not headers or shared
libraries) that may be needed
The factory function FromSpec is available to build
the distributed RDF. Note, however, the addition and use of the metadata
is not yet supported.
Support for the following API operations was added to distributed
RDataFrame:
Alias
DefaultValueFor
FilterAvailable
FilterMissing
RooFit
Breaking function signature
changes
The RooRealVar::format() function was changed to return
a std::string instead of a TString *. The
former return type was not memory safe, since the caller had to delete
the TString. This pattern was not appropriate for a modern
C++ library. If you absolutely need the old return type, wrap the call
to format() inside
new TString{var.format(..)}. However, this is not
recommended.
Fix for
RooAbsReal::createHistogram() with extended pdfs
There was a problem with RooAbsReal::createHistogram()
when using it to get histograms with predicted yields for extended pdfs.
The Scale(bool) argument was always set internally to
false in case createHistogram() was called on
an extended pdf. There was no way for the user to override that. This
meant that one could not get yield histograms that were correctly scaled
by the bin volumes using that function. This release changes that
behavior, meaning the Scale(bool) command argument is now
respected for extended pdfs.
RooCrystalBall improvements
Fitting instabilities in the RooCrystalBall class (as well as in
TMath’s cbShape function) with high N parameter have been mitigated by
reorganizing the code implementation.
I/O
Honour the Davix.GSI.CACheck parameter also in the
ROOT::Internal::RRawFileDavix class.
Added support for enum class with a non default
underlying size, for example enum smallenum: std::int16_t.
The default is 32 bits. All enums, independently of their in memory size
are stored on file using 32 bits to enable forward compatibility of the
file; files created with a enum class with a non default
underlying size can be read with old version of ROOT into a
enum type of default size.
Note: enum class with an underlying size strictly
greater than 32 bits are not supported since they would be truncated
when stored on file.
The version number of TStreamerInfo has been increase
to 10 to encoded the addition of the support for enum class
with a non default underlying size. This allows the opportunity to
detect files written by old version of ROOT (v9 and older
of TStreamerInfo) where enum class with a non
default underlying size where stored incorrectly but recoverably. Those
files can be recover by using I/O customization rules that takes in
consideration their size at the time of writing (this information is not
recorded in the ROOT file). See
https://github.com/root-project/root/pull/17009#issuecomment-2522228598
for some examples.
New attribute for I/O customization rules: CanIgnore.
When using this attribute the rule will be ignored if the input is
missing from the schema/class-layout they apply to instead of issue a
Warning
The logic to retrieve branch names of a TTree has been improved,
leading to O(10) speedup. For example, an RDataFrame wrapping a TTree
with O(10K) columns could be spending multiple minutes just to retrieve
the full dataset schema, whereas now it will take seconds.
RNTuple
Following the HEP-CCE
review of the RNTuple public API, the following types were moved
from the ROOT::Experimental to the ROOT
namespace:
DescriptorId_t
Detail::RFieldVisitor
ENTupleColumnType (renamed from
EColumnType)
ENTupleStructure
NTupleSize_t
RArrayAsRVecField
RArrayField
RAtomicField
RBitsetField
RCardinalityField
RClassField
RClusterDescriptor
RClusterGroupDescriptor
RColumnDescriptor
RCreateFieldOptions
REntry
REnumField
RExtraTypeInfoDescriptor
RField
RFieldBase
RFieldDescriptor
RFieldToken (moved from
REntry::RFieldToken)
RFieldZero
RIntegralField
RInvalidField
RMapField
RNTupleCardinality
RNTupleCollectionView
RNTupleDescriptor
RNTupleDirectAccessView
RNTupleFillStatus
RNTupleGlobalRange
RNTupleLocalRange (renamed from
RNTupleClusterRange)
RNTupleLocator
RNTupleLocatorObject64
RNTupleModel
RNTupleReader
RNTupleReadOptions
RNTupleView
RNTupleViewBase
RNTupleWriteOptions
RNTupleWriter
RNullableField
RPairField
RProxiedCollectionField
RRecordField
RRVecField
RSetField
RSimpleField
RStreamerField
RTupleField
RVariantField
RVectorField
New options have been added to TFileMerger (which can be passed as
whitespace-separated TStrings via
TFileMerger::SetMergeOptions)
“FirstSrcCompression”: when merging multiple files, instructs the
class-specific merger to use the same compression as the first object of
the destination’s class as the destination’s compression. Currently only
recognized by the RNTuple merger;
“DefaultCompression”: specifies that the merged output should use
the class-specific default compression. Currently only meaningful for
RNTuple, which has a default compression different from the TFile’s
default compression (ZSTD instead of ZLIB). This option is automatically
set by hadd when no other compression option is
specified;
“rntuple.MergingMode=(Filter|Union|Strict)”: RNTuple-specific option
that specifies the merging mode that should be used by the RNTupleMerger
(see RNTupleMergeOptions);
“rntuple.ErrBehavior=(Abort|Skip)”: RNTuple-specific option that
specifies the behavior of the RNTupleMerger on error (see link
above);
“rntuple.ExtraVerbose”: RNTuple-specific option that tells the
RNTupleMerger to emit more information during the merge process.
The option to explicitly pass a type name or
std::type_info to
RNTupleReader::GetView<void> has been added, in case
the on-disk type of the field differs from the underlying type of the
pointer to read into.
The RNTupleProcessor
has been extended to support joins (comparable to TTree
friends) and chains of joins. As an effect,
RNTupleReader::OpenFriends() has been removed. Note that
the RNTupleProcessor is still under active development and will remain
in the Experimental namespace.
Tutorials and Code Examples
The ROOT Tutorials have been modernized - we organized the
tutorials into new categories and added more informative descriptions to
each section. Some of the tutorials were fixed, renamed or moved to the
legacy folder but also new tutorials were added to showcase features not
represented before. We believe that interacting with the tutorials is
now much easier and more pleasant both for the new and old users. Have a
look here for
all the details.
add tutorials/visualisation/webgui/bootstrap example
showing usage of RWebWindow with bootstrap framework, including
embedding of TWebCanvas in the widget
Math
RooFit / HistFactory
An important bottleneck in HistFactory was removed when many
histograms are used to construct a measurement.
Performance
improvements in Minuit2 for the case of parameters with limits
For variable parameters with limits, Minuit2 applies trigonometric
transformations into an internal space for the minimization. This can be
a significant bottleneck for highly-optimized function, to the point
that this is also mentioned in section 1.3.1 of the old
MINUIT user’s guide. One prominent case of highly-optimized
functions are RooFit likelihoods, which are heavily caching intermediate
results to make numeric gradients and Hessians as efficient as possible.
This meant that e.g. for HistFactory likelihoods, a significant fraction
of the gradients and Hessians evaluation time was spent in the parameter
transformations. To alleviate this bottleneck, Minuit2 is now also
caching the result of the trigonometric transformations, only
recomputing them if a parameters value was changed. As a result, the
time spent in in parameter transformations when minimizing RooFit
likelihoods and evaluating the Hessian becomes negligible.
Graphics
SavePrimitive methods of all graphics-related classes were revised
and modernized. Objects with large arrays are stored more efficiently.
Many small bugs were found and fixed.
extend stressGraphics test on more use-cases, including
TSpline, TScatter, TEfficiency,
TProfile2D, TProfile3D,
TGraph2DErrors, TGraph2DAsymmErrors
classes
enable stressGraphics tests for web-based graphics
JavaScript ROOT
ROOT 6.36 will use JSROOT
7.9 release series. It includes following important changes:
Implement ‘nmatch’ parameter for TTree::Draw to limit
processed events
Implement ‘elist’ parameter for TTree::Draw to specify
entries list for processing
Implement ‘staged’ algorithm for TTree::Draw to first
select entries and then process only these entries
Implement ‘cont5’ draw option for TGraph2D using
Delaunay algorithm
Implement ‘pol’ and ‘arr_colz’ draw option for TH2
Only ‘col7’ draw option uses bar offset and width for color
TH2 drawing
Interactive zooming and context menu on ‘chord’ TH2
drawing
Implement ‘box1’ for TH3 with negative bins
Introduce settings.FilesTimeout to configure global
timeout for file reading operations
Introduce settings.FilesRemap to let provide fallback
address for http server, used for root.cern
Introduce settings.TreeReadBunchSize to configure bunch
read size for TTree processing
Adjust histogram title drawing with native implementation
Improve float to string conversion when ‘g’ is specified
Support ‘same’ option for first histogram, draw directly on pad
Display underflow/overflow bins when configured for the axis,
implement ‘allbins’ draw option for histograms
Support different angle coordinates in TGraphPolargram,
handle ‘N’ and ‘O’ draw options
Support fAxisAngle in TGraphPolargram, provide
‘rangleNN’ draw option
Implement ‘arc’ draw option for TPave
Provide context menus for all derived from TPave
classes
Let edit histograms and graphs title via context menu
Support Poisson errors for TH1/TH2,
https://root-forum.cern.ch/t/62335/
Test fSumw2 when detect empty TH2 bin, sync with
https://github.com/root-project/root/pull/17948
Support TLink and TButton object, used in
TInspectCanvas
Support TF12 - projection of TF2
Upgrade three.js r168 -> r174
Remove support of qt5 webengine, only qt6web can be used
Set ‘user-select: none’ style in drawings to exclude text selection,
using settings.UserSelect value
Internals - use private members and methods
Internals - use WeakRef class for cross-referencing of
painters
Internals - use negative indexes in arrays and Strings
Fix - handle TPave NDC position also when fInit is not
set
Fix - properly handle image sizes in svg2pdf
Fix - drawing TPaveText with zero text size
Fix - correct axis range in TScatter drawing
Fix - use draw option also for graph drawing in
TTree::Draw
Jupyter lab
Use JSROOT 7.9.0 as fallback version.
The tutorials have been reviewed, improved and modernised. It is now
more intuitive to navigate through the individual parts of the ROOT
tutorials. Some tutorials were added to showcase the new features, some
were modernized to modern C++ standards and some were moved to the
legacy folder.
Build,
Configuration and Testing Infrastructure
New
build options for dependiencies of image processing
ROOT supports image processing via libAfterImage, which
can be enabled with the asimage build option. A few more
options were added to make ROOT builds more reproducible and to avoid
builtin dependencies:
asimage_tiff (default ON): build
libAfterImage with TIFF support if libtiff is
found on the system
builtin_gif (default OFF): don’t look for
libgif on the system and instead build it together with
ROOT
builtin_jpeg (default OFF): same as above
but for libjpeg
builtin_png (default OFF): same as above
but for libpng
With default build option values, there is no difference in behavior
compared to previous ROOT versions. The real benefit of the new options
becomes apparent in builds with fail-on-missing=ON, because
then the build will fail if any of the dependencies is not found.
Bugs and Issues fixed in
this release
More than 200 items were addressed for this release. The full list
is:
[#18827] -
ROOT uses the wrong value for Planck’s constant